Skip to content

Commit

Permalink
Merge branch 'main' into oauth-client-type
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny authored Oct 23, 2022
2 parents 8290420 + 4eeea7b commit 8ba4b5e
Show file tree
Hide file tree
Showing 16 changed files with 204 additions and 54 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
code.gitea.io/gitea-vet v0.2.2-0.20220122151748-48ebc902541b
code.gitea.io/sdk/gitea v0.15.1
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681
gitea.com/go-chi/cache v0.2.0
gitea.com/go-chi/captcha v0.0.0-20211013065431-70641c1a35d5
gitea.com/go-chi/session v0.0.0-20211218221615-e3605d8b28b8
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcig
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb h1:Yy0Bxzc8R2wxiwXoG/rECGplJUSpXqCsog9PuJFgiHs=
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681 h1:MMSPgnVULVwV9kEBgvyEUhC9v/uviZ55hPJEMjpbNR4=
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
gitea.com/go-chi/cache v0.2.0 h1:E0npuTfDW6CT1yD8NMDVc1SK6IeRjfmRL2zlEsCEd7w=
gitea.com/go-chi/cache v0.2.0/go.mod h1:iQlVK2aKTZ/rE9UcHyz9pQWGvdP9i1eI2spOpzgCrtE=
Expand Down
19 changes: 17 additions & 2 deletions models/packages/container/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ type ImageTagsSearchOptions struct {
PackageID int64
Query string
IsTagged bool
Sort packages.VersionSort
db.Paginator
}

Expand Down Expand Up @@ -195,12 +196,26 @@ func (opts *ImageTagsSearchOptions) toConds() builder.Cond {
return cond
}

func (opts *ImageTagsSearchOptions) configureOrderBy(e db.Engine) {
switch opts.Sort {
case packages.SortVersionDesc:
e.Desc("package_version.version")
case packages.SortVersionAsc:
e.Asc("package_version.version")
case packages.SortCreatedAsc:
e.Asc("package_version.created_unix")
default:
e.Desc("package_version.created_unix")
}
}

// SearchImageTags gets a sorted list of the tags of an image
func SearchImageTags(ctx context.Context, opts *ImageTagsSearchOptions) ([]*packages.PackageVersion, int64, error) {
sess := db.GetEngine(ctx).
Join("INNER", "package", "package.id = package_version.package_id").
Where(opts.toConds()).
Desc("package_version.created_unix")
Where(opts.toConds())

opts.configureOrderBy(sess)

if opts.Paginator != nil {
sess = db.SetSessionPagination(sess, opts)
Expand Down
23 changes: 17 additions & 6 deletions models/packages/package_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,17 @@ type SearchValue struct {
ExactMatch bool
}

type VersionSort = string

const (
SortNameAsc VersionSort = "name_asc"
SortNameDesc VersionSort = "name_desc"
SortVersionAsc VersionSort = "version_asc"
SortVersionDesc VersionSort = "version_desc"
SortCreatedAsc VersionSort = "created_asc"
SortCreatedDesc VersionSort = "created_desc"
)

// PackageSearchOptions are options for SearchXXX methods
// Besides IsInternal are all fields optional and are not used if they have their default value (nil, "", 0)
type PackageSearchOptions struct {
Expand All @@ -176,7 +187,7 @@ type PackageSearchOptions struct {
IsInternal util.OptionalBool
HasFileWithName string // only results are found which are associated with a file with the specific name
HasFiles util.OptionalBool // only results are found which have associated files
Sort string
Sort VersionSort
db.Paginator
}

Expand Down Expand Up @@ -254,15 +265,15 @@ func (opts *PackageSearchOptions) toConds() builder.Cond {

func (opts *PackageSearchOptions) configureOrderBy(e db.Engine) {
switch opts.Sort {
case "alphabetically":
case SortNameAsc:
e.Asc("package.name")
case "reversealphabetically":
case SortNameDesc:
e.Desc("package.name")
case "highestversion":
case SortVersionDesc:
e.Desc("package_version.version")
case "lowestversion":
case SortVersionAsc:
e.Asc("package_version.version")
case "oldest":
case SortCreatedAsc:
e.Asc("package_version.created_unix")
default:
e.Desc("package_version.created_unix")
Expand Down
4 changes: 4 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ never = Never

rss_feed = RSS Feed

[filter]
string.asc = A - Z
string.desc = Z - A

[error]
occurred = An error occurred
report_message = If you are sure this is a Gitea bug, please search for issues on <a href="https://github.com/go-gitea/gitea/issues" target="_blank">GitHub</a> or open a new issue if necessary.
Expand Down
29 changes: 29 additions & 0 deletions routers/web/auth/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const (
// TODO move error and responses to SDK or models

// AuthorizeErrorCode represents an error code specified in RFC 6749
// https://datatracker.ietf.org/doc/html/rfc6749#section-4.2.2.1
type AuthorizeErrorCode string

const (
Expand All @@ -68,6 +69,7 @@ const (
)

// AuthorizeError represents an error type specified in RFC 6749
// https://datatracker.ietf.org/doc/html/rfc6749#section-4.2.2.1
type AuthorizeError struct {
ErrorCode AuthorizeErrorCode `json:"error" form:"error"`
ErrorDescription string
Expand All @@ -80,6 +82,7 @@ func (err AuthorizeError) Error() string {
}

// AccessTokenErrorCode represents an error code specified in RFC 6749
// https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
type AccessTokenErrorCode string

const (
Expand All @@ -98,6 +101,7 @@ const (
)

// AccessTokenError represents an error response specified in RFC 6749
// https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
type AccessTokenError struct {
ErrorCode AccessTokenErrorCode `json:"error" form:"error"`
ErrorDescription string `json:"error_description"`
Expand Down Expand Up @@ -129,6 +133,7 @@ const (
)

// AccessTokenResponse represents a successful access token response
// https://datatracker.ietf.org/doc/html/rfc6749#section-4.2.2
type AccessTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType TokenType `json:"token_type"`
Expand Down Expand Up @@ -676,6 +681,30 @@ func AccessTokenOAuth(ctx *context.Context) {
}

func handleRefreshToken(ctx *context.Context, form forms.AccessTokenForm, serverKey, clientKey oauth2.JWTSigningKey) {
app, err := auth.GetOAuth2ApplicationByClientID(ctx, form.ClientID)
if err != nil {
handleAccessTokenError(ctx, AccessTokenError{
ErrorCode: AccessTokenErrorCodeInvalidClient,
ErrorDescription: fmt.Sprintf("cannot load client with client id: %q", form.ClientID),
})
return
}
// "The authorization server MUST ... require client authentication for confidential clients"
// https://datatracker.ietf.org/doc/html/rfc6749#section-6
if !app.ValidateClientSecret([]byte(form.ClientSecret)) {
errorDescription := "invalid client secret"
if form.ClientSecret == "" {
errorDescription = "invalid empty client secret"
}
// "invalid_client ... Client authentication failed"
// https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
handleAccessTokenError(ctx, AccessTokenError{
ErrorCode: AccessTokenErrorCodeInvalidClient,
ErrorDescription: errorDescription,
})
return
}

token, err := oauth2.ParseToken(form.RefreshToken, serverKey)
if err != nil {
handleAccessTokenError(ctx, AccessTokenError{
Expand Down
7 changes: 6 additions & 1 deletion routers/web/user/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ func ListPackageVersions(ctx *context.Context) {
}

query := ctx.FormTrim("q")
sort := ctx.FormTrim("sort")

ctx.Data["Title"] = ctx.Tr("packages.title")
ctx.Data["IsPackagesPage"] = true
Expand All @@ -243,9 +244,11 @@ func ListPackageVersions(ctx *context.Context) {
Owner: ctx.Package.Owner,
}
ctx.Data["Query"] = query
ctx.Data["Sort"] = sort

pagerParams := map[string]string{
"q": query,
"q": query,
"sort": sort,
}

var (
Expand All @@ -264,6 +267,7 @@ func ListPackageVersions(ctx *context.Context) {
PackageID: p.ID,
Query: query,
IsTagged: tagged == "" || tagged == "tagged",
Sort: sort,
})
if err != nil {
ctx.ServerError("SearchImageTags", err)
Expand All @@ -278,6 +282,7 @@ func ListPackageVersions(ctx *context.Context) {
Value: query,
},
IsInternal: util.OptionalBoolFalse,
Sort: sort,
})
if err != nil {
ctx.ServerError("SearchVersions", err)
Expand Down
20 changes: 12 additions & 8 deletions services/markup/processorhelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,26 @@ import (
"context"

"code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup"
)

func ProcessorHelper() *markup.ProcessorHelper {
return &markup.ProcessorHelper{
IsUsernameMentionable: func(ctx context.Context, username string) bool {
// TODO: cast ctx to modules/context.Context and use IsUserVisibleToViewer

// Only link if the user actually exists
userExists, err := user.IsUserExist(ctx, 0, username)
mentionedUser, err := user.GetUserByName(ctx, username)
if err != nil {
log.Error("Failed to validate user in mention %q exists, assuming it does", username)
userExists = true
return false
}

giteaCtx, ok := ctx.(*gitea_context.Context)
if !ok {
// when using general context, use user's visibility to check
return mentionedUser.Visibility.IsPublic()
}
return userExists

// when using gitea context (web context), use user's visibility and user's permission to check
return user.IsUserVisibleToViewer(giteaCtx, mentionedUser, giteaCtx.Doer)
},
}
}
37 changes: 35 additions & 2 deletions services/markup/processorhelper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,48 @@ package markup

import (
"context"
"net/http"
"testing"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/models/user"
gitea_context "code.gitea.io/gitea/modules/context"

"github.com/stretchr/testify/assert"
)

func TestProcessorHelper(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
assert.True(t, ProcessorHelper().IsUsernameMentionable(context.Background(), "user10"))
assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), "no-such-user"))

userPublic := "user1"
userPrivate := "user31"
userLimited := "user33"
userNoSuch := "no-such-user"

unittest.AssertCount(t, &user.User{Name: userPublic}, 1)
unittest.AssertCount(t, &user.User{Name: userPrivate}, 1)
unittest.AssertCount(t, &user.User{Name: userLimited}, 1)
unittest.AssertCount(t, &user.User{Name: userNoSuch}, 0)

// when using general context, use user's visibility to check
assert.True(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userPublic))
assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userLimited))
assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userPrivate))
assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userNoSuch))

// when using web context, use user.IsUserVisibleToViewer to check
var err error
giteaCtx := &gitea_context.Context{}
giteaCtx.Req, err = http.NewRequest("GET", "/", nil)
assert.NoError(t, err)

giteaCtx.Doer = nil
assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPublic))
assert.False(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPrivate))

giteaCtx.Doer, err = user.GetUserByName(db.DefaultContext, userPrivate)
assert.NoError(t, err)
assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPublic))
assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPrivate))
}
12 changes: 6 additions & 6 deletions templates/admin/packages/list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,20 @@
<th>ID</th>
<th>{{.locale.Tr "admin.packages.owner"}}</th>
<th>{{.locale.Tr "admin.packages.type"}}</th>
<th data-sortt-asc="alphabetically" data-sortt-desc="reversealphabetically">
<th data-sortt-asc="name_asc" data-sortt-desc="name_desc">
{{.locale.Tr "admin.packages.name"}}
{{SortArrow "alphabetically" "reversealphabetically" .SortType false}}
{{SortArrow "name_asc" "name_desc" .SortType false}}
</th>
<th data-sortt-asc="highestversion" data-sortt-desc="lowestversion">
<th data-sortt-asc="version_desc" data-sortt-desc="version_asc">
{{.locale.Tr "admin.packages.version"}}
{{SortArrow "highestversion" "lowestversion" .SortType false}}
{{SortArrow "version_desc" "version_asc" .SortType false}}
</th>
<th>{{.locale.Tr "admin.packages.creator"}}</th>
<th>{{.locale.Tr "admin.packages.repository"}}</th>
<th>{{.locale.Tr "admin.packages.size"}}</th>
<th data-sortt-asc="oldest" data-sortt-desc="newest">
<th data-sortt-asc="created_asc" data-sortt-desc="created_desc">
{{.locale.Tr "admin.packages.published"}}
{{SortArrow "oldest" "newest" .SortType true}}
{{SortArrow "created_asc" "created_desc" .SortType true}}
</th>
<th>{{.locale.Tr "admin.notices.op"}}</th>
</tr>
Expand Down
10 changes: 8 additions & 2 deletions templates/package/shared/versionlist.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
<form class="ui form ignore-dirty">
<div class="ui fluid action input">
<input name="q" value="{{.Query}}" placeholder="{{.locale.Tr "explore.search"}}..." autofocus>
<select class="ui dropdown" name="sort">
<option value="version_asc"{{if eq .Sort "version_asc"}} selected="selected"{{end}}>{{.locale.Tr "filter.string.asc"}}</option>
<option value="version_desc"{{if eq .Sort "version_desc"}} selected="selected"{{end}}>{{.locale.Tr "filter.string.desc"}}</option>
<option value="created_asc"{{if eq .Sort "created_asc"}} selected="selected"{{end}}>{{.locale.Tr "repo.issues.filter_sort.oldest"}}</option>
<option value="created_desc"{{if or (eq .Sort "") (eq .Sort "created_desc")}} selected="selected"{{end}}>{{.locale.Tr "repo.issues.filter_sort.latest"}}</option>
</select>
{{if eq .PackageDescriptor.Package.Type "container"}}
<select class="ui dropdown" name="tagged">
{{$isTagged := or (eq .Tagged "") (eq .Tagged "tagged")}}
<option value="tagged" {{if $isTagged}}selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.tagged"}}</option>
<option value="untagged" {{if not $isTagged}}selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.untagged"}}</option>
<option value="tagged"{{if $isTagged}} selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.tagged"}}</option>
<option value="untagged"{{if not $isTagged}} selected="selected"{{end}}>{{.locale.Tr "packages.filter.container.untagged"}}</option>
</select>
{{end}}
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
Expand Down
Loading

0 comments on commit 8ba4b5e

Please sign in to comment.