mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-07 00:01:40 -04:00
Compare commits
11 Commits
3510d7e33a
...
7ddc11def7
Author | SHA1 | Date | |
---|---|---|---|
|
7ddc11def7 | ||
|
d9f748a700 | ||
|
de484e86bc | ||
|
db2286bbb6 | ||
|
60c4725cc2 | ||
|
0a6b57bcaf | ||
|
51951d4503 | ||
|
7a0f2fb1dc | ||
|
21c91b7dff | ||
|
e763fab685 | ||
|
9edf80f472 |
41
CHANGELOG.md
41
CHANGELOG.md
@ -4,6 +4,47 @@ 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.18.1](https://github.com/go-gitea/gitea/releases/tag/v1.18.1) - 2023-01-17
|
||||
|
||||
* API
|
||||
* Add `sync_on_commit` option for push mirrors api (#22271) (#22292)
|
||||
* BUGFIXES
|
||||
* Update `github.com/zeripath/zapx/v15` (#22485)
|
||||
* Fix pull request API field `closed_at` always being `null` (#22482) (#22483)
|
||||
* Fix container blob mount (#22226) (#22476)
|
||||
* Fix error when calculating repository size (#22392) (#22474)
|
||||
* Fix Operator does not exist bug on explore page with ONLY_SHOW_RELEVANT_REPOS (#22454) (#22472)
|
||||
* Fix environments for KaTeX and error reporting (#22453) (#22473)
|
||||
* Remove the netgo tag for Windows build (#22467) (#22468)
|
||||
* Fix migration from GitBucket (#22477) (#22465)
|
||||
* Prevent panic on looking at api "git" endpoints for empty repos (#22457) (#22458)
|
||||
* Fix PR status layout on mobile (#21547) (#22441)
|
||||
* Fix wechatwork webhook sends empty content in PR review (#21762) (#22440)
|
||||
* Remove duplicate "Actions" label in mobile view (#21974) (#22439)
|
||||
* Fix leaving organization bug on user settings -> orgs (#21983) (#22438)
|
||||
* Fixed colour transparency regex matching in project board sorting (#22092) (#22437)
|
||||
* Correctly handle select on multiple channels in Queues (#22146) (#22428)
|
||||
* Prepend refs/heads/ to issue template refs (#20461) (#22427)
|
||||
* Restore function to "Show more" buttons (#22399) (#22426)
|
||||
* Continue GCing other repos on error in one repo (#22422) (#22425)
|
||||
* Allow HOST has no port (#22280) (#22409)
|
||||
* Fix omit avatar_url in discord payload when empty (#22393) (#22394)
|
||||
* Don't display stop watch top bar icon when disabled and hidden when click other place (#22374) (#22387)
|
||||
* Don't lookup mail server when using sendmail (#22300) (#22383)
|
||||
* Fix gravatar disable bug (#22337)
|
||||
* Fix update settings table on install (#22326) (#22327)
|
||||
* Fix sitemap (#22272) (#22320)
|
||||
* Fix code search title translation (#22285) (#22316)
|
||||
* Fix due date rendering the wrong date in issue (#22302) (#22306)
|
||||
* Fix get system setting bug when enabled redis cache (#22298)
|
||||
* Fix bug of DisableGravatar default value (#22297)
|
||||
* Fix key signature error page (#22229) (#22230)
|
||||
* TESTING
|
||||
* Remove test session cache to reduce possible concurrent problem (#22199) (#22429)
|
||||
* MISC
|
||||
* Restore previous official review when an official review is deleted (#22449) (#22460)
|
||||
* Log STDERR of external renderer when it fails (#22442) (#22444)
|
||||
|
||||
## [1.18.0](https://github.com/go-gitea/gitea/releases/tag/v1.18.0) - 2022-12-29
|
||||
|
||||
* SECURITY
|
||||
|
@ -29,7 +29,7 @@ local addIssueLabelsOverrides(labels) =
|
||||
|
||||
grafanaDashboards+:: {
|
||||
|
||||
local giteaSelector = 'job="$job", instance="$instance"',
|
||||
local giteaSelector = 'job=~"$job", instance=~"$instance"',
|
||||
local giteaStatsPanel =
|
||||
grafana.statPanel.new(
|
||||
'Gitea stats',
|
||||
@ -399,25 +399,31 @@ local addIssueLabelsOverrides(labels) =
|
||||
.addTemplate(
|
||||
{
|
||||
hide: 0,
|
||||
label: null,
|
||||
label: 'job',
|
||||
name: 'job',
|
||||
options: [],
|
||||
datasource: '$datasource',
|
||||
query: 'label_values(gitea_organizations, job)',
|
||||
refresh: 1,
|
||||
regex: '',
|
||||
type: 'query',
|
||||
multi: true,
|
||||
allValue: '.+'
|
||||
},
|
||||
)
|
||||
.addTemplate(
|
||||
{
|
||||
hide: 0,
|
||||
label: null,
|
||||
label: 'instance',
|
||||
name: 'instance',
|
||||
options: [],
|
||||
datasource: '$datasource',
|
||||
query: 'label_values(gitea_organizations{job="$job"}, instance)',
|
||||
refresh: 1,
|
||||
regex: '',
|
||||
type: 'query',
|
||||
multi: true,
|
||||
allValue: '.+'
|
||||
},
|
||||
)
|
||||
.addTemplate(
|
||||
|
@ -18,7 +18,7 @@ params:
|
||||
description: Git with a cup of tea
|
||||
author: The Gitea Authors
|
||||
website: https://docs.gitea.io
|
||||
version: 1.18.0
|
||||
version: 1.18.1
|
||||
minGoVersion: 1.18
|
||||
goVersion: 1.19
|
||||
minNodeVersion: 16
|
||||
|
@ -42,7 +42,41 @@ To use the Authorization Code Grant as a third party application it is required
|
||||
|
||||
## Scopes
|
||||
|
||||
Currently Gitea does not support scopes (see [#4300](https://github.com/go-gitea/gitea/issues/4300)) and all third party applications will be granted access to all resources of the user and their organizations.
|
||||
Gitea supports the following scopes for tokens:
|
||||
|
||||
| Name | Description |
|
||||
| ---- | ----------- |
|
||||
| **(no scope)** | Grants read-only access to public user profile and public repositories. |
|
||||
| **repo** | Full control over all repositories. |
|
||||
| **repo:status** | Grants read/write access to commit status in all repositories. |
|
||||
| **public_repo** | Grants read/write access to public repositories only. |
|
||||
| **admin:repo_hook** | Grants access to repository hooks of all repositories. This is included in the `repo` scope. |
|
||||
| **write:repo_hook** | Grants read/write access to repository hooks |
|
||||
| **read:repo_hook** | Grants read-only access to repository hooks |
|
||||
| **admin:org** | Grants full access to organization settings |
|
||||
| **write:org** | Grants read/write access to organization settings |
|
||||
| **read:org** | Grants read-only access to organization settings |
|
||||
| **admin:public_key** | Grants full access for managing public keys |
|
||||
| **write:public_key** | Grant read/write access to public keys |
|
||||
| **read:public_key** | Grant read-only access to public keys |
|
||||
| **admin:org_hook** | Grants full access to organizational-level hooks |
|
||||
| **notification** | Grants full access to notifications |
|
||||
| **user** | Grants full access to user profile info |
|
||||
| **read:user** | Grants read access to user's profile |
|
||||
| **user:email** | Grants read access to user's email addresses |
|
||||
| **user:follow** | Grants access to follow/un-follow a user |
|
||||
| **delete_repo** | Grants access to delete repositories as an admin |
|
||||
| **package** | Grants full access to hosted packages |
|
||||
| **write:package** | Grants read/write access to packages |
|
||||
| **read:package** | Grants read access to packages |
|
||||
| **delete:package** | Grants delete access to packages |
|
||||
| **admin:gpg_key** | Grants full access for managing GPG keys |
|
||||
| **write:gpg_key** | Grants read/write access to GPG keys |
|
||||
| **read:gpg_key** | Grants read-only access to GPG keys |
|
||||
| **admin:application** | Grants full access to manage applications |
|
||||
| **write:application** | Grants read/write access for managing applications |
|
||||
| **read:application** | Grants read access for managing applications |
|
||||
| **sudo** | Allows to perform actions as the site admin. |
|
||||
|
||||
## Client types
|
||||
|
||||
|
@ -138,6 +138,8 @@ For more information, refer to Gitea's [API docs]({{< relref "doc/developers/api
|
||||
|
||||
You can see the latest API (for example) on <https://try.gitea.io/api/swagger>.
|
||||
|
||||
You can also see an example of the `swagger.json` file at <https://try.gitea.io/swagger.v1.json>.
|
||||
|
||||
## Adjusting your server for public/private use
|
||||
|
||||
### Preventing spammers
|
||||
|
1
main.go
1
main.go
@ -17,6 +17,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
// register supported doc types
|
||||
_ "code.gitea.io/gitea/modules/markup/asciicast"
|
||||
_ "code.gitea.io/gitea/modules/markup/console"
|
||||
_ "code.gitea.io/gitea/modules/markup/csv"
|
||||
_ "code.gitea.io/gitea/modules/markup/markdown"
|
||||
|
@ -65,6 +65,7 @@ type AccessToken struct {
|
||||
TokenHash string `xorm:"UNIQUE"` // sha256 of token
|
||||
TokenSalt string
|
||||
TokenLastEight string `xorm:"INDEX token_last_eight"`
|
||||
Scope AccessTokenScope
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
|
251
models/auth/token_scope.go
Normal file
251
models/auth/token_scope.go
Normal file
@ -0,0 +1,251 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AccessTokenScope represents the scope for an access token.
|
||||
type AccessTokenScope string
|
||||
|
||||
const (
|
||||
AccessTokenScopeAll AccessTokenScope = "all"
|
||||
|
||||
AccessTokenScopeRepo AccessTokenScope = "repo"
|
||||
AccessTokenScopeRepoStatus AccessTokenScope = "repo:status"
|
||||
AccessTokenScopePublicRepo AccessTokenScope = "public_repo"
|
||||
|
||||
AccessTokenScopeAdminOrg AccessTokenScope = "admin:org"
|
||||
AccessTokenScopeWriteOrg AccessTokenScope = "write:org"
|
||||
AccessTokenScopeReadOrg AccessTokenScope = "read:org"
|
||||
|
||||
AccessTokenScopeAdminPublicKey AccessTokenScope = "admin:public_key"
|
||||
AccessTokenScopeWritePublicKey AccessTokenScope = "write:public_key"
|
||||
AccessTokenScopeReadPublicKey AccessTokenScope = "read:public_key"
|
||||
|
||||
AccessTokenScopeAdminRepoHook AccessTokenScope = "admin:repo_hook"
|
||||
AccessTokenScopeWriteRepoHook AccessTokenScope = "write:repo_hook"
|
||||
AccessTokenScopeReadRepoHook AccessTokenScope = "read:repo_hook"
|
||||
|
||||
AccessTokenScopeAdminOrgHook AccessTokenScope = "admin:org_hook"
|
||||
|
||||
AccessTokenScopeNotification AccessTokenScope = "notification"
|
||||
|
||||
AccessTokenScopeUser AccessTokenScope = "user"
|
||||
AccessTokenScopeReadUser AccessTokenScope = "read:user"
|
||||
AccessTokenScopeUserEmail AccessTokenScope = "user:email"
|
||||
AccessTokenScopeUserFollow AccessTokenScope = "user:follow"
|
||||
|
||||
AccessTokenScopeDeleteRepo AccessTokenScope = "delete_repo"
|
||||
|
||||
AccessTokenScopePackage AccessTokenScope = "package"
|
||||
AccessTokenScopeWritePackage AccessTokenScope = "write:package"
|
||||
AccessTokenScopeReadPackage AccessTokenScope = "read:package"
|
||||
AccessTokenScopeDeletePackage AccessTokenScope = "delete:package"
|
||||
|
||||
AccessTokenScopeAdminGPGKey AccessTokenScope = "admin:gpg_key"
|
||||
AccessTokenScopeWriteGPGKey AccessTokenScope = "write:gpg_key"
|
||||
AccessTokenScopeReadGPGKey AccessTokenScope = "read:gpg_key"
|
||||
|
||||
AccessTokenScopeAdminApplication AccessTokenScope = "admin:application"
|
||||
AccessTokenScopeWriteApplication AccessTokenScope = "write:application"
|
||||
AccessTokenScopeReadApplication AccessTokenScope = "read:application"
|
||||
|
||||
AccessTokenScopeSudo AccessTokenScope = "sudo"
|
||||
)
|
||||
|
||||
// AccessTokenScopeBitmap represents a bitmap of access token scopes.
|
||||
type AccessTokenScopeBitmap uint64
|
||||
|
||||
// Bitmap of each scope, including the child scopes.
|
||||
const (
|
||||
// AccessTokenScopeAllBits is the bitmap of all access token scopes, except `sudo`.
|
||||
AccessTokenScopeAllBits AccessTokenScopeBitmap = AccessTokenScopeRepoBits |
|
||||
AccessTokenScopeAdminOrgBits | AccessTokenScopeAdminPublicKeyBits | AccessTokenScopeAdminOrgHookBits |
|
||||
AccessTokenScopeNotificationBits | AccessTokenScopeUserBits | AccessTokenScopeDeleteRepoBits |
|
||||
AccessTokenScopePackageBits | AccessTokenScopeAdminGPGKeyBits | AccessTokenScopeAdminApplicationBits
|
||||
|
||||
AccessTokenScopeRepoBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeRepoStatusBits | AccessTokenScopePublicRepoBits | AccessTokenScopeAdminRepoHookBits
|
||||
AccessTokenScopeRepoStatusBits AccessTokenScopeBitmap = 1 << iota
|
||||
AccessTokenScopePublicRepoBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeAdminOrgBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWriteOrgBits
|
||||
AccessTokenScopeWriteOrgBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadOrgBits
|
||||
AccessTokenScopeReadOrgBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeAdminPublicKeyBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWritePublicKeyBits
|
||||
AccessTokenScopeWritePublicKeyBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadPublicKeyBits
|
||||
AccessTokenScopeReadPublicKeyBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeAdminRepoHookBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWriteRepoHookBits
|
||||
AccessTokenScopeWriteRepoHookBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadRepoHookBits
|
||||
AccessTokenScopeReadRepoHookBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeAdminOrgHookBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeNotificationBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeUserBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadUserBits | AccessTokenScopeUserEmailBits | AccessTokenScopeUserFollowBits
|
||||
AccessTokenScopeReadUserBits AccessTokenScopeBitmap = 1 << iota
|
||||
AccessTokenScopeUserEmailBits AccessTokenScopeBitmap = 1 << iota
|
||||
AccessTokenScopeUserFollowBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeDeleteRepoBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopePackageBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWritePackageBits | AccessTokenScopeDeletePackageBits
|
||||
AccessTokenScopeWritePackageBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadPackageBits
|
||||
AccessTokenScopeReadPackageBits AccessTokenScopeBitmap = 1 << iota
|
||||
AccessTokenScopeDeletePackageBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeAdminGPGKeyBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWriteGPGKeyBits
|
||||
AccessTokenScopeWriteGPGKeyBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadGPGKeyBits
|
||||
AccessTokenScopeReadGPGKeyBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeAdminApplicationBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWriteApplicationBits
|
||||
AccessTokenScopeWriteApplicationBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadApplicationBits
|
||||
AccessTokenScopeReadApplicationBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
AccessTokenScopeSudoBits AccessTokenScopeBitmap = 1 << iota
|
||||
|
||||
// The current implementation only supports up to 64 token scopes.
|
||||
// If we need to support > 64 scopes,
|
||||
// refactoring the whole implementation in this file (and only this file) is needed.
|
||||
)
|
||||
|
||||
// allAccessTokenScopes contains all access token scopes.
|
||||
// The order is important: parent scope must precedes child scopes.
|
||||
var allAccessTokenScopes = []AccessTokenScope{
|
||||
AccessTokenScopeRepo, AccessTokenScopeRepoStatus, AccessTokenScopePublicRepo,
|
||||
AccessTokenScopeAdminOrg, AccessTokenScopeWriteOrg, AccessTokenScopeReadOrg,
|
||||
AccessTokenScopeAdminPublicKey, AccessTokenScopeWritePublicKey, AccessTokenScopeReadPublicKey,
|
||||
AccessTokenScopeAdminRepoHook, AccessTokenScopeWriteRepoHook, AccessTokenScopeReadRepoHook,
|
||||
AccessTokenScopeAdminOrgHook,
|
||||
AccessTokenScopeNotification,
|
||||
AccessTokenScopeUser, AccessTokenScopeReadUser, AccessTokenScopeUserEmail, AccessTokenScopeUserFollow,
|
||||
AccessTokenScopeDeleteRepo,
|
||||
AccessTokenScopePackage, AccessTokenScopeWritePackage, AccessTokenScopeReadPackage, AccessTokenScopeDeletePackage,
|
||||
AccessTokenScopeAdminGPGKey, AccessTokenScopeWriteGPGKey, AccessTokenScopeReadGPGKey,
|
||||
AccessTokenScopeAdminApplication, AccessTokenScopeWriteApplication, AccessTokenScopeReadApplication,
|
||||
AccessTokenScopeSudo,
|
||||
}
|
||||
|
||||
// allAccessTokenScopeBits contains all access token scopes.
|
||||
var allAccessTokenScopeBits = map[AccessTokenScope]AccessTokenScopeBitmap{
|
||||
AccessTokenScopeRepo: AccessTokenScopeRepoBits,
|
||||
AccessTokenScopeRepoStatus: AccessTokenScopeRepoStatusBits,
|
||||
AccessTokenScopePublicRepo: AccessTokenScopePublicRepoBits,
|
||||
AccessTokenScopeAdminOrg: AccessTokenScopeAdminOrgBits,
|
||||
AccessTokenScopeWriteOrg: AccessTokenScopeWriteOrgBits,
|
||||
AccessTokenScopeReadOrg: AccessTokenScopeReadOrgBits,
|
||||
AccessTokenScopeAdminPublicKey: AccessTokenScopeAdminPublicKeyBits,
|
||||
AccessTokenScopeWritePublicKey: AccessTokenScopeWritePublicKeyBits,
|
||||
AccessTokenScopeReadPublicKey: AccessTokenScopeReadPublicKeyBits,
|
||||
AccessTokenScopeAdminRepoHook: AccessTokenScopeAdminRepoHookBits,
|
||||
AccessTokenScopeWriteRepoHook: AccessTokenScopeWriteRepoHookBits,
|
||||
AccessTokenScopeReadRepoHook: AccessTokenScopeReadRepoHookBits,
|
||||
AccessTokenScopeAdminOrgHook: AccessTokenScopeAdminOrgHookBits,
|
||||
AccessTokenScopeNotification: AccessTokenScopeNotificationBits,
|
||||
AccessTokenScopeUser: AccessTokenScopeUserBits,
|
||||
AccessTokenScopeReadUser: AccessTokenScopeReadUserBits,
|
||||
AccessTokenScopeUserEmail: AccessTokenScopeUserEmailBits,
|
||||
AccessTokenScopeUserFollow: AccessTokenScopeUserFollowBits,
|
||||
AccessTokenScopeDeleteRepo: AccessTokenScopeDeleteRepoBits,
|
||||
AccessTokenScopePackage: AccessTokenScopePackageBits,
|
||||
AccessTokenScopeWritePackage: AccessTokenScopeWritePackageBits,
|
||||
AccessTokenScopeReadPackage: AccessTokenScopeReadPackageBits,
|
||||
AccessTokenScopeDeletePackage: AccessTokenScopeDeletePackageBits,
|
||||
AccessTokenScopeAdminGPGKey: AccessTokenScopeAdminGPGKeyBits,
|
||||
AccessTokenScopeWriteGPGKey: AccessTokenScopeWriteGPGKeyBits,
|
||||
AccessTokenScopeReadGPGKey: AccessTokenScopeReadGPGKeyBits,
|
||||
AccessTokenScopeAdminApplication: AccessTokenScopeAdminApplicationBits,
|
||||
AccessTokenScopeWriteApplication: AccessTokenScopeWriteApplicationBits,
|
||||
AccessTokenScopeReadApplication: AccessTokenScopeReadApplicationBits,
|
||||
AccessTokenScopeSudo: AccessTokenScopeSudoBits,
|
||||
}
|
||||
|
||||
// Parse parses the scope string into a bitmap, thus removing possible duplicates.
|
||||
func (s AccessTokenScope) Parse() (AccessTokenScopeBitmap, error) {
|
||||
list := strings.Split(string(s), ",")
|
||||
|
||||
var bitmap AccessTokenScopeBitmap
|
||||
for _, v := range list {
|
||||
singleScope := AccessTokenScope(v)
|
||||
if singleScope == "" {
|
||||
continue
|
||||
}
|
||||
if singleScope == AccessTokenScopeAll {
|
||||
bitmap |= AccessTokenScopeAllBits
|
||||
continue
|
||||
}
|
||||
|
||||
bits, ok := allAccessTokenScopeBits[singleScope]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("invalid access token scope: %s", singleScope)
|
||||
}
|
||||
bitmap |= bits
|
||||
}
|
||||
return bitmap, nil
|
||||
}
|
||||
|
||||
// Normalize returns a normalized scope string without any duplicates.
|
||||
func (s AccessTokenScope) Normalize() (AccessTokenScope, error) {
|
||||
bitmap, err := s.Parse()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return bitmap.ToScope(), nil
|
||||
}
|
||||
|
||||
// HasScope returns true if the string has the given scope
|
||||
func (s AccessTokenScope) HasScope(scope AccessTokenScope) (bool, error) {
|
||||
bitmap, err := s.Parse()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return bitmap.HasScope(scope)
|
||||
}
|
||||
|
||||
// HasScope returns true if the string has the given scope
|
||||
func (bitmap AccessTokenScopeBitmap) HasScope(scope AccessTokenScope) (bool, error) {
|
||||
expectedBits, ok := allAccessTokenScopeBits[scope]
|
||||
if !ok {
|
||||
return false, fmt.Errorf("invalid access token scope: %s", scope)
|
||||
}
|
||||
|
||||
return bitmap&expectedBits == expectedBits, nil
|
||||
}
|
||||
|
||||
// ToScope returns a normalized scope string without any duplicates.
|
||||
func (bitmap AccessTokenScopeBitmap) ToScope() AccessTokenScope {
|
||||
var scopes []string
|
||||
|
||||
// iterate over all scopes, and reconstruct the bitmap
|
||||
// if the reconstructed bitmap doesn't change, then the scope is already included
|
||||
var reconstruct AccessTokenScopeBitmap
|
||||
|
||||
for _, singleScope := range allAccessTokenScopes {
|
||||
// no need for error checking here, since we know the scope is valid
|
||||
if ok, _ := bitmap.HasScope(singleScope); ok {
|
||||
current := reconstruct | allAccessTokenScopeBits[singleScope]
|
||||
if current == reconstruct {
|
||||
continue
|
||||
}
|
||||
|
||||
reconstruct = current
|
||||
scopes = append(scopes, string(singleScope))
|
||||
}
|
||||
}
|
||||
|
||||
scope := AccessTokenScope(strings.Join(scopes, ","))
|
||||
scope = AccessTokenScope(strings.ReplaceAll(
|
||||
string(scope),
|
||||
"repo,admin:org,admin:public_key,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application",
|
||||
"all",
|
||||
))
|
||||
return scope
|
||||
}
|
84
models/auth/token_scope_test.go
Normal file
84
models/auth/token_scope_test.go
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAccessTokenScope_Normalize(t *testing.T) {
|
||||
tests := []struct {
|
||||
in AccessTokenScope
|
||||
out AccessTokenScope
|
||||
err error
|
||||
}{
|
||||
{"", "", nil},
|
||||
{"repo", "repo", nil},
|
||||
{"repo,repo:status", "repo", nil},
|
||||
{"repo,public_repo", "repo", nil},
|
||||
{"admin:public_key,write:public_key", "admin:public_key", nil},
|
||||
{"admin:public_key,read:public_key", "admin:public_key", nil},
|
||||
{"write:public_key,read:public_key", "write:public_key", nil}, // read is include in write
|
||||
{"admin:repo_hook,write:repo_hook", "admin:repo_hook", nil},
|
||||
{"admin:repo_hook,read:repo_hook", "admin:repo_hook", nil},
|
||||
{"repo,admin:repo_hook,read:repo_hook", "repo", nil}, // admin:repo_hook is a child scope of repo
|
||||
{"repo,read:repo_hook", "repo", nil}, // read:repo_hook is a child scope of repo
|
||||
{"user", "user", nil},
|
||||
{"user,read:user", "user", nil},
|
||||
{"user,admin:org,write:org", "admin:org,user", nil},
|
||||
{"admin:org,write:org,user", "admin:org,user", nil},
|
||||
{"package", "package", nil},
|
||||
{"package,write:package", "package", nil},
|
||||
{"package,write:package,delete:package", "package", nil},
|
||||
{"write:package,read:package", "write:package", nil}, // read is include in write
|
||||
{"write:package,delete:package", "write:package,delete:package", nil}, // write and delete are not include in each other
|
||||
{"admin:gpg_key", "admin:gpg_key", nil},
|
||||
{"admin:gpg_key,write:gpg_key", "admin:gpg_key", nil},
|
||||
{"admin:gpg_key,write:gpg_key,user", "user,admin:gpg_key", nil},
|
||||
{"admin:application,write:application,user", "user,admin:application", nil},
|
||||
{"all", "all", nil},
|
||||
{"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application", "all", nil},
|
||||
{"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application,sudo", "all,sudo", nil},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(string(test.in), func(t *testing.T) {
|
||||
scope, err := test.in.Normalize()
|
||||
assert.Equal(t, test.out, scope)
|
||||
assert.Equal(t, test.err, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccessTokenScope_HasScope(t *testing.T) {
|
||||
tests := []struct {
|
||||
in AccessTokenScope
|
||||
scope AccessTokenScope
|
||||
out bool
|
||||
err error
|
||||
}{
|
||||
{"repo", "repo", true, nil},
|
||||
{"repo", "repo:status", true, nil},
|
||||
{"repo", "public_repo", true, nil},
|
||||
{"repo", "admin:org", false, nil},
|
||||
{"repo", "admin:public_key", false, nil},
|
||||
{"repo:status", "repo", false, nil},
|
||||
{"repo:status", "public_repo", false, nil},
|
||||
{"admin:org", "write:org", true, nil},
|
||||
{"admin:org", "read:org", true, nil},
|
||||
{"admin:org", "admin:org", true, nil},
|
||||
{"user", "read:user", true, nil},
|
||||
{"package", "write:package", true, nil},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(string(test.in), func(t *testing.T) {
|
||||
scope, err := test.in.HasScope(test.scope)
|
||||
assert.Equal(t, test.out, scope)
|
||||
assert.Equal(t, test.err, err)
|
||||
})
|
||||
}
|
||||
}
|
@ -4,8 +4,11 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
@ -18,6 +21,7 @@ const (
|
||||
type Paginator interface {
|
||||
GetSkipTake() (skip, take int)
|
||||
GetStartEnd() (start, end int)
|
||||
IsListAll() bool
|
||||
}
|
||||
|
||||
// GetPaginatedSession creates a paginated database session
|
||||
@ -44,9 +48,12 @@ func SetEnginePagination(e Engine, p Paginator) Engine {
|
||||
// ListOptions options to paginate results
|
||||
type ListOptions struct {
|
||||
PageSize int
|
||||
Page int // start from 1
|
||||
Page int // start from 1
|
||||
ListAll bool // if true, then PageSize and Page will not be taken
|
||||
}
|
||||
|
||||
var _ Paginator = &ListOptions{}
|
||||
|
||||
// GetSkipTake returns the skip and take values
|
||||
func (opts *ListOptions) GetSkipTake() (skip, take int) {
|
||||
opts.SetDefaultValues()
|
||||
@ -60,6 +67,11 @@ func (opts *ListOptions) GetStartEnd() (start, end int) {
|
||||
return start, end
|
||||
}
|
||||
|
||||
// IsListAll indicates PageSize and Page will be ignored
|
||||
func (opts *ListOptions) IsListAll() bool {
|
||||
return opts.ListAll
|
||||
}
|
||||
|
||||
// SetDefaultValues sets default values
|
||||
func (opts *ListOptions) SetDefaultValues() {
|
||||
if opts.PageSize <= 0 {
|
||||
@ -79,6 +91,8 @@ type AbsoluteListOptions struct {
|
||||
take int
|
||||
}
|
||||
|
||||
var _ Paginator = &AbsoluteListOptions{}
|
||||
|
||||
// NewAbsoluteListOptions creates a list option with applied limits
|
||||
func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
|
||||
if skip < 0 {
|
||||
@ -93,6 +107,11 @@ func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
|
||||
return &AbsoluteListOptions{skip, take}
|
||||
}
|
||||
|
||||
// IsListAll will always return false
|
||||
func (opts *AbsoluteListOptions) IsListAll() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// GetSkipTake returns the skip and take values
|
||||
func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
|
||||
return opts.skip, opts.take
|
||||
@ -102,3 +121,32 @@ func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
|
||||
func (opts *AbsoluteListOptions) GetStartEnd() (start, end int) {
|
||||
return opts.skip, opts.skip + opts.take
|
||||
}
|
||||
|
||||
// FindOptions represents a find options
|
||||
type FindOptions interface {
|
||||
Paginator
|
||||
ToConds() builder.Cond
|
||||
}
|
||||
|
||||
// Find represents a common find function which accept an options interface
|
||||
func Find[T any](ctx context.Context, opts FindOptions, objects *[]T) error {
|
||||
sess := GetEngine(ctx).Where(opts.ToConds())
|
||||
if !opts.IsListAll() {
|
||||
sess.Limit(opts.GetSkipTake())
|
||||
}
|
||||
return sess.Find(&objects)
|
||||
}
|
||||
|
||||
// Count represents a common count function which accept an options interface
|
||||
func Count[T any](ctx context.Context, opts FindOptions, object T) (int64, error) {
|
||||
return GetEngine(ctx).Where(opts.ToConds()).Count(object)
|
||||
}
|
||||
|
||||
// FindAndCount represents a common findandcount function which accept an options interface
|
||||
func FindAndCount[T any](ctx context.Context, opts FindOptions, objects *[]T) (int64, error) {
|
||||
sess := GetEngine(ctx).Where(opts.ToConds())
|
||||
if !opts.IsListAll() {
|
||||
sess.Limit(opts.GetSkipTake())
|
||||
}
|
||||
return sess.FindAndCount(&objects)
|
||||
}
|
||||
|
@ -8,9 +8,7 @@ package issues
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@ -22,8 +20,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/markdown"
|
||||
"code.gitea.io/gitea/modules/references"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
@ -687,31 +683,6 @@ func (c *Comment) LoadReview() error {
|
||||
return c.loadReview(db.DefaultContext)
|
||||
}
|
||||
|
||||
var notEnoughLines = regexp.MustCompile(`fatal: file .* has only \d+ lines?`)
|
||||
|
||||
func (c *Comment) checkInvalidation(doer *user_model.User, repo *git.Repository, branch string) error {
|
||||
// FIXME differentiate between previous and proposed line
|
||||
commit, err := repo.LineBlame(branch, repo.Path, c.TreePath, uint(c.UnsignedLine()))
|
||||
if err != nil && (strings.Contains(err.Error(), "fatal: no such path") || notEnoughLines.MatchString(err.Error())) {
|
||||
c.Invalidated = true
|
||||
return UpdateComment(c, doer)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.CommitSHA != "" && c.CommitSHA != commit.ID.String() {
|
||||
c.Invalidated = true
|
||||
return UpdateComment(c, doer)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckInvalidation checks if the line of code comment got changed by another commit.
|
||||
// If the line got changed the comment is going to be invalidated.
|
||||
func (c *Comment) CheckInvalidation(repo *git.Repository, doer *user_model.User, branch string) error {
|
||||
return c.checkInvalidation(doer, repo, branch)
|
||||
}
|
||||
|
||||
// DiffSide returns "previous" if Comment.Line is a LOC of the previous changes and "proposed" if it is a LOC of the proposed changes.
|
||||
func (c *Comment) DiffSide() string {
|
||||
if c.Line < 0 {
|
||||
@ -1008,23 +979,28 @@ func GetCommentByID(ctx context.Context, id int64) (*Comment, error) {
|
||||
// FindCommentsOptions describes the conditions to Find comments
|
||||
type FindCommentsOptions struct {
|
||||
db.ListOptions
|
||||
RepoID int64
|
||||
IssueID int64
|
||||
ReviewID int64
|
||||
Since int64
|
||||
Before int64
|
||||
Line int64
|
||||
TreePath string
|
||||
Type CommentType
|
||||
RepoID int64
|
||||
IssueID int64
|
||||
ReviewID int64
|
||||
Since int64
|
||||
Before int64
|
||||
Line int64
|
||||
TreePath string
|
||||
Type CommentType
|
||||
IssueIDs []int64
|
||||
Invalidated util.OptionalBool
|
||||
}
|
||||
|
||||
func (opts *FindCommentsOptions) toConds() builder.Cond {
|
||||
// ToConds implements FindOptions interface
|
||||
func (opts *FindCommentsOptions) ToConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.RepoID > 0 {
|
||||
cond = cond.And(builder.Eq{"issue.repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.IssueID > 0 {
|
||||
cond = cond.And(builder.Eq{"comment.issue_id": opts.IssueID})
|
||||
} else if len(opts.IssueIDs) > 0 {
|
||||
cond = cond.And(builder.In("comment.issue_id", opts.IssueIDs))
|
||||
}
|
||||
if opts.ReviewID > 0 {
|
||||
cond = cond.And(builder.Eq{"comment.review_id": opts.ReviewID})
|
||||
@ -1044,13 +1020,16 @@ func (opts *FindCommentsOptions) toConds() builder.Cond {
|
||||
if len(opts.TreePath) > 0 {
|
||||
cond = cond.And(builder.Eq{"comment.tree_path": opts.TreePath})
|
||||
}
|
||||
if !opts.Invalidated.IsNone() {
|
||||
cond = cond.And(builder.Eq{"comment.invalidated": opts.Invalidated.IsTrue()})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
// FindComments returns all comments according options
|
||||
func FindComments(ctx context.Context, opts *FindCommentsOptions) ([]*Comment, error) {
|
||||
comments := make([]*Comment, 0, 10)
|
||||
sess := db.GetEngine(ctx).Where(opts.toConds())
|
||||
sess := db.GetEngine(ctx).Where(opts.ToConds())
|
||||
if opts.RepoID > 0 {
|
||||
sess.Join("INNER", "issue", "issue.id = comment.issue_id")
|
||||
}
|
||||
@ -1069,13 +1048,19 @@ func FindComments(ctx context.Context, opts *FindCommentsOptions) ([]*Comment, e
|
||||
|
||||
// CountComments count all comments according options by ignoring pagination
|
||||
func CountComments(opts *FindCommentsOptions) (int64, error) {
|
||||
sess := db.GetEngine(db.DefaultContext).Where(opts.toConds())
|
||||
sess := db.GetEngine(db.DefaultContext).Where(opts.ToConds())
|
||||
if opts.RepoID > 0 {
|
||||
sess.Join("INNER", "issue", "issue.id = comment.issue_id")
|
||||
}
|
||||
return sess.Count(&Comment{})
|
||||
}
|
||||
|
||||
// UpdateCommentInvalidate updates comment invalidated column
|
||||
func UpdateCommentInvalidate(ctx context.Context, c *Comment) error {
|
||||
_, err := db.GetEngine(ctx).ID(c.ID).Cols("invalidated").Update(c)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateComment updates information of comment.
|
||||
func UpdateComment(c *Comment, doer *user_model.User) error {
|
||||
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||
@ -1134,120 +1119,6 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
|
||||
return DeleteReaction(ctx, &ReactionOptions{CommentID: comment.ID})
|
||||
}
|
||||
|
||||
// CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS
|
||||
type CodeComments map[string]map[int64][]*Comment
|
||||
|
||||
// FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line
|
||||
func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User) (CodeComments, error) {
|
||||
return fetchCodeCommentsByReview(ctx, issue, currentUser, nil)
|
||||
}
|
||||
|
||||
func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review) (CodeComments, error) {
|
||||
pathToLineToComment := make(CodeComments)
|
||||
if review == nil {
|
||||
review = &Review{ID: 0}
|
||||
}
|
||||
opts := FindCommentsOptions{
|
||||
Type: CommentTypeCode,
|
||||
IssueID: issue.ID,
|
||||
ReviewID: review.ID,
|
||||
}
|
||||
|
||||
comments, err := findCodeComments(ctx, opts, issue, currentUser, review)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, comment := range comments {
|
||||
if pathToLineToComment[comment.TreePath] == nil {
|
||||
pathToLineToComment[comment.TreePath] = make(map[int64][]*Comment)
|
||||
}
|
||||
pathToLineToComment[comment.TreePath][comment.Line] = append(pathToLineToComment[comment.TreePath][comment.Line], comment)
|
||||
}
|
||||
return pathToLineToComment, nil
|
||||
}
|
||||
|
||||
func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review) ([]*Comment, error) {
|
||||
var comments []*Comment
|
||||
if review == nil {
|
||||
review = &Review{ID: 0}
|
||||
}
|
||||
conds := opts.toConds()
|
||||
if review.ID == 0 {
|
||||
conds = conds.And(builder.Eq{"invalidated": false})
|
||||
}
|
||||
e := db.GetEngine(ctx)
|
||||
if err := e.Where(conds).
|
||||
Asc("comment.created_unix").
|
||||
Asc("comment.id").
|
||||
Find(&comments); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := issue.LoadRepo(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := CommentList(comments).LoadPosters(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find all reviews by ReviewID
|
||||
reviews := make(map[int64]*Review)
|
||||
ids := make([]int64, 0, len(comments))
|
||||
for _, comment := range comments {
|
||||
if comment.ReviewID != 0 {
|
||||
ids = append(ids, comment.ReviewID)
|
||||
}
|
||||
}
|
||||
if err := e.In("id", ids).Find(&reviews); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n := 0
|
||||
for _, comment := range comments {
|
||||
if re, ok := reviews[comment.ReviewID]; ok && re != nil {
|
||||
// If the review is pending only the author can see the comments (except if the review is set)
|
||||
if review.ID == 0 && re.Type == ReviewTypePending &&
|
||||
(currentUser == nil || currentUser.ID != re.ReviewerID) {
|
||||
continue
|
||||
}
|
||||
comment.Review = re
|
||||
}
|
||||
comments[n] = comment
|
||||
n++
|
||||
|
||||
if err := comment.LoadResolveDoer(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := comment.LoadReactions(issue.Repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
if comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
|
||||
Ctx: ctx,
|
||||
URLPrefix: issue.Repo.Link(),
|
||||
Metas: issue.Repo.ComposeMetas(),
|
||||
}, comment.Content); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return comments[:n], nil
|
||||
}
|
||||
|
||||
// FetchCodeCommentsByLine fetches the code comments for a given treePath and line number
|
||||
func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64) ([]*Comment, error) {
|
||||
opts := FindCommentsOptions{
|
||||
Type: CommentTypeCode,
|
||||
IssueID: issue.ID,
|
||||
TreePath: treePath,
|
||||
Line: line,
|
||||
}
|
||||
return findCodeComments(ctx, opts, issue, currentUser, nil)
|
||||
}
|
||||
|
||||
// UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id
|
||||
func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID string, posterID int64) error {
|
||||
_, err := db.GetEngine(db.DefaultContext).Table("comment").
|
||||
|
129
models/issues/comment_code.go
Normal file
129
models/issues/comment_code.go
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package issues
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/markdown"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
// CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS
|
||||
type CodeComments map[string]map[int64][]*Comment
|
||||
|
||||
// FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line
|
||||
func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User) (CodeComments, error) {
|
||||
return fetchCodeCommentsByReview(ctx, issue, currentUser, nil)
|
||||
}
|
||||
|
||||
func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review) (CodeComments, error) {
|
||||
pathToLineToComment := make(CodeComments)
|
||||
if review == nil {
|
||||
review = &Review{ID: 0}
|
||||
}
|
||||
opts := FindCommentsOptions{
|
||||
Type: CommentTypeCode,
|
||||
IssueID: issue.ID,
|
||||
ReviewID: review.ID,
|
||||
}
|
||||
|
||||
comments, err := findCodeComments(ctx, opts, issue, currentUser, review)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, comment := range comments {
|
||||
if pathToLineToComment[comment.TreePath] == nil {
|
||||
pathToLineToComment[comment.TreePath] = make(map[int64][]*Comment)
|
||||
}
|
||||
pathToLineToComment[comment.TreePath][comment.Line] = append(pathToLineToComment[comment.TreePath][comment.Line], comment)
|
||||
}
|
||||
return pathToLineToComment, nil
|
||||
}
|
||||
|
||||
func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review) ([]*Comment, error) {
|
||||
var comments []*Comment
|
||||
if review == nil {
|
||||
review = &Review{ID: 0}
|
||||
}
|
||||
conds := opts.ToConds()
|
||||
if review.ID == 0 {
|
||||
conds = conds.And(builder.Eq{"invalidated": false})
|
||||
}
|
||||
e := db.GetEngine(ctx)
|
||||
if err := e.Where(conds).
|
||||
Asc("comment.created_unix").
|
||||
Asc("comment.id").
|
||||
Find(&comments); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := issue.LoadRepo(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := CommentList(comments).LoadPosters(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find all reviews by ReviewID
|
||||
reviews := make(map[int64]*Review)
|
||||
ids := make([]int64, 0, len(comments))
|
||||
for _, comment := range comments {
|
||||
if comment.ReviewID != 0 {
|
||||
ids = append(ids, comment.ReviewID)
|
||||
}
|
||||
}
|
||||
if err := e.In("id", ids).Find(&reviews); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n := 0
|
||||
for _, comment := range comments {
|
||||
if re, ok := reviews[comment.ReviewID]; ok && re != nil {
|
||||
// If the review is pending only the author can see the comments (except if the review is set)
|
||||
if review.ID == 0 && re.Type == ReviewTypePending &&
|
||||
(currentUser == nil || currentUser.ID != re.ReviewerID) {
|
||||
continue
|
||||
}
|
||||
comment.Review = re
|
||||
}
|
||||
comments[n] = comment
|
||||
n++
|
||||
|
||||
if err := comment.LoadResolveDoer(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := comment.LoadReactions(issue.Repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
if comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
|
||||
Ctx: ctx,
|
||||
URLPrefix: issue.Repo.Link(),
|
||||
Metas: issue.Repo.ComposeMetas(),
|
||||
}, comment.Content); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return comments[:n], nil
|
||||
}
|
||||
|
||||
// FetchCodeCommentsByLine fetches the code comments for a given treePath and line number
|
||||
func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64) ([]*Comment, error) {
|
||||
opts := FindCommentsOptions{
|
||||
Type: CommentTypeCode,
|
||||
IssueID: issue.ID,
|
||||
TreePath: treePath,
|
||||
Line: line,
|
||||
}
|
||||
return findCodeComments(ctx, opts, issue, currentUser, nil)
|
||||
}
|
@ -12,7 +12,6 @@ import (
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"xorm.io/xorm"
|
||||
@ -161,7 +160,7 @@ func (prs PullRequestList) loadAttributes(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Load issues.
|
||||
issueIDs := prs.getIssueIDs()
|
||||
issueIDs := prs.GetIssueIDs()
|
||||
issues := make([]*Issue, 0, len(issueIDs))
|
||||
if err := db.GetEngine(ctx).
|
||||
Where("id > 0").
|
||||
@ -180,7 +179,8 @@ func (prs PullRequestList) loadAttributes(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (prs PullRequestList) getIssueIDs() []int64 {
|
||||
// GetIssueIDs returns all issue ids
|
||||
func (prs PullRequestList) GetIssueIDs() []int64 {
|
||||
issueIDs := make([]int64, 0, len(prs))
|
||||
for i := range prs {
|
||||
issueIDs = append(issueIDs, prs[i].IssueID)
|
||||
@ -192,24 +192,3 @@ func (prs PullRequestList) getIssueIDs() []int64 {
|
||||
func (prs PullRequestList) LoadAttributes() error {
|
||||
return prs.loadAttributes(db.DefaultContext)
|
||||
}
|
||||
|
||||
// InvalidateCodeComments will lookup the prs for code comments which got invalidated by change
|
||||
func (prs PullRequestList) InvalidateCodeComments(ctx context.Context, doer *user_model.User, repo *git.Repository, branch string) error {
|
||||
if len(prs) == 0 {
|
||||
return nil
|
||||
}
|
||||
issueIDs := prs.getIssueIDs()
|
||||
var codeComments []*Comment
|
||||
if err := db.GetEngine(ctx).
|
||||
Where("type = ? and invalidated = ?", CommentTypeCode, false).
|
||||
In("issue_id", issueIDs).
|
||||
Find(&codeComments); err != nil {
|
||||
return fmt.Errorf("find code comments: %w", err)
|
||||
}
|
||||
for _, comment := range codeComments {
|
||||
if err := comment.CheckInvalidation(repo, doer, branch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -972,7 +972,7 @@ func DeleteReview(r *Review) error {
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
if _, err := sess.Where(opts.toConds()).Delete(new(Comment)); err != nil {
|
||||
if _, err := sess.Where(opts.ToConds()).Delete(new(Comment)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -982,7 +982,7 @@ func DeleteReview(r *Review) error {
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
if _, err := sess.Where(opts.toConds()).Delete(new(Comment)); err != nil {
|
||||
if _, err := sess.Where(opts.ToConds()).Delete(new(Comment)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1006,7 +1006,7 @@ func (r *Review) GetCodeCommentsCount() int {
|
||||
IssueID: r.IssueID,
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
conds := opts.toConds()
|
||||
conds := opts.ToConds()
|
||||
if r.ID == 0 {
|
||||
conds = conds.And(builder.Eq{"invalidated": false})
|
||||
}
|
||||
@ -1026,7 +1026,7 @@ func (r *Review) HTMLURL() string {
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
comment := new(Comment)
|
||||
has, err := db.GetEngine(db.DefaultContext).Where(opts.toConds()).Get(comment)
|
||||
has, err := db.GetEngine(db.DefaultContext).Where(opts.ToConds()).Get(comment)
|
||||
if err != nil || !has {
|
||||
return ""
|
||||
}
|
||||
|
@ -451,6 +451,8 @@ var migrations = []Migration{
|
||||
NewMigration("Drop ForeignReference table", v1_19.DropForeignReferenceTable),
|
||||
// v238 -> v239
|
||||
NewMigration("Add updated unix to LFSMetaObject", v1_19.AddUpdatedUnixToLFSMetaObject),
|
||||
// v239 -> v240
|
||||
NewMigration("Add scope for access_token", v1_19.AddScopeForAccessTokens),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current db version
|
||||
|
22
models/migrations/v1_19/v239.go
Normal file
22
models/migrations/v1_19/v239.go
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_19 //nolint
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddScopeForAccessTokens(x *xorm.Engine) error {
|
||||
type AccessToken struct {
|
||||
Scope string
|
||||
}
|
||||
|
||||
if err := x.Sync(new(AccessToken)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// all previous tokens have `all` and `sudo` scopes
|
||||
_, err := x.Exec("UPDATE access_token SET scope = ? WHERE scope IS NULL OR scope = ''", "all,sudo")
|
||||
return err
|
||||
}
|
@ -268,6 +268,16 @@ func Init() error {
|
||||
if setting_module.OfflineMode {
|
||||
disableGravatar = true
|
||||
enableFederatedAvatar = false
|
||||
if !GetSettingBool(KeyPictureDisableGravatar) {
|
||||
if err := SetSettingNoVersion(KeyPictureDisableGravatar, "true"); err != nil {
|
||||
return fmt.Errorf("Failed to set setting %q: %w", KeyPictureDisableGravatar, err)
|
||||
}
|
||||
}
|
||||
if GetSettingBool(KeyPictureEnableFederatedAvatar) {
|
||||
if err := SetSettingNoVersion(KeyPictureEnableFederatedAvatar, "false"); err != nil {
|
||||
return fmt.Errorf("Failed to set setting %q: %w", KeyPictureEnableFederatedAvatar, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if enableFederatedAvatar || !disableGravatar {
|
||||
|
64
modules/markup/asciicast/asciicast.go
Normal file
64
modules/markup/asciicast/asciicast.go
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package asciicast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"regexp"
|
||||
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
func init() {
|
||||
markup.RegisterRenderer(Renderer{})
|
||||
}
|
||||
|
||||
// Renderer implements markup.Renderer for asciicast files.
|
||||
// See https://github.com/asciinema/asciinema/blob/develop/doc/asciicast-v2.md
|
||||
type Renderer struct{}
|
||||
|
||||
// Name implements markup.Renderer
|
||||
func (Renderer) Name() string {
|
||||
return "asciicast"
|
||||
}
|
||||
|
||||
// Extensions implements markup.Renderer
|
||||
func (Renderer) Extensions() []string {
|
||||
return []string{".cast"}
|
||||
}
|
||||
|
||||
const (
|
||||
playerClassName = "asciinema-player-container"
|
||||
playerSrcAttr = "data-asciinema-player-src"
|
||||
)
|
||||
|
||||
// SanitizerRules implements markup.Renderer
|
||||
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
|
||||
return []setting.MarkupSanitizerRule{
|
||||
{Element: "div", AllowAttr: "class", Regexp: regexp.MustCompile(playerClassName)},
|
||||
{Element: "div", AllowAttr: playerSrcAttr},
|
||||
}
|
||||
}
|
||||
|
||||
// Render implements markup.Renderer
|
||||
func (Renderer) Render(ctx *markup.RenderContext, _ io.Reader, output io.Writer) error {
|
||||
rawURL := fmt.Sprintf("%s/%s/%s/raw/%s/%s",
|
||||
setting.AppSubURL,
|
||||
url.PathEscape(ctx.Metas["user"]),
|
||||
url.PathEscape(ctx.Metas["repo"]),
|
||||
ctx.Metas["BranchNameSubURL"],
|
||||
url.PathEscape(ctx.RelativePath),
|
||||
)
|
||||
|
||||
_, err := io.WriteString(output, fmt.Sprintf(
|
||||
`<div class="%s" %s="%s"></div>`,
|
||||
playerClassName,
|
||||
playerSrcAttr,
|
||||
rawURL,
|
||||
))
|
||||
return err
|
||||
}
|
@ -747,6 +747,7 @@ access_token_deletion_cancel_action = Cancel
|
||||
access_token_deletion_confirm_action = Delete
|
||||
access_token_deletion_desc = Deleting a token will revoke access to your account for applications using it. This cannot be undone. Continue?
|
||||
delete_token_success = The token has been deleted. Applications using it no longer have access to your account.
|
||||
select_scopes = Select scopes
|
||||
|
||||
manage_oauth2_applications = Manage OAuth2 Applications
|
||||
edit_oauth2_application = Edit OAuth2 Application
|
||||
|
76
package-lock.json
generated
76
package-lock.json
generated
@ -16,6 +16,7 @@
|
||||
"@primer/octicons": "17.10.0",
|
||||
"@vue/compiler-sfc": "3.2.45",
|
||||
"add-asset-webpack-plugin": "2.0.1",
|
||||
"asciinema-player": "3.0.1",
|
||||
"css-loader": "6.7.3",
|
||||
"dropzone": "6.0.0-beta.2",
|
||||
"easymde": "2.18.0",
|
||||
@ -197,6 +198,17 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz",
|
||||
"integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@braintree/sanitize-url": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz",
|
||||
@ -2094,6 +2106,15 @@
|
||||
"printable-characters": "^1.0.42"
|
||||
}
|
||||
},
|
||||
"node_modules/asciinema-player": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.0.1.tgz",
|
||||
"integrity": "sha512-plm/C/MhOtZWysrfcT/rzxOuu8vxvvDSvF50pqZS6KpJUDmATedAhO54zktbE/g7RiaaYfzgX8xjRhlQdgISwA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"solid-js": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/assertion-error": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
||||
@ -7754,6 +7775,11 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"node_modules/regexp-tree": {
|
||||
"version": "0.1.24",
|
||||
"resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz",
|
||||
@ -8249,6 +8275,19 @@
|
||||
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/solid-js": {
|
||||
"version": "1.6.9",
|
||||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.9.tgz",
|
||||
"integrity": "sha512-kV3fMmm+1C2J95c8eDOPKGfZHnuAkHUBLG4hX1Xu08bXeAIPqmxuz/QdH3B8SIdTp3EatBVIyA6RCes3hrGzpg==",
|
||||
"dependencies": {
|
||||
"csstype": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/solid-js/node_modules/csstype": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
|
||||
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
|
||||
},
|
||||
"node_modules/sortablejs": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||
@ -10159,6 +10198,14 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
|
||||
"integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA=="
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz",
|
||||
"integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
}
|
||||
},
|
||||
"@braintree/sanitize-url": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz",
|
||||
@ -11525,6 +11572,15 @@
|
||||
"printable-characters": "^1.0.42"
|
||||
}
|
||||
},
|
||||
"asciinema-player": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.0.1.tgz",
|
||||
"integrity": "sha512-plm/C/MhOtZWysrfcT/rzxOuu8vxvvDSvF50pqZS6KpJUDmATedAhO54zktbE/g7RiaaYfzgX8xjRhlQdgISwA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"solid-js": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"assertion-error": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
||||
@ -15606,6 +15662,11 @@
|
||||
"strip-indent": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"regexp-tree": {
|
||||
"version": "0.1.24",
|
||||
"resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz",
|
||||
@ -15960,6 +16021,21 @@
|
||||
"socks": "^2.3.3"
|
||||
}
|
||||
},
|
||||
"solid-js": {
|
||||
"version": "1.6.9",
|
||||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.9.tgz",
|
||||
"integrity": "sha512-kV3fMmm+1C2J95c8eDOPKGfZHnuAkHUBLG4hX1Xu08bXeAIPqmxuz/QdH3B8SIdTp3EatBVIyA6RCes3hrGzpg==",
|
||||
"requires": {
|
||||
"csstype": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
|
||||
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"sortablejs": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||
|
@ -16,6 +16,7 @@
|
||||
"@primer/octicons": "17.10.0",
|
||||
"@vue/compiler-sfc": "3.2.45",
|
||||
"add-asset-webpack-plugin": "2.0.1",
|
||||
"asciinema-player": "3.0.1",
|
||||
"css-loader": "6.7.3",
|
||||
"dropzone": "6.0.0-beta.2",
|
||||
"easymde": "2.18.0",
|
||||
|
@ -69,6 +69,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
@ -206,9 +207,36 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.APIContext)
|
||||
}
|
||||
|
||||
// Contexter middleware already checks token for user sign in process.
|
||||
func reqToken() func(ctx *context.APIContext) {
|
||||
func reqToken(requiredScope auth_model.AccessTokenScope) func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if true == ctx.Data["IsApiToken"] {
|
||||
// If OAuth2 token is present
|
||||
if _, ok := ctx.Data["ApiTokenScope"]; ctx.Data["IsApiToken"] == true && ok {
|
||||
// no scope required
|
||||
if requiredScope == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// check scope
|
||||
scope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
|
||||
allow, err := scope.HasScope(requiredScope)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusForbidden, "reqToken", "parsing token failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
if allow {
|
||||
return
|
||||
}
|
||||
|
||||
// if requires 'repo' scope, but only has 'public_repo' scope, allow it only if the repo is public
|
||||
if requiredScope == auth_model.AccessTokenScopeRepo {
|
||||
if allowPublicRepo, err := scope.HasScope(auth_model.AccessTokenScopePublicRepo); err == nil && allowPublicRepo {
|
||||
if ctx.Repo.Repository != nil && !ctx.Repo.Repository.IsPrivate {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Error(http.StatusForbidden, "reqToken", "token does not have required scope: "+requiredScope)
|
||||
return
|
||||
}
|
||||
if ctx.Context.IsBasicAuth {
|
||||
@ -631,7 +659,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
}))
|
||||
|
||||
m.Group("", func() {
|
||||
// Miscellaneous
|
||||
// Miscellaneous (no scope required)
|
||||
if setting.API.EnableSwagger {
|
||||
m.Get("/swagger", func(ctx *context.APIContext) {
|
||||
ctx.Redirect(setting.AppSubURL + "/api/swagger")
|
||||
@ -657,7 +685,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
m.Get("/repository", settings.GetGeneralRepoSettings)
|
||||
})
|
||||
|
||||
// Notifications
|
||||
// Notifications (requires 'notification' scope)
|
||||
m.Group("/notifications", func() {
|
||||
m.Combo("").
|
||||
Get(notify.ListNotifications).
|
||||
@ -666,9 +694,9 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
m.Combo("/threads/{id}").
|
||||
Get(notify.GetThread).
|
||||
Patch(notify.ReadThread)
|
||||
}, reqToken())
|
||||
}, reqToken(auth_model.AccessTokenScopeNotification))
|
||||
|
||||
// Users
|
||||
// Users (no scope required)
|
||||
m.Group("/users", func() {
|
||||
m.Get("/search", reqExploreSignIn(), user.Search)
|
||||
|
||||
@ -688,6 +716,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
}, context_service.UserAssignmentAPI())
|
||||
})
|
||||
|
||||
// (no scope required)
|
||||
m.Group("/users", func() {
|
||||
m.Group("/{username}", func() {
|
||||
m.Get("/keys", user.ListPublicKeys)
|
||||
@ -703,57 +732,62 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
|
||||
m.Get("/subscriptions", user.GetWatchedRepos)
|
||||
}, context_service.UserAssignmentAPI())
|
||||
}, reqToken())
|
||||
}, reqToken(""))
|
||||
|
||||
m.Group("/user", func() {
|
||||
m.Get("", user.GetAuthenticatedUser)
|
||||
m.Group("/settings", func() {
|
||||
m.Get("", user.GetUserSettings)
|
||||
m.Patch("", bind(api.UserSettingsOptions{}), user.UpdateUserSettings)
|
||||
}, reqToken())
|
||||
m.Combo("/emails").Get(user.ListEmails).
|
||||
Post(bind(api.CreateEmailOption{}), user.AddEmail).
|
||||
Delete(bind(api.DeleteEmailOption{}), user.DeleteEmail)
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadUser), user.GetUserSettings)
|
||||
m.Patch("", reqToken(auth_model.AccessTokenScopeUser), bind(api.UserSettingsOptions{}), user.UpdateUserSettings)
|
||||
})
|
||||
m.Combo("/emails").Get(reqToken(auth_model.AccessTokenScopeReadUser), user.ListEmails).
|
||||
Post(reqToken(auth_model.AccessTokenScopeUser), bind(api.CreateEmailOption{}), user.AddEmail).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeUser), bind(api.DeleteEmailOption{}), user.DeleteEmail)
|
||||
|
||||
m.Get("/followers", user.ListMyFollowers)
|
||||
m.Group("/following", func() {
|
||||
m.Get("", user.ListMyFollowing)
|
||||
m.Group("/{username}", func() {
|
||||
m.Get("", user.CheckMyFollowing)
|
||||
m.Put("", user.Follow)
|
||||
m.Delete("", user.Unfollow)
|
||||
m.Put("", reqToken(auth_model.AccessTokenScopeUserFollow), user.Follow) // requires 'user:follow' scope
|
||||
m.Delete("", reqToken(auth_model.AccessTokenScopeUserFollow), user.Unfollow) // requires 'user:follow' scope
|
||||
}, context_service.UserAssignmentAPI())
|
||||
})
|
||||
|
||||
// (admin:public_key scope)
|
||||
m.Group("/keys", func() {
|
||||
m.Combo("").Get(user.ListMyPublicKeys).
|
||||
Post(bind(api.CreateKeyOption{}), user.CreatePublicKey)
|
||||
m.Combo("/{id}").Get(user.GetPublicKey).
|
||||
Delete(user.DeletePublicKey)
|
||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadPublicKey), user.ListMyPublicKeys).
|
||||
Post(reqToken(auth_model.AccessTokenScopeWritePublicKey), bind(api.CreateKeyOption{}), user.CreatePublicKey)
|
||||
m.Combo("/{id}").Get(reqToken(auth_model.AccessTokenScopeReadPublicKey), user.GetPublicKey).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWritePublicKey), user.DeletePublicKey)
|
||||
})
|
||||
|
||||
// (admin:application scope)
|
||||
m.Group("/applications", func() {
|
||||
m.Combo("/oauth2").
|
||||
Get(user.ListOauth2Applications).
|
||||
Post(bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application)
|
||||
Get(reqToken(auth_model.AccessTokenScopeReadApplication), user.ListOauth2Applications).
|
||||
Post(reqToken(auth_model.AccessTokenScopeWriteApplication), bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application)
|
||||
m.Combo("/oauth2/{id}").
|
||||
Delete(user.DeleteOauth2Application).
|
||||
Patch(bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application).
|
||||
Get(user.GetOauth2Application)
|
||||
}, reqToken())
|
||||
|
||||
m.Group("/gpg_keys", func() {
|
||||
m.Combo("").Get(user.ListMyGPGKeys).
|
||||
Post(bind(api.CreateGPGKeyOption{}), user.CreateGPGKey)
|
||||
m.Combo("/{id}").Get(user.GetGPGKey).
|
||||
Delete(user.DeleteGPGKey)
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteApplication), user.DeleteOauth2Application).
|
||||
Patch(reqToken(auth_model.AccessTokenScopeWriteApplication), bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application).
|
||||
Get(reqToken(auth_model.AccessTokenScopeReadApplication), user.GetOauth2Application)
|
||||
})
|
||||
|
||||
m.Get("/gpg_key_token", user.GetVerificationToken)
|
||||
m.Post("/gpg_key_verify", bind(api.VerifyGPGKeyOption{}), user.VerifyUserGPGKey)
|
||||
// (admin:gpg_key scope)
|
||||
m.Group("/gpg_keys", func() {
|
||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadGPGKey), user.ListMyGPGKeys).
|
||||
Post(reqToken(auth_model.AccessTokenScopeWriteGPGKey), bind(api.CreateGPGKeyOption{}), user.CreateGPGKey)
|
||||
m.Combo("/{id}").Get(reqToken(auth_model.AccessTokenScopeReadGPGKey), user.GetGPGKey).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteGPGKey), user.DeleteGPGKey)
|
||||
})
|
||||
m.Get("/gpg_key_token", reqToken(auth_model.AccessTokenScopeReadGPGKey), user.GetVerificationToken)
|
||||
m.Post("/gpg_key_verify", reqToken(auth_model.AccessTokenScopeReadGPGKey), bind(api.VerifyGPGKeyOption{}), user.VerifyUserGPGKey)
|
||||
|
||||
m.Combo("/repos").Get(user.ListMyRepos).
|
||||
// (repo scope)
|
||||
m.Combo("/repos", reqToken(auth_model.AccessTokenScopeRepo)).Get(user.ListMyRepos).
|
||||
Post(bind(api.CreateRepoOption{}), repo.Create)
|
||||
|
||||
// (repo scope)
|
||||
m.Group("/starred", func() {
|
||||
m.Get("", user.GetMyStarredRepos)
|
||||
m.Group("/{username}/{reponame}", func() {
|
||||
@ -761,57 +795,57 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
m.Put("", user.Star)
|
||||
m.Delete("", user.Unstar)
|
||||
}, repoAssignment())
|
||||
})
|
||||
m.Get("/times", repo.ListMyTrackedTimes)
|
||||
|
||||
m.Get("/stopwatches", repo.GetStopwatches)
|
||||
|
||||
m.Get("/subscriptions", user.GetMyWatchedRepos)
|
||||
|
||||
m.Get("/teams", org.ListUserTeams)
|
||||
}, reqToken())
|
||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
||||
m.Get("/times", reqToken(auth_model.AccessTokenScopeRepo), repo.ListMyTrackedTimes)
|
||||
m.Get("/stopwatches", reqToken(auth_model.AccessTokenScopeRepo), repo.GetStopwatches)
|
||||
m.Get("/subscriptions", reqToken(auth_model.AccessTokenScopeRepo), user.GetMyWatchedRepos)
|
||||
m.Get("/teams", reqToken(auth_model.AccessTokenScopeRepo), org.ListUserTeams)
|
||||
}, reqToken(""))
|
||||
|
||||
// Repositories
|
||||
m.Post("/org/{org}/repos", reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepoDeprecated)
|
||||
m.Post("/org/{org}/repos", reqToken(auth_model.AccessTokenScopeAdminOrg), bind(api.CreateRepoOption{}), repo.CreateOrgRepoDeprecated)
|
||||
|
||||
m.Combo("/repositories/{id}", reqToken()).Get(repo.GetByID)
|
||||
m.Combo("/repositories/{id}", reqToken(auth_model.AccessTokenScopeRepo)).Get(repo.GetByID)
|
||||
|
||||
m.Group("/repos", func() {
|
||||
m.Get("/search", repo.Search)
|
||||
|
||||
m.Get("/issues/search", repo.SearchIssues)
|
||||
|
||||
m.Post("/migrate", reqToken(), bind(api.MigrateRepoOptions{}), repo.Migrate)
|
||||
// (repo scope)
|
||||
m.Post("/migrate", reqToken(auth_model.AccessTokenScopeRepo), bind(api.MigrateRepoOptions{}), repo.Migrate)
|
||||
|
||||
m.Group("/{username}/{reponame}", func() {
|
||||
m.Combo("").Get(reqAnyRepoReader(), repo.Get).
|
||||
Delete(reqToken(), reqOwner(), repo.Delete).
|
||||
Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit)
|
||||
m.Post("/generate", reqToken(), reqRepoReader(unit.TypeCode), bind(api.GenerateRepoOption{}), repo.Generate)
|
||||
m.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer)
|
||||
m.Post("/transfer/accept", reqToken(), repo.AcceptTransfer)
|
||||
m.Post("/transfer/reject", reqToken(), repo.RejectTransfer)
|
||||
m.Combo("/notifications").
|
||||
Get(reqToken(), notify.ListRepoNotifications).
|
||||
Put(reqToken(), notify.ReadRepoNotifications)
|
||||
Delete(reqToken(auth_model.AccessTokenScopeDeleteRepo), reqOwner(), repo.Delete).
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit)
|
||||
m.Post("/generate", reqToken(auth_model.AccessTokenScopeRepo), reqRepoReader(unit.TypeCode), bind(api.GenerateRepoOption{}), repo.Generate)
|
||||
m.Group("/transfer", func() {
|
||||
m.Post("", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer)
|
||||
m.Post("/accept", repo.AcceptTransfer)
|
||||
m.Post("/reject", repo.RejectTransfer)
|
||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
||||
m.Combo("/notifications", reqToken(auth_model.AccessTokenScopeNotification)).
|
||||
Get(notify.ListRepoNotifications).
|
||||
Put(notify.ReadRepoNotifications)
|
||||
m.Group("/hooks/git", func() {
|
||||
m.Combo("").Get(repo.ListGitHooks)
|
||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadRepoHook), repo.ListGitHooks)
|
||||
m.Group("/{id}", func() {
|
||||
m.Combo("").Get(repo.GetGitHook).
|
||||
Patch(bind(api.EditGitHookOption{}), repo.EditGitHook).
|
||||
Delete(repo.DeleteGitHook)
|
||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadRepoHook), repo.GetGitHook).
|
||||
Patch(reqToken(auth_model.AccessTokenScopeWriteRepoHook), bind(api.EditGitHookOption{}), repo.EditGitHook).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteRepoHook), repo.DeleteGitHook)
|
||||
})
|
||||
}, reqToken(), reqAdmin(), reqGitHook(), context.ReferencesGitRepo(true))
|
||||
}, reqAdmin(), reqGitHook(), context.ReferencesGitRepo(true))
|
||||
m.Group("/hooks", func() {
|
||||
m.Combo("").Get(repo.ListHooks).
|
||||
Post(bind(api.CreateHookOption{}), repo.CreateHook)
|
||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadRepoHook), repo.ListHooks).
|
||||
Post(reqToken(auth_model.AccessTokenScopeWriteRepoHook), bind(api.CreateHookOption{}), repo.CreateHook)
|
||||
m.Group("/{id}", func() {
|
||||
m.Combo("").Get(repo.GetHook).
|
||||
Patch(bind(api.EditHookOption{}), repo.EditHook).
|
||||
Delete(repo.DeleteHook)
|
||||
m.Post("/tests", context.ReferencesGitRepo(), context.RepoRefForAPI, repo.TestHook)
|
||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadRepoHook), repo.GetHook).
|
||||
Patch(reqToken(auth_model.AccessTokenScopeWriteRepoHook), bind(api.EditHookOption{}), repo.EditHook).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteRepoHook), repo.DeleteHook)
|
||||
m.Post("/tests", reqToken(auth_model.AccessTokenScopeReadRepoHook), context.ReferencesGitRepo(), context.RepoRefForAPI, repo.TestHook)
|
||||
})
|
||||
}, reqToken(), reqAdmin(), reqWebhooksEnabled())
|
||||
}, reqAdmin(), reqWebhooksEnabled())
|
||||
m.Group("/collaborators", func() {
|
||||
m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
|
||||
m.Group("/{collaborator}", func() {
|
||||
@ -819,26 +853,26 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddCollaborator).
|
||||
Delete(reqAdmin(), repo.DeleteCollaborator)
|
||||
m.Get("/permission", repo.GetRepoPermissions)
|
||||
}, reqToken())
|
||||
}, reqToken())
|
||||
m.Get("/assignees", reqToken(), reqAnyRepoReader(), repo.GetAssignees)
|
||||
m.Get("/reviewers", reqToken(), reqAnyRepoReader(), repo.GetReviewers)
|
||||
})
|
||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
||||
m.Get("/assignees", reqToken(auth_model.AccessTokenScopeRepo), reqAnyRepoReader(), repo.GetAssignees)
|
||||
m.Get("/reviewers", reqToken(auth_model.AccessTokenScopeRepo), reqAnyRepoReader(), repo.GetReviewers)
|
||||
m.Group("/teams", func() {
|
||||
m.Get("", reqAnyRepoReader(), repo.ListTeams)
|
||||
m.Combo("/{team}").Get(reqAnyRepoReader(), repo.IsTeam).
|
||||
Put(reqAdmin(), repo.AddTeam).
|
||||
Delete(reqAdmin(), repo.DeleteTeam)
|
||||
}, reqToken())
|
||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
||||
m.Get("/raw/*", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetRawFile)
|
||||
m.Get("/media/*", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetRawFileOrLFS)
|
||||
m.Get("/archive/*", reqRepoReader(unit.TypeCode), repo.GetArchive)
|
||||
m.Combo("/forks").Get(repo.ListForks).
|
||||
Post(reqToken(), reqRepoReader(unit.TypeCode), bind(api.CreateForkOption{}), repo.CreateFork)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoReader(unit.TypeCode), bind(api.CreateForkOption{}), repo.CreateFork)
|
||||
m.Group("/branches", func() {
|
||||
m.Get("", repo.ListBranches)
|
||||
m.Get("/*", repo.GetBranch)
|
||||
m.Delete("/*", reqRepoWriter(unit.TypeCode), repo.DeleteBranch)
|
||||
m.Post("", reqRepoWriter(unit.TypeCode), bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
|
||||
m.Delete("/*", reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeCode), repo.DeleteBranch)
|
||||
m.Post("", reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeCode), bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
|
||||
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
|
||||
m.Group("/branch_protections", func() {
|
||||
m.Get("", repo.ListBranchProtections)
|
||||
@ -848,74 +882,74 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
m.Patch("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection)
|
||||
m.Delete("", repo.DeleteBranchProtection)
|
||||
})
|
||||
}, reqToken(), reqAdmin())
|
||||
}, reqToken(auth_model.AccessTokenScopeRepo), reqAdmin())
|
||||
m.Group("/tags", func() {
|
||||
m.Get("", repo.ListTags)
|
||||
m.Get("/*", repo.GetTag)
|
||||
m.Post("", reqRepoWriter(unit.TypeCode), bind(api.CreateTagOption{}), repo.CreateTag)
|
||||
m.Delete("/*", repo.DeleteTag)
|
||||
m.Post("", reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeCode), bind(api.CreateTagOption{}), repo.CreateTag)
|
||||
m.Delete("/*", reqToken(auth_model.AccessTokenScopeRepo), repo.DeleteTag)
|
||||
}, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo(true))
|
||||
m.Group("/keys", func() {
|
||||
m.Combo("").Get(repo.ListDeployKeys).
|
||||
Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey)
|
||||
m.Combo("/{id}").Get(repo.GetDeployKey).
|
||||
Delete(repo.DeleteDeploykey)
|
||||
}, reqToken(), reqAdmin())
|
||||
}, reqToken(auth_model.AccessTokenScopeRepo), reqAdmin())
|
||||
m.Group("/times", func() {
|
||||
m.Combo("").Get(repo.ListTrackedTimesByRepository)
|
||||
m.Combo("/{timetrackingusername}").Get(repo.ListTrackedTimesByUser)
|
||||
}, mustEnableIssues, reqToken())
|
||||
}, mustEnableIssues, reqToken(auth_model.AccessTokenScopeRepo))
|
||||
m.Group("/wiki", func() {
|
||||
m.Combo("/page/{pageName}").
|
||||
Get(repo.GetWikiPage).
|
||||
Patch(mustNotBeArchived, reqRepoWriter(unit.TypeWiki), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage).
|
||||
Delete(mustNotBeArchived, reqRepoWriter(unit.TypeWiki), repo.DeleteWikiPage)
|
||||
Patch(mustNotBeArchived, reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeWiki), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage).
|
||||
Delete(mustNotBeArchived, reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeWiki), repo.DeleteWikiPage)
|
||||
m.Get("/revisions/{pageName}", repo.ListPageRevisions)
|
||||
m.Post("/new", mustNotBeArchived, reqRepoWriter(unit.TypeWiki), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage)
|
||||
m.Post("/new", mustNotBeArchived, reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeWiki), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage)
|
||||
m.Get("/pages", repo.ListWikiPages)
|
||||
}, mustEnableWiki)
|
||||
m.Group("/issues", func() {
|
||||
m.Combo("").Get(repo.ListIssues).
|
||||
Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
|
||||
m.Group("/comments", func() {
|
||||
m.Get("", repo.ListRepoIssueComments)
|
||||
m.Group("/{id}", func() {
|
||||
m.Combo("").
|
||||
Get(repo.GetIssueComment).
|
||||
Patch(mustNotBeArchived, reqToken(), bind(api.EditIssueCommentOption{}), repo.EditIssueComment).
|
||||
Delete(reqToken(), repo.DeleteIssueComment)
|
||||
Patch(mustNotBeArchived, reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditIssueCommentOption{}), repo.EditIssueComment).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), repo.DeleteIssueComment)
|
||||
m.Combo("/reactions").
|
||||
Get(repo.GetIssueCommentReactions).
|
||||
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueCommentReaction).
|
||||
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueCommentReaction)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditReactionOption{}), repo.PostIssueCommentReaction).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditReactionOption{}), repo.DeleteIssueCommentReaction)
|
||||
m.Group("/assets", func() {
|
||||
m.Combo("").
|
||||
Get(repo.ListIssueCommentAttachments).
|
||||
Post(reqToken(), mustNotBeArchived, repo.CreateIssueCommentAttachment)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.CreateIssueCommentAttachment)
|
||||
m.Combo("/{asset}").
|
||||
Get(repo.GetIssueCommentAttachment).
|
||||
Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueCommentAttachment).
|
||||
Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueCommentAttachment)
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueCommentAttachment).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.DeleteIssueCommentAttachment)
|
||||
}, mustEnableAttachments)
|
||||
})
|
||||
})
|
||||
m.Group("/{index}", func() {
|
||||
m.Combo("").Get(repo.GetIssue).
|
||||
Patch(reqToken(), bind(api.EditIssueOption{}), repo.EditIssue).
|
||||
Delete(reqToken(), reqAdmin(), context.ReferencesGitRepo(), repo.DeleteIssue)
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditIssueOption{}), repo.EditIssue).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), context.ReferencesGitRepo(), repo.DeleteIssue)
|
||||
m.Group("/comments", func() {
|
||||
m.Combo("").Get(repo.ListIssueComments).
|
||||
Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueCommentOption{}), repo.CreateIssueComment)
|
||||
m.Combo("/{id}", reqToken()).Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueCommentDeprecated).
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.CreateIssueCommentOption{}), repo.CreateIssueComment)
|
||||
m.Combo("/{id}", reqToken(auth_model.AccessTokenScopeRepo)).Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueCommentDeprecated).
|
||||
Delete(repo.DeleteIssueCommentDeprecated)
|
||||
})
|
||||
m.Get("/timeline", repo.ListIssueCommentsAndTimeline)
|
||||
m.Group("/labels", func() {
|
||||
m.Combo("").Get(repo.ListIssueLabels).
|
||||
Post(reqToken(), bind(api.IssueLabelsOption{}), repo.AddIssueLabels).
|
||||
Put(reqToken(), bind(api.IssueLabelsOption{}), repo.ReplaceIssueLabels).
|
||||
Delete(reqToken(), repo.ClearIssueLabels)
|
||||
m.Delete("/{id}", reqToken(), repo.DeleteIssueLabel)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.IssueLabelsOption{}), repo.AddIssueLabels).
|
||||
Put(reqToken(auth_model.AccessTokenScopeRepo), bind(api.IssueLabelsOption{}), repo.ReplaceIssueLabels).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), repo.ClearIssueLabels)
|
||||
m.Delete("/{id}", reqToken(auth_model.AccessTokenScopeRepo), repo.DeleteIssueLabel)
|
||||
})
|
||||
m.Group("/times", func() {
|
||||
m.Combo("").
|
||||
@ -923,125 +957,125 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
Post(bind(api.AddTimeOption{}), repo.AddTime).
|
||||
Delete(repo.ResetIssueTime)
|
||||
m.Delete("/{id}", repo.DeleteTime)
|
||||
}, reqToken())
|
||||
m.Combo("/deadline").Post(reqToken(), bind(api.EditDeadlineOption{}), repo.UpdateIssueDeadline)
|
||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
||||
m.Combo("/deadline").Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditDeadlineOption{}), repo.UpdateIssueDeadline)
|
||||
m.Group("/stopwatch", func() {
|
||||
m.Post("/start", reqToken(), repo.StartIssueStopwatch)
|
||||
m.Post("/stop", reqToken(), repo.StopIssueStopwatch)
|
||||
m.Delete("/delete", reqToken(), repo.DeleteIssueStopwatch)
|
||||
m.Post("/start", reqToken(auth_model.AccessTokenScopeRepo), repo.StartIssueStopwatch)
|
||||
m.Post("/stop", reqToken(auth_model.AccessTokenScopeRepo), repo.StopIssueStopwatch)
|
||||
m.Delete("/delete", reqToken(auth_model.AccessTokenScopeRepo), repo.DeleteIssueStopwatch)
|
||||
})
|
||||
m.Group("/subscriptions", func() {
|
||||
m.Get("", repo.GetIssueSubscribers)
|
||||
m.Get("/check", reqToken(), repo.CheckIssueSubscription)
|
||||
m.Put("/{user}", reqToken(), repo.AddIssueSubscription)
|
||||
m.Delete("/{user}", reqToken(), repo.DelIssueSubscription)
|
||||
m.Get("/check", reqToken(auth_model.AccessTokenScopeRepo), repo.CheckIssueSubscription)
|
||||
m.Put("/{user}", reqToken(auth_model.AccessTokenScopeRepo), repo.AddIssueSubscription)
|
||||
m.Delete("/{user}", reqToken(auth_model.AccessTokenScopeRepo), repo.DelIssueSubscription)
|
||||
})
|
||||
m.Combo("/reactions").
|
||||
Get(repo.GetIssueReactions).
|
||||
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueReaction).
|
||||
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueReaction)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditReactionOption{}), repo.PostIssueReaction).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditReactionOption{}), repo.DeleteIssueReaction)
|
||||
m.Group("/assets", func() {
|
||||
m.Combo("").
|
||||
Get(repo.ListIssueAttachments).
|
||||
Post(reqToken(), mustNotBeArchived, repo.CreateIssueAttachment)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.CreateIssueAttachment)
|
||||
m.Combo("/{asset}").
|
||||
Get(repo.GetIssueAttachment).
|
||||
Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueAttachment).
|
||||
Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueAttachment)
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueAttachment).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.DeleteIssueAttachment)
|
||||
}, mustEnableAttachments)
|
||||
})
|
||||
}, mustEnableIssuesOrPulls)
|
||||
m.Group("/labels", func() {
|
||||
m.Combo("").Get(repo.ListLabels).
|
||||
Post(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateLabelOption{}), repo.CreateLabel)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateLabelOption{}), repo.CreateLabel)
|
||||
m.Combo("/{id}").Get(repo.GetLabel).
|
||||
Patch(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditLabelOption{}), repo.EditLabel).
|
||||
Delete(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteLabel)
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditLabelOption{}), repo.EditLabel).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteLabel)
|
||||
})
|
||||
m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown)
|
||||
m.Post("/markdown/raw", misc.MarkdownRaw)
|
||||
m.Post("/markdown", reqToken(auth_model.AccessTokenScopeRepo), bind(api.MarkdownOption{}), misc.Markdown)
|
||||
m.Post("/markdown/raw", reqToken(auth_model.AccessTokenScopeRepo), misc.MarkdownRaw)
|
||||
m.Group("/milestones", func() {
|
||||
m.Combo("").Get(repo.ListMilestones).
|
||||
Post(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateMilestoneOption{}), repo.CreateMilestone)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateMilestoneOption{}), repo.CreateMilestone)
|
||||
m.Combo("/{id}").Get(repo.GetMilestone).
|
||||
Patch(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditMilestoneOption{}), repo.EditMilestone).
|
||||
Delete(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteMilestone)
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditMilestoneOption{}), repo.EditMilestone).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteMilestone)
|
||||
})
|
||||
m.Get("/stargazers", repo.ListStargazers)
|
||||
m.Get("/subscribers", repo.ListSubscribers)
|
||||
m.Group("/subscription", func() {
|
||||
m.Get("", user.IsWatching)
|
||||
m.Put("", reqToken(), user.Watch)
|
||||
m.Delete("", reqToken(), user.Unwatch)
|
||||
m.Put("", reqToken(auth_model.AccessTokenScopeRepo), user.Watch)
|
||||
m.Delete("", reqToken(auth_model.AccessTokenScopeRepo), user.Unwatch)
|
||||
})
|
||||
m.Group("/releases", func() {
|
||||
m.Combo("").Get(repo.ListReleases).
|
||||
Post(reqToken(), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.CreateReleaseOption{}), repo.CreateRelease)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.CreateReleaseOption{}), repo.CreateRelease)
|
||||
m.Group("/{id}", func() {
|
||||
m.Combo("").Get(repo.GetRelease).
|
||||
Patch(reqToken(), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.EditReleaseOption{}), repo.EditRelease).
|
||||
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteRelease)
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.EditReleaseOption{}), repo.EditRelease).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), repo.DeleteRelease)
|
||||
m.Group("/assets", func() {
|
||||
m.Combo("").Get(repo.ListReleaseAttachments).
|
||||
Post(reqToken(), reqRepoWriter(unit.TypeReleases), repo.CreateReleaseAttachment)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), repo.CreateReleaseAttachment)
|
||||
m.Combo("/{asset}").Get(repo.GetReleaseAttachment).
|
||||
Patch(reqToken(), reqRepoWriter(unit.TypeReleases), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment).
|
||||
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseAttachment)
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseAttachment)
|
||||
})
|
||||
})
|
||||
m.Group("/tags", func() {
|
||||
m.Combo("/{tag}").
|
||||
Get(repo.GetReleaseByTag).
|
||||
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseByTag)
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseByTag)
|
||||
})
|
||||
}, reqRepoReader(unit.TypeReleases))
|
||||
m.Post("/mirror-sync", reqToken(), reqRepoWriter(unit.TypeCode), repo.MirrorSync)
|
||||
m.Post("/push_mirrors-sync", reqAdmin(), repo.PushMirrorSync)
|
||||
m.Post("/mirror-sync", reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeCode), repo.MirrorSync)
|
||||
m.Post("/push_mirrors-sync", reqAdmin(), reqToken(auth_model.AccessTokenScopeRepo), repo.PushMirrorSync)
|
||||
m.Group("/push_mirrors", func() {
|
||||
m.Combo("").Get(repo.ListPushMirrors).
|
||||
Post(bind(api.CreatePushMirrorOption{}), repo.AddPushMirror)
|
||||
m.Combo("/{name}").
|
||||
Delete(repo.DeletePushMirrorByRemoteName).
|
||||
Get(repo.GetPushMirrorByName)
|
||||
}, reqAdmin())
|
||||
}, reqAdmin(), reqToken(auth_model.AccessTokenScopeRepo))
|
||||
|
||||
m.Get("/editorconfig/{filename}", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetEditorconfig)
|
||||
m.Group("/pulls", func() {
|
||||
m.Combo("").Get(repo.ListPullRequests).
|
||||
Post(reqToken(), mustNotBeArchived, bind(api.CreatePullRequestOption{}), repo.CreatePullRequest)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.CreatePullRequestOption{}), repo.CreatePullRequest)
|
||||
m.Group("/{index}", func() {
|
||||
m.Combo("").Get(repo.GetPullRequest).
|
||||
Patch(reqToken(), bind(api.EditPullRequestOption{}), repo.EditPullRequest)
|
||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditPullRequestOption{}), repo.EditPullRequest)
|
||||
m.Get(".{diffType:diff|patch}", repo.DownloadPullDiffOrPatch)
|
||||
m.Post("/update", reqToken(), repo.UpdatePullRequest)
|
||||
m.Post("/update", reqToken(auth_model.AccessTokenScopeRepo), repo.UpdatePullRequest)
|
||||
m.Get("/commits", repo.GetPullRequestCommits)
|
||||
m.Get("/files", repo.GetPullRequestFiles)
|
||||
m.Combo("/merge").Get(repo.IsPullRequestMerged).
|
||||
Post(reqToken(), mustNotBeArchived, bind(forms.MergePullRequestForm{}), repo.MergePullRequest).
|
||||
Delete(reqToken(), mustNotBeArchived, repo.CancelScheduledAutoMerge)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(forms.MergePullRequestForm{}), repo.MergePullRequest).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.CancelScheduledAutoMerge)
|
||||
m.Group("/reviews", func() {
|
||||
m.Combo("").
|
||||
Get(repo.ListPullReviews).
|
||||
Post(reqToken(), bind(api.CreatePullReviewOptions{}), repo.CreatePullReview)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.CreatePullReviewOptions{}), repo.CreatePullReview)
|
||||
m.Group("/{id}", func() {
|
||||
m.Combo("").
|
||||
Get(repo.GetPullReview).
|
||||
Delete(reqToken(), repo.DeletePullReview).
|
||||
Post(reqToken(), bind(api.SubmitPullReviewOptions{}), repo.SubmitPullReview)
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), repo.DeletePullReview).
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.SubmitPullReviewOptions{}), repo.SubmitPullReview)
|
||||
m.Combo("/comments").
|
||||
Get(repo.GetPullReviewComments)
|
||||
m.Post("/dismissals", reqToken(), bind(api.DismissPullReviewOptions{}), repo.DismissPullReview)
|
||||
m.Post("/undismissals", reqToken(), repo.UnDismissPullReview)
|
||||
m.Post("/dismissals", reqToken(auth_model.AccessTokenScopeRepo), bind(api.DismissPullReviewOptions{}), repo.DismissPullReview)
|
||||
m.Post("/undismissals", reqToken(auth_model.AccessTokenScopeRepo), repo.UnDismissPullReview)
|
||||
})
|
||||
})
|
||||
m.Combo("/requested_reviewers").
|
||||
Delete(reqToken(), bind(api.PullReviewRequestOptions{}), repo.DeleteReviewRequests).
|
||||
Post(reqToken(), bind(api.PullReviewRequestOptions{}), repo.CreateReviewRequests)
|
||||
m.Combo("/requested_reviewers", reqToken(auth_model.AccessTokenScopeRepo)).
|
||||
Delete(bind(api.PullReviewRequestOptions{}), repo.DeleteReviewRequests).
|
||||
Post(bind(api.PullReviewRequestOptions{}), repo.CreateReviewRequests)
|
||||
})
|
||||
}, mustAllowPulls, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo())
|
||||
m.Group("/statuses", func() {
|
||||
m.Combo("/{sha}").Get(repo.GetCommitStatuses).
|
||||
Post(reqToken(), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
|
||||
Post(reqToken(auth_model.AccessTokenScopeRepoStatus), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
|
||||
}, reqRepoReader(unit.TypeCode))
|
||||
m.Group("/commits", func() {
|
||||
m.Get("", context.ReferencesGitRepo(), repo.GetAllCommits)
|
||||
@ -1062,7 +1096,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
m.Get("/tags/{sha}", repo.GetAnnotatedTag)
|
||||
m.Get("/notes/{sha}", repo.GetNote)
|
||||
}, context.ReferencesGitRepo(true), reqRepoReader(unit.TypeCode))
|
||||
m.Post("/diffpatch", reqRepoWriter(unit.TypeCode), reqToken(), bind(api.ApplyDiffPatchFileOptions{}), repo.ApplyDiffPatch)
|
||||
m.Post("/diffpatch", reqRepoWriter(unit.TypeCode), reqToken(auth_model.AccessTokenScopeRepo), bind(api.ApplyDiffPatchFileOptions{}), repo.ApplyDiffPatch)
|
||||
m.Group("/contents", func() {
|
||||
m.Get("", repo.GetContentsList)
|
||||
m.Get("/*", repo.GetContents)
|
||||
@ -1070,15 +1104,15 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
m.Post("", bind(api.CreateFileOptions{}), reqRepoBranchWriter, repo.CreateFile)
|
||||
m.Put("", bind(api.UpdateFileOptions{}), reqRepoBranchWriter, repo.UpdateFile)
|
||||
m.Delete("", bind(api.DeleteFileOptions{}), reqRepoBranchWriter, repo.DeleteFile)
|
||||
}, reqToken())
|
||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
||||
}, reqRepoReader(unit.TypeCode))
|
||||
m.Get("/signing-key.gpg", misc.SigningKey)
|
||||
m.Group("/topics", func() {
|
||||
m.Combo("").Get(repo.ListTopics).
|
||||
Put(reqToken(), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics)
|
||||
Put(reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics)
|
||||
m.Group("/{topic}", func() {
|
||||
m.Combo("").Put(reqToken(), repo.AddTopic).
|
||||
Delete(reqToken(), repo.DeleteTopic)
|
||||
m.Combo("").Put(reqToken(auth_model.AccessTokenScopeRepo), repo.AddTopic).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), repo.DeleteTopic)
|
||||
}, reqAdmin())
|
||||
}, reqAnyRepoReader())
|
||||
m.Get("/issue_templates", context.ReferencesGitRepo(), repo.GetIssueTemplates)
|
||||
@ -1089,49 +1123,49 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
// NOTE: these are Gitea package management API - see packages.CommonRoutes and packages.DockerContainerRoutes for endpoints that implement package manager APIs
|
||||
m.Group("/packages/{username}", func() {
|
||||
m.Group("/{type}/{name}/{version}", func() {
|
||||
m.Get("", packages.GetPackage)
|
||||
m.Delete("", reqPackageAccess(perm.AccessModeWrite), packages.DeletePackage)
|
||||
m.Get("/files", packages.ListPackageFiles)
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadPackage), packages.GetPackage)
|
||||
m.Delete("", reqToken(auth_model.AccessTokenScopeDeletePackage), reqPackageAccess(perm.AccessModeWrite), packages.DeletePackage)
|
||||
m.Get("/files", reqToken(auth_model.AccessTokenScopeReadPackage), packages.ListPackageFiles)
|
||||
})
|
||||
m.Get("/", packages.ListPackages)
|
||||
m.Get("/", reqToken(auth_model.AccessTokenScopeReadPackage), packages.ListPackages)
|
||||
}, context_service.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead))
|
||||
|
||||
// Organizations
|
||||
m.Get("/user/orgs", reqToken(), org.ListMyOrgs)
|
||||
m.Get("/user/orgs", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListMyOrgs)
|
||||
m.Group("/users/{username}/orgs", func() {
|
||||
m.Get("", org.ListUserOrgs)
|
||||
m.Get("/{org}/permissions", reqToken(), org.GetUserOrgsPermissions)
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListUserOrgs)
|
||||
m.Get("/{org}/permissions", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetUserOrgsPermissions)
|
||||
}, context_service.UserAssignmentAPI())
|
||||
m.Post("/orgs", reqToken(), bind(api.CreateOrgOption{}), org.Create)
|
||||
m.Get("/orgs", org.GetAll)
|
||||
m.Post("/orgs", reqToken(auth_model.AccessTokenScopeWriteOrg), bind(api.CreateOrgOption{}), org.Create)
|
||||
m.Get("/orgs", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetAll)
|
||||
m.Group("/orgs/{org}", func() {
|
||||
m.Combo("").Get(org.Get).
|
||||
Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
|
||||
Delete(reqToken(), reqOrgOwnership(), org.Delete)
|
||||
m.Combo("/repos").Get(user.ListOrgRepos).
|
||||
Post(reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
|
||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.Get).
|
||||
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.Delete)
|
||||
m.Combo("/repos").Get(reqToken(auth_model.AccessTokenScopeReadOrg), user.ListOrgRepos).
|
||||
Post(reqToken(auth_model.AccessTokenScopeWriteOrg), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
|
||||
m.Group("/members", func() {
|
||||
m.Get("", org.ListMembers)
|
||||
m.Combo("/{username}").Get(org.IsMember).
|
||||
Delete(reqToken(), reqOrgOwnership(), org.DeleteMember)
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListMembers)
|
||||
m.Combo("/{username}").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.IsMember).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.DeleteMember)
|
||||
})
|
||||
m.Group("/public_members", func() {
|
||||
m.Get("", org.ListPublicMembers)
|
||||
m.Combo("/{username}").Get(org.IsPublicMember).
|
||||
Put(reqToken(), reqOrgMembership(), org.PublicizeMember).
|
||||
Delete(reqToken(), reqOrgMembership(), org.ConcealMember)
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListPublicMembers)
|
||||
m.Combo("/{username}").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.IsPublicMember).
|
||||
Put(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgMembership(), org.PublicizeMember).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgMembership(), org.ConcealMember)
|
||||
})
|
||||
m.Group("/teams", func() {
|
||||
m.Get("", org.ListTeams)
|
||||
m.Post("", reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam)
|
||||
m.Get("/search", org.SearchTeam)
|
||||
}, reqToken(), reqOrgMembership())
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListTeams)
|
||||
m.Post("", reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam)
|
||||
m.Get("/search", reqToken(auth_model.AccessTokenScopeReadOrg), org.SearchTeam)
|
||||
}, reqOrgMembership())
|
||||
m.Group("/labels", func() {
|
||||
m.Get("", org.ListLabels)
|
||||
m.Post("", reqToken(), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel)
|
||||
m.Combo("/{id}").Get(org.GetLabel).
|
||||
Patch(reqToken(), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel).
|
||||
Delete(reqToken(), reqOrgOwnership(), org.DeleteLabel)
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListLabels)
|
||||
m.Post("", reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel)
|
||||
m.Combo("/{id}").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetLabel).
|
||||
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.DeleteLabel)
|
||||
})
|
||||
m.Group("/hooks", func() {
|
||||
m.Combo("").Get(org.ListHooks).
|
||||
@ -1139,27 +1173,27 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
m.Combo("/{id}").Get(org.GetHook).
|
||||
Patch(bind(api.EditHookOption{}), org.EditHook).
|
||||
Delete(org.DeleteHook)
|
||||
}, reqToken(), reqOrgOwnership(), reqWebhooksEnabled())
|
||||
}, reqToken(auth_model.AccessTokenScopeAdminOrgHook), reqOrgOwnership(), reqWebhooksEnabled())
|
||||
}, orgAssignment(true))
|
||||
m.Group("/teams/{teamid}", func() {
|
||||
m.Combo("").Get(org.GetTeam).
|
||||
Patch(reqOrgOwnership(), bind(api.EditTeamOption{}), org.EditTeam).
|
||||
Delete(reqOrgOwnership(), org.DeleteTeam)
|
||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeam).
|
||||
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditTeamOption{}), org.EditTeam).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.DeleteTeam)
|
||||
m.Group("/members", func() {
|
||||
m.Get("", org.GetTeamMembers)
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamMembers)
|
||||
m.Combo("/{username}").
|
||||
Get(org.GetTeamMember).
|
||||
Put(reqOrgOwnership(), org.AddTeamMember).
|
||||
Delete(reqOrgOwnership(), org.RemoveTeamMember)
|
||||
Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamMember).
|
||||
Put(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.AddTeamMember).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.RemoveTeamMember)
|
||||
})
|
||||
m.Group("/repos", func() {
|
||||
m.Get("", org.GetTeamRepos)
|
||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamRepos)
|
||||
m.Combo("/{org}/{reponame}").
|
||||
Put(org.AddTeamRepository).
|
||||
Delete(org.RemoveTeamRepository).
|
||||
Get(org.GetTeamRepo)
|
||||
Put(reqToken(auth_model.AccessTokenScopeWriteOrg), org.AddTeamRepository).
|
||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), org.RemoveTeamRepository).
|
||||
Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamRepo)
|
||||
})
|
||||
}, orgAssignment(false, true), reqToken(), reqTeamMembership())
|
||||
}, orgAssignment(false, true), reqToken(""), reqTeamMembership())
|
||||
|
||||
m.Group("/admin", func() {
|
||||
m.Group("/cron", func() {
|
||||
@ -1187,7 +1221,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
m.Post("/{username}/{reponame}", admin.AdoptRepository)
|
||||
m.Delete("/{username}/{reponame}", admin.DeleteUnadoptedRepository)
|
||||
})
|
||||
}, reqToken(), reqSiteAdmin())
|
||||
}, reqToken(auth_model.AccessTokenScopeSudo), reqSiteAdmin())
|
||||
|
||||
m.Group("/topics", func() {
|
||||
m.Get("/search", repo.TopicSearch)
|
||||
|
@ -5,9 +5,11 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
system_model "code.gitea.io/gitea/models/system"
|
||||
@ -201,6 +203,16 @@ func ChangeConfig(ctx *context.Context) {
|
||||
value := ctx.FormString("value")
|
||||
version := ctx.FormInt("version")
|
||||
|
||||
if check, ok := changeConfigChecks[key]; ok {
|
||||
if err := check(ctx, value); err != nil {
|
||||
log.Warn("refused to set setting: %v", err)
|
||||
ctx.JSON(http.StatusOK, map[string]string{
|
||||
"err": ctx.Tr("admin.config.set_setting_failed", key),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := system_model.SetSetting(&system_model.Setting{
|
||||
SettingKey: key,
|
||||
SettingValue: value,
|
||||
@ -217,3 +229,18 @@ func ChangeConfig(ctx *context.Context) {
|
||||
"version": version + 1,
|
||||
})
|
||||
}
|
||||
|
||||
var changeConfigChecks = map[string]func(ctx *context.Context, newValue string) error{
|
||||
system_model.KeyPictureDisableGravatar: func(_ *context.Context, newValue string) error {
|
||||
if v, _ := strconv.ParseBool(newValue); setting.OfflineMode && !v {
|
||||
return fmt.Errorf("%q should be true when OFFLINE_MODE is true", system_model.KeyPictureDisableGravatar)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
system_model.KeyPictureEnableFederatedAvatar: func(_ *context.Context, newValue string) error {
|
||||
if v, _ := strconv.ParseBool(newValue); setting.OfflineMode && v {
|
||||
return fmt.Errorf("%q cannot be false when OFFLINE_MODE is true", system_model.KeyPictureEnableFederatedAvatar)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -42,9 +42,15 @@ func ApplicationsPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
scope, err := form.GetScope()
|
||||
if err != nil {
|
||||
ctx.ServerError("GetScope", err)
|
||||
return
|
||||
}
|
||||
t := &auth_model.AccessToken{
|
||||
UID: ctx.Doer.ID,
|
||||
Name: form.Name,
|
||||
UID: ctx.Doer.ID,
|
||||
Name: form.Name,
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
exist, err := auth_model.AccessTokenByNameExists(t)
|
||||
|
@ -59,6 +59,8 @@ func (o *OAuth2) Name() string {
|
||||
}
|
||||
|
||||
// userIDFromToken returns the user id corresponding to the OAuth token.
|
||||
// It will set 'IsApiToken' to true if the token is an API token and
|
||||
// set 'ApiTokenScope' to the scope of the access token
|
||||
func (o *OAuth2) userIDFromToken(req *http.Request, store DataStore) int64 {
|
||||
_ = req.ParseForm()
|
||||
|
||||
@ -86,6 +88,7 @@ func (o *OAuth2) userIDFromToken(req *http.Request, store DataStore) int64 {
|
||||
uid := CheckOAuthAccessToken(tokenSHA)
|
||||
if uid != 0 {
|
||||
store.GetData()["IsApiToken"] = true
|
||||
store.GetData()["ApiTokenScope"] = auth_model.AccessTokenScopeAll // fallback to all
|
||||
}
|
||||
return uid
|
||||
}
|
||||
@ -101,6 +104,7 @@ func (o *OAuth2) userIDFromToken(req *http.Request, store DataStore) int64 {
|
||||
log.Error("UpdateAccessToken: %v", err)
|
||||
}
|
||||
store.GetData()["IsApiToken"] = true
|
||||
store.GetData()["ApiTokenScope"] = t.Scope
|
||||
return t.UID
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,10 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u
|
||||
},
|
||||
}
|
||||
|
||||
if pr.Issue.ClosedUnix != 0 {
|
||||
apiPullRequest.Closed = pr.Issue.ClosedUnix.AsTimePtr()
|
||||
}
|
||||
|
||||
gitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath())
|
||||
if err != nil {
|
||||
log.Error("OpenRepository[%s]: %v", pr.BaseRepo.RepoPath(), err)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
@ -377,7 +378,8 @@ func (f *AddSecretForm) Validate(req *http.Request, errs binding.Errors) binding
|
||||
|
||||
// NewAccessTokenForm form for creating access token
|
||||
type NewAccessTokenForm struct {
|
||||
Name string `binding:"Required;MaxSize(255)"`
|
||||
Name string `binding:"Required;MaxSize(255)"`
|
||||
Scope []string
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
@ -386,6 +388,12 @@ func (f *NewAccessTokenForm) Validate(req *http.Request, errs binding.Errors) bi
|
||||
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
func (f *NewAccessTokenForm) GetScope() (auth_model.AccessTokenScope, error) {
|
||||
scope := strings.Join(f.Scope, ",")
|
||||
s, err := auth_model.AccessTokenScope(scope).Normalize()
|
||||
return s, err
|
||||
}
|
||||
|
||||
// EditOAuth2ApplicationForm form for editing oauth2 applications
|
||||
type EditOAuth2ApplicationForm struct {
|
||||
Name string `binding:"Required;MaxSize(255)" form:"application_name"`
|
||||
|
@ -4,8 +4,10 @@
|
||||
package forms
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -83,3 +85,28 @@ func TestRegisterForm_IsDomainAllowed_BlocklistedEmail(t *testing.T) {
|
||||
assert.Equal(t, v.valid, form.IsEmailDomainAllowed())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAccessTokenForm_GetScope(t *testing.T) {
|
||||
tests := []struct {
|
||||
form NewAccessTokenForm
|
||||
scope auth_model.AccessTokenScope
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
form: NewAccessTokenForm{Name: "test", Scope: []string{"repo"}},
|
||||
scope: "repo",
|
||||
},
|
||||
{
|
||||
form: NewAccessTokenForm{Name: "test", Scope: []string{"repo", "user"}},
|
||||
scope: "repo,user",
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
scope, err := test.form.GetScope()
|
||||
assert.Equal(t, test.expectedErr, err)
|
||||
assert.Equal(t, test.scope, scope)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -33,10 +33,14 @@ func (f *GitBucketDownloaderFactory) New(ctx context.Context, opts base.MigrateO
|
||||
return nil, err
|
||||
}
|
||||
|
||||
baseURL := u.Scheme + "://" + u.Host
|
||||
fields := strings.Split(u.Path, "/")
|
||||
oldOwner := fields[1]
|
||||
oldName := strings.TrimSuffix(fields[2], ".git")
|
||||
if len(fields) < 2 {
|
||||
return nil, fmt.Errorf("invalid path: %s", u.Path)
|
||||
}
|
||||
baseURL := u.Scheme + "://" + u.Host + strings.TrimSuffix(strings.Join(fields[:len(fields)-2], "/"), "/git")
|
||||
|
||||
oldOwner := fields[len(fields)-2]
|
||||
oldName := strings.TrimSuffix(fields[len(fields)-1], ".git")
|
||||
|
||||
log.Trace("Create GitBucket downloader. BaseURL: %s RepoOwner: %s RepoName: %s", baseURL, oldOwner, oldName)
|
||||
return NewGitBucketDownloader(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, oldOwner, oldName), nil
|
||||
@ -71,6 +75,7 @@ func (g *GitBucketDownloader) ColorFormat(s fmt.State) {
|
||||
func NewGitBucketDownloader(ctx context.Context, baseURL, userName, password, token, repoOwner, repoName string) *GitBucketDownloader {
|
||||
githubDownloader := NewGithubDownloaderV3(ctx, baseURL, userName, password, token, repoOwner, repoName)
|
||||
githubDownloader.SkipReactions = true
|
||||
githubDownloader.SkipReviews = true
|
||||
return &GitBucketDownloader{
|
||||
githubDownloader,
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ type GithubDownloaderV3 struct {
|
||||
curClientIdx int
|
||||
maxPerPage int
|
||||
SkipReactions bool
|
||||
SkipReviews bool
|
||||
}
|
||||
|
||||
// NewGithubDownloaderV3 creates a github Downloader via github v3 API
|
||||
@ -809,6 +810,9 @@ func (g *GithubDownloaderV3) convertGithubReviewComments(cs []*github.PullReques
|
||||
// GetReviews returns pull requests review
|
||||
func (g *GithubDownloaderV3) GetReviews(reviewable base.Reviewable) ([]*base.Review, error) {
|
||||
allReviews := make([]*base.Review, 0, g.maxPerPage)
|
||||
if g.SkipReviews {
|
||||
return allReviews, nil
|
||||
}
|
||||
opt := &github.ListOptions{
|
||||
PerPage: g.maxPerPage,
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ func checkForInvalidation(ctx context.Context, requests issues_model.PullRequest
|
||||
}
|
||||
go func() {
|
||||
// FIXME: graceful: We need to tell the manager we're doing something...
|
||||
err := requests.InvalidateCodeComments(ctx, doer, gitRepo, branch)
|
||||
err := InvalidateCodeComments(ctx, requests, doer, gitRepo, branch)
|
||||
if err != nil {
|
||||
log.Error("PullRequestList.InvalidateCodeComments: %v", err)
|
||||
}
|
||||
|
@ -23,6 +23,53 @@ import (
|
||||
issue_service "code.gitea.io/gitea/services/issue"
|
||||
)
|
||||
|
||||
var notEnoughLines = regexp.MustCompile(`fatal: file .* has only \d+ lines?`)
|
||||
|
||||
// checkInvalidation checks if the line of code comment got changed by another commit.
|
||||
// If the line got changed the comment is going to be invalidated.
|
||||
func checkInvalidation(ctx context.Context, c *issues_model.Comment, doer *user_model.User, repo *git.Repository, branch string) error {
|
||||
// FIXME differentiate between previous and proposed line
|
||||
commit, err := repo.LineBlame(branch, repo.Path, c.TreePath, uint(c.UnsignedLine()))
|
||||
if err != nil && (strings.Contains(err.Error(), "fatal: no such path") || notEnoughLines.MatchString(err.Error())) {
|
||||
c.Invalidated = true
|
||||
return issues_model.UpdateCommentInvalidate(ctx, c)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.CommitSHA != "" && c.CommitSHA != commit.ID.String() {
|
||||
c.Invalidated = true
|
||||
return issues_model.UpdateCommentInvalidate(ctx, c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InvalidateCodeComments will lookup the prs for code comments which got invalidated by change
|
||||
func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestList, doer *user_model.User, repo *git.Repository, branch string) error {
|
||||
if len(prs) == 0 {
|
||||
return nil
|
||||
}
|
||||
issueIDs := prs.GetIssueIDs()
|
||||
var codeComments []*issues_model.Comment
|
||||
|
||||
if err := db.Find(ctx, &issues_model.FindCommentsOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
Type: issues_model.CommentTypeCode,
|
||||
Invalidated: util.OptionalBoolFalse,
|
||||
IssueIDs: issueIDs,
|
||||
}, &codeComments); err != nil {
|
||||
return fmt.Errorf("find code comments: %v", err)
|
||||
}
|
||||
for _, comment := range codeComments {
|
||||
if err := checkInvalidation(ctx, comment, doer, repo, branch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateCodeComment creates a comment on the code line
|
||||
func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue, line int64, content, treePath string, isReview bool, replyReviewID int64, latestCommitID string) (*issues_model.Comment, error) {
|
||||
var (
|
||||
@ -114,8 +161,6 @@ func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.
|
||||
return comment, nil
|
||||
}
|
||||
|
||||
var notEnoughLines = regexp.MustCompile(`exit status 128 - fatal: file .* has only \d+ lines?`)
|
||||
|
||||
// createCodeComment creates a plain code comment at the specified line / path
|
||||
func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, treePath string, line, reviewID int64) (*issues_model.Comment, error) {
|
||||
var commitID, patch string
|
||||
|
@ -22,7 +22,7 @@
|
||||
<script src='https://hcaptcha.com/1/api.js' async></script>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<script src="{{AssetUrlPrefix}}/js/index.js?v={{AssetVersion}}" onerror="alert('Failed to load asset files from ' + this.src + ', please make sure the asset files can be accessed and the ROOT_URL setting in app.ini is correct.')"></script>
|
||||
<script src="{{AssetUrlPrefix}}/js/index.js?v={{AssetVersion}}" onerror="alert('Failed to load asset files from ' + this.src + '. Please make sure the asset files can be accessed.')"></script>
|
||||
{{template "custom/footer" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
@ -41,6 +41,207 @@
|
||||
<label for="name">{{.locale.Tr "settings.token_name"}}</label>
|
||||
<input id="name" name="name" value="{{.name}}" autofocus required>
|
||||
</div>
|
||||
<details class="ui optional field">
|
||||
<summary class="p-2">
|
||||
{{.locale.Tr "settings.select_scopes"}}
|
||||
</summary>
|
||||
<div class="field pl-2">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="repo">
|
||||
<label>repo</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field pl-4">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="repo:status">
|
||||
<label>repo:status</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="public:repo">
|
||||
<label>public_repo</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="admin:org">
|
||||
<label>admin:org</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field pl-4">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="write:org">
|
||||
<label>write:org</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="read:public_key">
|
||||
<label>read:public_key</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="admin:public_key">
|
||||
<label>admin:public_key</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field pl-4">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="write:public_key">
|
||||
<label>write:public_key</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="read:public_key">
|
||||
<label>read:public_key</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="admin:repo_hook">
|
||||
<label>admin:repo_hook</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field pl-4">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="write:repo_hook">
|
||||
<label>write:repo_hook</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="read:repo_hook">
|
||||
<label>read:repo_hook</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="admin:org_hook">
|
||||
<label>admin:org_hook</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="notification">
|
||||
<label>notification</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="user">
|
||||
<label>user</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field pl-4">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="read:user">
|
||||
<label>read:user</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="user:email">
|
||||
<label>user:email</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="user:follow">
|
||||
<label>user:follow</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="delete:repo">
|
||||
<label>delete_repo</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="package">
|
||||
<label>package</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field pl-4">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="write:package">
|
||||
<label>write:package</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="read:package">
|
||||
<label>read:package</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="delete:package">
|
||||
<label>delete:package</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="admin:gpg_key">
|
||||
<label>admin:gpg_key</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field pl-4">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="write:gpg_key">
|
||||
<label>write:gpg_key</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="read:gpg_key">
|
||||
<label>read:gpg_key</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="admin:application">
|
||||
<label>admin:application</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field pl-4">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="write:application">
|
||||
<label>write:application</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="read:application">
|
||||
<label>read:application</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="enable-system" type="checkbox" name="scope" value="sudo">
|
||||
<label>sudo</label>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
<button class="ui green button">
|
||||
{{.locale.Tr "settings.generate_token"}}
|
||||
</button>
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
@ -20,7 +21,7 @@ import (
|
||||
func TestAPIAdminOrgCreate(t *testing.T) {
|
||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeSudo)
|
||||
|
||||
org := api.CreateOrgOption{
|
||||
UserName: "user2_org",
|
||||
@ -54,7 +55,7 @@ func TestAPIAdminOrgCreate(t *testing.T) {
|
||||
func TestAPIAdminOrgCreateBadVisibility(t *testing.T) {
|
||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeSudo)
|
||||
|
||||
org := api.CreateOrgOption{
|
||||
UserName: "user2_org",
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
@ -24,7 +25,7 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||
session := loginUser(t, "user1")
|
||||
keyOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
|
||||
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeSudo)
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", keyOwner.Name, token)
|
||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment\n",
|
||||
@ -51,7 +52,7 @@ func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
// user1 is an admin user
|
||||
token := getUserToken(t, "user1")
|
||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeSudo)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d?token=%s", unittest.NonexistentID, token)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
@ -60,7 +61,7 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
adminUsername := "user1"
|
||||
normalUsername := "user2"
|
||||
token := getUserToken(t, adminUsername)
|
||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", adminUsername, token)
|
||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||
@ -81,7 +82,7 @@ func TestAPISudoUser(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
adminUsername := "user1"
|
||||
normalUsername := "user2"
|
||||
token := getUserToken(t, adminUsername)
|
||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s&token=%s", normalUsername, token)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
@ -97,7 +98,7 @@ func TestAPISudoUserForbidden(t *testing.T) {
|
||||
adminUsername := "user1"
|
||||
normalUsername := "user2"
|
||||
|
||||
token := getUserToken(t, normalUsername)
|
||||
token := getUserToken(t, normalUsername, auth_model.AccessTokenScopeSudo)
|
||||
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s&token=%s", adminUsername, token)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
@ -106,7 +107,7 @@ func TestAPISudoUserForbidden(t *testing.T) {
|
||||
func TestAPIListUsers(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
adminUsername := "user1"
|
||||
token := getUserToken(t, adminUsername)
|
||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users?token=%s", token)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
@ -142,7 +143,7 @@ func TestAPIListUsersNonAdmin(t *testing.T) {
|
||||
func TestAPICreateUserInvalidEmail(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
adminUsername := "user1"
|
||||
token := getUserToken(t, adminUsername)
|
||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users?token=%s", token)
|
||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||
"email": "invalid_email@domain.com\r\n",
|
||||
@ -160,7 +161,7 @@ func TestAPICreateUserInvalidEmail(t *testing.T) {
|
||||
func TestAPICreateAndDeleteUser(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
adminUsername := "user1"
|
||||
token := getUserToken(t, adminUsername)
|
||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
||||
|
||||
req := NewRequestWithValues(
|
||||
t,
|
||||
@ -186,7 +187,7 @@ func TestAPICreateAndDeleteUser(t *testing.T) {
|
||||
func TestAPIEditUser(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
adminUsername := "user1"
|
||||
token := getUserToken(t, adminUsername)
|
||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s?token=%s", "user2", token)
|
||||
|
||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||
@ -228,7 +229,7 @@ func TestAPIEditUser(t *testing.T) {
|
||||
func TestAPICreateRepoForUser(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
adminUsername := "user1"
|
||||
token := getUserToken(t, adminUsername)
|
||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
||||
|
||||
req := NewRequestWithJSON(
|
||||
t,
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -15,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
|
||||
token := getUserToken(t, "user2")
|
||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token)
|
||||
resp := MakeRequest(t, req, NoExpectedStatus)
|
||||
if !exists {
|
||||
@ -31,7 +32,7 @@ func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
|
||||
}
|
||||
|
||||
func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||
token := getUserToken(t, "user2")
|
||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token)
|
||||
resp := MakeRequest(t, req, expectedHTTPStatus)
|
||||
|
||||
@ -43,7 +44,7 @@ func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPSta
|
||||
}
|
||||
|
||||
func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||
token := getUserToken(t, "user2")
|
||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections?token="+token, &api.BranchProtection{
|
||||
RuleName: branchName,
|
||||
})
|
||||
@ -57,7 +58,7 @@ func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTP
|
||||
}
|
||||
|
||||
func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.BranchProtection, expectedHTTPStatus int) {
|
||||
token := getUserToken(t, "user2")
|
||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, "PATCH", "/api/v1/repos/user2/repo1/branch_protections/"+branchName+"?token="+token, body)
|
||||
resp := MakeRequest(t, req, expectedHTTPStatus)
|
||||
|
||||
@ -69,13 +70,13 @@ func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.Bran
|
||||
}
|
||||
|
||||
func testAPIDeleteBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||
token := getUserToken(t, "user2")
|
||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token)
|
||||
MakeRequest(t, req, expectedHTTPStatus)
|
||||
}
|
||||
|
||||
func testAPIDeleteBranch(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||
token := getUserToken(t, "user2")
|
||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token)
|
||||
MakeRequest(t, req, expectedHTTPStatus)
|
||||
}
|
||||
@ -101,7 +102,7 @@ func TestAPICreateBranch(t *testing.T) {
|
||||
|
||||
func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
|
||||
username := "user2"
|
||||
ctx := NewAPITestContext(t, username, "my-noo-repo")
|
||||
ctx := NewAPITestContext(t, username, "my-noo-repo", auth_model.AccessTokenScopeRepo)
|
||||
giteaURL.Path = ctx.GitPath()
|
||||
|
||||
t.Run("CreateRepo", doAPICreateRepository(ctx, false))
|
||||
@ -149,7 +150,7 @@ func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
|
||||
}
|
||||
|
||||
func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBranch, newBranch string, status int) bool {
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+user+"/"+repo+"/branches?token="+token, &api.CreateBranchRepoOption{
|
||||
BranchName: newBranch,
|
||||
OldBranchName: oldBranch,
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -81,7 +82,7 @@ func TestAPICreateCommentAttachment(t *testing.T) {
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets?token=%s",
|
||||
repoOwner.Name, repo.Name, comment.ID, token)
|
||||
|
||||
@ -120,7 +121,7 @@ func TestAPIEditCommentAttachment(t *testing.T) {
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s",
|
||||
repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||
@ -143,7 +144,7 @@ func TestAPIDeleteCommentAttachment(t *testing.T) {
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s",
|
||||
repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
||||
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -75,8 +76,9 @@ func TestAPIListIssueComments(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/comments",
|
||||
repoOwner.Name, repo.Name, issue.Index)
|
||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/comments?token=%s",
|
||||
repoOwner.Name, repo.Name, issue.Index, token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var comments []*api.Comment
|
||||
@ -94,7 +96,7 @@ func TestAPICreateComment(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
token := getUserToken(t, repoOwner.Name)
|
||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments?token=%s",
|
||||
repoOwner.Name, repo.Name, issue.Index, token)
|
||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||
@ -116,7 +118,7 @@ func TestAPIGetComment(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID})
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
token := getUserToken(t, repoOwner.Name)
|
||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s", repoOwner.Name, repo.Name, comment.ID, token)
|
||||
@ -144,7 +146,7 @@ func TestAPIEditComment(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
token := getUserToken(t, repoOwner.Name)
|
||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
|
||||
repoOwner.Name, repo.Name, comment.ID, token)
|
||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||
@ -168,7 +170,7 @@ func TestAPIDeleteComment(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
token := getUserToken(t, repoOwner.Name)
|
||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
|
||||
repoOwner.Name, repo.Name, comment.ID, token)
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -20,7 +21,8 @@ type makeRequestFunc func(testing.TB, *http.Request, int) *httptest.ResponseReco
|
||||
func TestGPGKeys(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
tokenWithGPGKeyScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminGPGKey, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
@ -34,6 +36,10 @@ func TestGPGKeys(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "LoggedAsUser2", makeRequest: session.MakeRequest, token: token,
|
||||
results: []int{http.StatusForbidden, http.StatusOK, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden},
|
||||
},
|
||||
{
|
||||
name: "LoggedAsUser2WithScope", makeRequest: session.MakeRequest, token: tokenWithGPGKeyScope,
|
||||
results: []int{http.StatusOK, http.StatusOK, http.StatusNotFound, http.StatusNoContent, http.StatusUnprocessableEntity, http.StatusNotFound, http.StatusCreated, http.StatusNotFound, http.StatusCreated},
|
||||
},
|
||||
}
|
||||
@ -73,7 +79,7 @@ func TestGPGKeys(t *testing.T) {
|
||||
t.Run("CheckState", func(t *testing.T) {
|
||||
var keys []*api.GPGKey
|
||||
|
||||
req := NewRequest(t, "GET", "/api/v1/user/gpg_keys?token="+token) // GET all keys
|
||||
req := NewRequest(t, "GET", "/api/v1/user/gpg_keys?token="+tokenWithGPGKeyScope) // GET all keys
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &keys)
|
||||
assert.Len(t, keys, 1)
|
||||
@ -89,7 +95,7 @@ func TestGPGKeys(t *testing.T) {
|
||||
assert.Empty(t, subKey.Emails)
|
||||
|
||||
var key api.GPGKey
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(primaryKey1.ID, 10)+"?token="+token) // Primary key 1
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(primaryKey1.ID, 10)+"?token="+tokenWithGPGKeyScope) // Primary key 1
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &key)
|
||||
assert.EqualValues(t, "38EA3BCED732982C", key.KeyID)
|
||||
@ -97,7 +103,7 @@ func TestGPGKeys(t *testing.T) {
|
||||
assert.EqualValues(t, "user2@example.com", key.Emails[0].Email)
|
||||
assert.True(t, key.Emails[0].Verified)
|
||||
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(subKey.ID, 10)+"?token="+token) // Subkey of 38EA3BCED732982C
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(subKey.ID, 10)+"?token="+tokenWithGPGKeyScope) // Subkey of 38EA3BCED732982C
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &key)
|
||||
assert.EqualValues(t, "70D7C694D17D03AD", key.KeyID)
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
@ -31,9 +32,9 @@ type APITestContext struct {
|
||||
ExpectedCode int
|
||||
}
|
||||
|
||||
func NewAPITestContext(t *testing.T, username, reponame string) APITestContext {
|
||||
func NewAPITestContext(t *testing.T, username, reponame string, scope ...auth.AccessTokenScope) APITestContext {
|
||||
session := loginUser(t, username)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, scope...)
|
||||
return APITestContext{
|
||||
Session: session,
|
||||
Token: token,
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -52,7 +53,7 @@ func TestHTTPSigPubKey(t *testing.T) {
|
||||
// Add our public key to user1
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
session := loginUser(t, "user1")
|
||||
token := url.QueryEscape(getTokenForLoggedInUser(t, session))
|
||||
token := url.QueryEscape(getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminPublicKey, auth_model.AccessTokenScopeSudo))
|
||||
keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)
|
||||
keyType := "ssh-rsa"
|
||||
keyContent := "AAAAB3NzaC1yc2EAAAADAQABAAABAQCqOZB5vkRvXFXups1/0StDRdG8plbNSwsWEnNnP4Bvurxa0+z3W9B8GLKnDiLw5MbpbMNyBlpXw13GfuIeciy10DWTz0xUbiy3J3KabCaT36asIw2y7k6Z0jL0UBnrVENwq5/lUbZYqSZ4rRU744wkhh8TULpzM14npQCZwg6aEbG+MwjzddQ72fR+3BPBrKn5dTmmu8rH99O+U+Nuto81Tg7PA+NUupcHOmhdiEGq49plgVFXK98Vks5tiybL4GuzFyWgyX73Dg/QBMn2eMHt1EMv5Gs3i6GFhKKGo4rjDi9qI6PX5oDR4LTNe6cR8td8YhVD8WFZwLLl/vaYyIqd"
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -72,7 +73,7 @@ func TestAPICreateIssueAttachment(t *testing.T) {
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets?token=%s",
|
||||
repoOwner.Name, repo.Name, issue.Index, token)
|
||||
|
||||
@ -110,7 +111,7 @@ func TestAPIEditIssueAttachment(t *testing.T) {
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d?token=%s",
|
||||
repoOwner.Name, repo.Name, issue.Index, attachment.ID, token)
|
||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||
@ -132,7 +133,7 @@ func TestAPIDeleteIssueAttachment(t *testing.T) {
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d?token=%s",
|
||||
repoOwner.Name, repo.Name, issue.Index, attachment.ID, token)
|
||||
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -24,7 +25,7 @@ func TestAPIModifyLabels(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/labels?token=%s", owner.Name, repo.Name, token)
|
||||
|
||||
// CreateLabel
|
||||
@ -96,7 +97,7 @@ func TestAPIAddIssueLabels(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels?token=%s",
|
||||
repo.OwnerName, repo.Name, issue.Index, token)
|
||||
req := NewRequestWithJSON(t, "POST", urlStr, &api.IssueLabelsOption{
|
||||
@ -119,7 +120,7 @@ func TestAPIReplaceIssueLabels(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels?token=%s",
|
||||
owner.Name, repo.Name, issue.Index, token)
|
||||
req := NewRequestWithJSON(t, "PUT", urlStr, &api.IssueLabelsOption{
|
||||
@ -143,7 +144,7 @@ func TestAPIModifyOrgLabels(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
user := "user1"
|
||||
session := loginUser(t, user)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeAdminOrg)
|
||||
urlStr := fmt.Sprintf("/api/v1/orgs/%s/labels?token=%s", owner.Name, token)
|
||||
|
||||
// CreateLabel
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -28,7 +29,7 @@ func TestAPIIssuesMilestone(t *testing.T) {
|
||||
assert.Equal(t, structs.StateOpen, milestone.State())
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// update values of issue
|
||||
milestoneState := "closed"
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -28,7 +29,7 @@ func TestAPIIssuesReactions(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/reactions?token=%s",
|
||||
@ -87,7 +88,7 @@ func TestAPICommentReactions(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -25,7 +26,7 @@ func TestAPIListStopWatches(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "GET", "/api/v1/user/stopwatches?token=%s", token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
var apiWatches []*api.StopWatch
|
||||
@ -51,7 +52,7 @@ func TestAPIStopStopWatches(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestf(t, "POST", "/api/v1/repos/%s/%s/issues/%d/stopwatch/stop?token=%s", owner.Name, issue.Repo.Name, issue.Index, token)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
@ -67,7 +68,7 @@ func TestAPICancelStopWatches(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/%d/stopwatch/delete?token=%s", owner.Name, issue.Repo.Name, issue.Index, token)
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
@ -83,7 +84,7 @@ func TestAPIStartStopWatches(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestf(t, "POST", "/api/v1/repos/%s/%s/issues/%d/stopwatch/start?token=%s", owner.Name, issue.Repo.Name, issue.Index, token)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -30,7 +31,7 @@ func TestAPIIssueSubscriptions(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue1.PosterID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
testSubscription := func(issue *issues_model.Issue, isWatching bool) {
|
||||
issueRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -29,7 +30,7 @@ func TestAPIListIssues(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/issues", owner.Name, repo.Name))
|
||||
|
||||
link.RawQuery = url.Values{"token": {token}, "state": {"all"}}.Encode()
|
||||
@ -80,7 +81,7 @@ func TestAPICreateIssue(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all&token=%s", owner.Name, repoBefore.Name, token)
|
||||
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{
|
||||
Body: body,
|
||||
@ -116,7 +117,7 @@ func TestAPIEditIssue(t *testing.T) {
|
||||
assert.Equal(t, api.StateOpen, issueBefore.State())
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// update values of issue
|
||||
issueState := "closed"
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -27,7 +28,7 @@ func TestAPIGetTrackedTimes(t *testing.T) {
|
||||
assert.NoError(t, issue2.LoadRepo(db.DefaultContext))
|
||||
|
||||
session := loginUser(t, user2.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/times?token=%s", user2.Name, issue2.Repo.Name, issue2.Index, token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
@ -70,7 +71,7 @@ func TestAPIDeleteTrackedTime(t *testing.T) {
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
session := loginUser(t, user2.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Deletion not allowed
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/%d/times/%d?token=%s", user2.Name, issue2.Repo.Name, issue2.Index, time6.ID, token)
|
||||
@ -105,7 +106,7 @@ func TestAPIAddTrackedTimes(t *testing.T) {
|
||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
|
||||
session := loginUser(t, admin.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/times?token=%s", user2.Name, issue2.Repo.Name, issue2.Index, token)
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -53,7 +54,7 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", repoOwner.Name, repo.Name, token)
|
||||
rawKeyBody := api.CreateKeyOption{
|
||||
Title: "read-only",
|
||||
@ -79,7 +80,7 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", repoOwner.Name, repo.Name, token)
|
||||
rawKeyBody := api.CreateKeyOption{
|
||||
Title: "read-write",
|
||||
@ -103,7 +104,7 @@ func TestCreateUserKey(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
token := url.QueryEscape(getTokenForLoggedInUser(t, session))
|
||||
token := url.QueryEscape(getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminPublicKey))
|
||||
keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)
|
||||
keyType := "ssh-rsa"
|
||||
keyContent := "AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM="
|
||||
@ -167,7 +168,7 @@ func TestCreateUserKey(t *testing.T) {
|
||||
|
||||
// Now login as user 2
|
||||
session2 := loginUser(t, "user2")
|
||||
token2 := url.QueryEscape(getTokenForLoggedInUser(t, session2))
|
||||
token2 := url.QueryEscape(getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeAdminPublicKey))
|
||||
|
||||
// Should find key even though not ours, but we shouldn't know whose it is
|
||||
fingerprintURL = fmt.Sprintf("/api/v1/user/keys?token=%s&fingerprint=%s", token2, newPublicKey.Fingerprint)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -27,7 +28,7 @@ func TestAPINotification(t *testing.T) {
|
||||
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
||||
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
||||
session := loginUser(t, user2.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeNotification)
|
||||
|
||||
// -- GET /notifications --
|
||||
// test filter
|
||||
@ -145,7 +146,7 @@ func TestAPINotificationPUT(t *testing.T) {
|
||||
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
||||
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
||||
session := loginUser(t, user2.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeNotification)
|
||||
|
||||
// Check notifications are as expected
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?all=true&token=%s", token))
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
@ -49,15 +49,15 @@ func testAPICreateOAuth2Application(t *testing.T) {
|
||||
assert.True(t, createdApp.ConfidentialClient)
|
||||
assert.NotEmpty(t, createdApp.Created)
|
||||
assert.EqualValues(t, appBody.RedirectURIs[0], createdApp.RedirectURIs[0])
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{UID: user.ID, Name: createdApp.Name})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{UID: user.ID, Name: createdApp.Name})
|
||||
}
|
||||
|
||||
func testAPIListOAuth2Applications(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadApplication)
|
||||
|
||||
existApp := unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{
|
||||
existApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
||||
UID: user.ID,
|
||||
Name: "test-app-1",
|
||||
RedirectURIs: []string{
|
||||
@ -80,15 +80,15 @@ func testAPIListOAuth2Applications(t *testing.T) {
|
||||
assert.Len(t, expectedApp.ClientID, 36)
|
||||
assert.Empty(t, expectedApp.ClientSecret)
|
||||
assert.EqualValues(t, existApp.RedirectURIs[0], expectedApp.RedirectURIs[0])
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
|
||||
}
|
||||
|
||||
func testAPIDeleteOAuth2Application(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteApplication)
|
||||
|
||||
oldApp := unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{
|
||||
oldApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
||||
UID: user.ID,
|
||||
Name: "test-app-1",
|
||||
})
|
||||
@ -97,7 +97,7 @@ func testAPIDeleteOAuth2Application(t *testing.T) {
|
||||
req := NewRequest(t, "DELETE", urlStr)
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
|
||||
unittest.AssertNotExistsBean(t, &auth.OAuth2Application{UID: oldApp.UID, Name: oldApp.Name})
|
||||
unittest.AssertNotExistsBean(t, &auth_model.OAuth2Application{UID: oldApp.UID, Name: oldApp.Name})
|
||||
|
||||
// Delete again will return not found
|
||||
req = NewRequest(t, "DELETE", urlStr)
|
||||
@ -107,9 +107,9 @@ func testAPIDeleteOAuth2Application(t *testing.T) {
|
||||
func testAPIGetOAuth2Application(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadApplication)
|
||||
|
||||
existApp := unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{
|
||||
existApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
||||
UID: user.ID,
|
||||
Name: "test-app-1",
|
||||
RedirectURIs: []string{
|
||||
@ -133,13 +133,13 @@ func testAPIGetOAuth2Application(t *testing.T) {
|
||||
assert.Empty(t, expectedApp.ClientSecret)
|
||||
assert.Len(t, expectedApp.RedirectURIs, 1)
|
||||
assert.EqualValues(t, existApp.RedirectURIs[0], expectedApp.RedirectURIs[0])
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
|
||||
}
|
||||
|
||||
func testAPIUpdateOAuth2Application(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
existApp := unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{
|
||||
existApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
||||
UID: user.ID,
|
||||
Name: "test-app-1",
|
||||
RedirectURIs: []string{
|
||||
@ -169,5 +169,5 @@ func testAPIUpdateOAuth2Application(t *testing.T) {
|
||||
assert.EqualValues(t, expectedApp.RedirectURIs[0], appBody.RedirectURIs[0])
|
||||
assert.EqualValues(t, expectedApp.RedirectURIs[1], appBody.RedirectURIs[1])
|
||||
assert.Equal(t, expectedApp.ConfidentialClient, appBody.ConfidentialClient)
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@ -21,7 +22,7 @@ import (
|
||||
|
||||
func TestAPIOrgCreate(t *testing.T) {
|
||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||
token := getUserToken(t, "user1")
|
||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrg)
|
||||
|
||||
org := api.CreateOrgOption{
|
||||
UserName: "user1_org",
|
||||
@ -79,7 +80,7 @@ func TestAPIOrgEdit(t *testing.T) {
|
||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrg)
|
||||
org := api.EditOrgOption{
|
||||
FullName: "User3 organization new full name",
|
||||
Description: "A new description",
|
||||
@ -106,7 +107,7 @@ func TestAPIOrgEditBadVisibility(t *testing.T) {
|
||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrg)
|
||||
org := api.EditOrgOption{
|
||||
FullName: "User3 organization new full name",
|
||||
Description: "A new description",
|
||||
@ -126,14 +127,16 @@ func TestAPIOrgDeny(t *testing.T) {
|
||||
setting.Service.RequireSignInView = false
|
||||
}()
|
||||
|
||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeReadOrg)
|
||||
|
||||
orgName := "user1_org"
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s", orgName)
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s?token=%s", orgName, token)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", orgName)
|
||||
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token=%s", orgName, token)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", orgName)
|
||||
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members?token=%s", orgName, token)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
}
|
||||
@ -141,20 +144,23 @@ func TestAPIOrgDeny(t *testing.T) {
|
||||
func TestAPIGetAll(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs")
|
||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeReadOrg)
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs?token=%s", token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiOrgList []*api.Organization
|
||||
DecodeJSON(t, resp, &apiOrgList)
|
||||
|
||||
assert.Len(t, apiOrgList, 7)
|
||||
assert.Equal(t, "org25", apiOrgList[0].FullName)
|
||||
assert.Equal(t, "public", apiOrgList[0].Visibility)
|
||||
// accessing with a token will return all orgs
|
||||
assert.Len(t, apiOrgList, 9)
|
||||
assert.Equal(t, "org25", apiOrgList[1].FullName)
|
||||
assert.Equal(t, "public", apiOrgList[1].Visibility)
|
||||
}
|
||||
|
||||
func TestAPIOrgSearchEmptyTeam(t *testing.T) {
|
||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||
token := getUserToken(t, "user1")
|
||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeAdminOrg)
|
||||
orgName := "org_with_empty_team"
|
||||
|
||||
// create org
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
packages_model "code.gitea.io/gitea/models/packages"
|
||||
container_model "code.gitea.io/gitea/models/packages/container"
|
||||
@ -31,6 +32,8 @@ func TestPackageContainer(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadPackage)
|
||||
|
||||
has := func(l packages_model.PackagePropertyList, name string) bool {
|
||||
for _, pp := range l {
|
||||
@ -558,7 +561,7 @@ func TestPackageContainer(t *testing.T) {
|
||||
assert.Equal(t, c.ExpectedLink, resp.Header().Get("Link"))
|
||||
}
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s?type=container&q=%s", user.Name, image))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s?type=container&q=%s&token=%s", user.Name, image, token))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiPackages []*api.Package
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
packages_model "code.gitea.io/gitea/models/packages"
|
||||
container_model "code.gitea.io/gitea/models/packages/container"
|
||||
@ -28,7 +29,8 @@ func TestPackageAPI(t *testing.T) {
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
tokenReadPackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadPackage)
|
||||
tokenDeletePackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeDeletePackage)
|
||||
|
||||
packageName := "test-package"
|
||||
packageVersion := "1.0.3"
|
||||
@ -42,7 +44,7 @@ func TestPackageAPI(t *testing.T) {
|
||||
t.Run("ListPackages", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s?token=%s", user.Name, token))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s?token=%s", user.Name, tokenReadPackage))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiPackages []*api.Package
|
||||
@ -59,10 +61,10 @@ func TestPackageAPI(t *testing.T) {
|
||||
t.Run("GetPackage", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s?token=%s", user.Name, packageName, packageVersion, tokenReadPackage))
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, tokenReadPackage))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var p *api.Package
|
||||
@ -81,7 +83,7 @@ func TestPackageAPI(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// no repository link
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, tokenReadPackage))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var ap1 *api.Package
|
||||
@ -91,7 +93,7 @@ func TestPackageAPI(t *testing.T) {
|
||||
// link to public repository
|
||||
assert.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, 1))
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, tokenReadPackage))
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var ap2 *api.Package
|
||||
@ -102,7 +104,7 @@ func TestPackageAPI(t *testing.T) {
|
||||
// link to private repository
|
||||
assert.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, 2))
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, tokenReadPackage))
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var ap3 *api.Package
|
||||
@ -116,10 +118,10 @@ func TestPackageAPI(t *testing.T) {
|
||||
t.Run("ListPackageFiles", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s/files?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s/files?token=%s", user.Name, packageName, packageVersion, tokenReadPackage))
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s/files?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s/files?token=%s", user.Name, packageName, packageVersion, tokenReadPackage))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var files []*api.PackageFile
|
||||
@ -137,10 +139,10 @@ func TestPackageAPI(t *testing.T) {
|
||||
t.Run("DeletePackage", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s?token=%s", user.Name, packageName, packageVersion, tokenDeletePackage))
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
|
||||
req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, tokenDeletePackage))
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -27,7 +28,7 @@ func TestAPIPullReview(t *testing.T) {
|
||||
|
||||
// test ListPullReviews
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/%s/pulls/%d/reviews?token=%s", repo.OwnerName, repo.Name, pullIssue.Index, token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
@ -230,7 +231,7 @@ func TestAPIPullReviewRequest(t *testing.T) {
|
||||
|
||||
// Test add Review Request
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/requested_reviewers?token=%s", repo.OwnerName, repo.Name, pullIssue.Index, token), &api.PullReviewRequestOptions{
|
||||
Reviewers: []string{"user4@example.com", "user8"},
|
||||
})
|
||||
@ -250,7 +251,7 @@ func TestAPIPullReviewRequest(t *testing.T) {
|
||||
|
||||
// Test Remove Review Request
|
||||
session2 := loginUser(t, "user4")
|
||||
token2 := getTokenForLoggedInUser(t, session2)
|
||||
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req = NewRequestWithJSON(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/requested_reviewers?token=%s", repo.OwnerName, repo.Name, pullIssue.Index, token2), &api.PullReviewRequestOptions{
|
||||
Reviewers: []string{"user4"},
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -28,7 +29,7 @@ func TestAPIViewPulls(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
ctx := NewAPITestContext(t, "user2", repo.Name)
|
||||
ctx := NewAPITestContext(t, "user2", repo.Name, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/pulls?state=all&token="+ctx.Token, owner.Name, repo.Name)
|
||||
resp := ctx.Session.MakeRequest(t, req, http.StatusOK)
|
||||
@ -74,7 +75,7 @@ func TestAPIMergePullWIP(t *testing.T) {
|
||||
assert.Contains(t, pr.Issue.Title, setting.Repository.PullRequest.WorkInProgressPrefixes[0])
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/merge?token=%s", owner.Name, repo.Name, pr.Index, token), &forms.MergePullRequestForm{
|
||||
MergeMessageField: pr.Issue.Title,
|
||||
Do: string(repo_model.MergeStyleMerge),
|
||||
@ -93,7 +94,7 @@ func TestAPICreatePullSuccess(t *testing.T) {
|
||||
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
||||
|
||||
session := loginUser(t, owner11.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
|
||||
Head: fmt.Sprintf("%s:master", owner11.Name),
|
||||
Base: "master",
|
||||
@ -113,7 +114,7 @@ func TestAPICreatePullWithFieldsSuccess(t *testing.T) {
|
||||
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
||||
|
||||
session := loginUser(t, owner11.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
opts := &api.CreatePullRequestOption{
|
||||
Head: fmt.Sprintf("%s:master", owner11.Name),
|
||||
@ -150,7 +151,7 @@ func TestAPICreatePullWithFieldsFailure(t *testing.T) {
|
||||
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
||||
|
||||
session := loginUser(t, owner11.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
opts := &api.CreatePullRequestOption{
|
||||
Head: fmt.Sprintf("%s:master", owner11.Name),
|
||||
@ -180,7 +181,7 @@ func TestAPIEditPull(t *testing.T) {
|
||||
owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
|
||||
|
||||
session := loginUser(t, owner10.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
|
||||
Head: "develop",
|
||||
Base: "master",
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -24,7 +25,7 @@ func TestAPIListReleases(t *testing.T) {
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
token := getUserToken(t, user2.LowerName)
|
||||
token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/releases", user2.Name, repo.Name))
|
||||
link.RawQuery = url.Values{"token": {token}}.Encode()
|
||||
@ -100,7 +101,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
session := loginUser(t, owner.LowerName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath())
|
||||
assert.NoError(t, err)
|
||||
@ -152,7 +153,7 @@ func TestAPICreateReleaseToDefaultBranch(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
session := loginUser(t, owner.LowerName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", "", "v0.0.1", "test")
|
||||
}
|
||||
@ -163,7 +164,7 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
session := loginUser(t, owner.LowerName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath())
|
||||
assert.NoError(t, err)
|
||||
@ -213,7 +214,7 @@ func TestAPIDeleteReleaseByTagName(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
session := loginUser(t, owner.LowerName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test")
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -24,7 +25,7 @@ func TestAPIDownloadArchive(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user2.LowerName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.zip", user2.Name, repo.Name))
|
||||
link.RawQuery = url.Values{"token": {token}}.Encode()
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -27,7 +28,7 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) {
|
||||
user10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 10})
|
||||
user11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 11})
|
||||
|
||||
testCtx := NewAPITestContext(t, repo2Owner.Name, repo2.Name)
|
||||
testCtx := NewAPITestContext(t, repo2Owner.Name, repo2.Name, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
t.Run("RepoOwnerShouldBeOwner", func(t *testing.T) {
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, repo2Owner.Name, testCtx.Token)
|
||||
@ -84,7 +85,7 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) {
|
||||
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
|
||||
|
||||
_session := loginUser(t, user5.Name)
|
||||
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name)
|
||||
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user5.Name, _testCtx.Token)
|
||||
resp := _session.MakeRequest(t, req, http.StatusOK)
|
||||
@ -99,7 +100,7 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) {
|
||||
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
|
||||
|
||||
_session := loginUser(t, user5.Name)
|
||||
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name)
|
||||
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user5.Name, _testCtx.Token)
|
||||
resp := _session.MakeRequest(t, req, http.StatusOK)
|
||||
@ -115,7 +116,7 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) {
|
||||
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user11.Name, perm.AccessModeRead))
|
||||
|
||||
_session := loginUser(t, user10.Name)
|
||||
_testCtx := NewAPITestContext(t, user10.Name, repo2.Name)
|
||||
_testCtx := NewAPITestContext(t, user10.Name, repo2.Name, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user11.Name, _testCtx.Token)
|
||||
resp := _session.MakeRequest(t, req, http.StatusOK)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
@ -146,10 +147,10 @@ func TestAPIRepoEdit(t *testing.T) {
|
||||
|
||||
// Get user2's token
|
||||
session := loginUser(t, user2.Name)
|
||||
token2 := getTokenForLoggedInUser(t, session)
|
||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
// Get user4's token
|
||||
session = loginUser(t, user4.Name)
|
||||
token4 := getTokenForLoggedInUser(t, session)
|
||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Test editing a repo1 which user2 owns, changing name and many properties
|
||||
origRepoEditOption := getRepoEditOptionFromRepo(repo1)
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -150,10 +151,10 @@ func TestAPICreateFile(t *testing.T) {
|
||||
|
||||
// Get user2's token
|
||||
session := loginUser(t, user2.Name)
|
||||
token2 := getTokenForLoggedInUser(t, session)
|
||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
// Get user4's token
|
||||
session = loginUser(t, user4.Name)
|
||||
token4 := getTokenForLoggedInUser(t, session)
|
||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Test creating a file in repo1 which user2 owns, try both with branch and empty branch
|
||||
for _, branch := range [...]string{
|
||||
@ -279,7 +280,7 @@ func TestAPICreateFile(t *testing.T) {
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
|
||||
// Test creating a file in an empty repository
|
||||
doAPICreateRepository(NewAPITestContext(t, "user2", "empty-repo"), true)(t)
|
||||
doAPICreateRepository(NewAPITestContext(t, "user2", "empty-repo", auth_model.AccessTokenScopeRepo), true)(t)
|
||||
createFileOptions = getCreateFileOptions()
|
||||
fileID++
|
||||
treePath = fmt.Sprintf("new/file%d.txt", fileID)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -48,10 +49,10 @@ func TestAPIDeleteFile(t *testing.T) {
|
||||
|
||||
// Get user2's token
|
||||
session := loginUser(t, user2.Name)
|
||||
token2 := getTokenForLoggedInUser(t, session)
|
||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
// Get user4's token
|
||||
session = loginUser(t, user4.Name)
|
||||
token4 := getTokenForLoggedInUser(t, session)
|
||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Test deleting a file in repo1 which user2 owns, try both with branch and empty branch
|
||||
for _, branch := range [...]string{
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -24,7 +25,7 @@ func TestAPIGetRawFileOrLFS(t *testing.T) {
|
||||
|
||||
// Test with LFS
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
httpContext := NewAPITestContext(t, "user2", "repo-lfs-test")
|
||||
httpContext := NewAPITestContext(t, "user2", "repo-lfs-test", auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeDeleteRepo)
|
||||
doAPICreateRepository(httpContext, false, func(t *testing.T, repository api.Repository) {
|
||||
u.Path = httpContext.GitPath()
|
||||
dstPath := t.TempDir()
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -116,10 +117,10 @@ func TestAPIUpdateFile(t *testing.T) {
|
||||
|
||||
// Get user2's token
|
||||
session := loginUser(t, user2.Name)
|
||||
token2 := getTokenForLoggedInUser(t, session)
|
||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
// Get user4's token
|
||||
session = loginUser(t, user4.Name)
|
||||
token4 := getTokenForLoggedInUser(t, session)
|
||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Test updating a file in repo1 which user2 owns, try both with branch and empty branch
|
||||
for _, branch := range [...]string{
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -30,7 +31,7 @@ func TestAPIListGitHooks(t *testing.T) {
|
||||
|
||||
// user1 is an admin user
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
@ -56,7 +57,7 @@ func TestAPIListGitHooksNoHooks(t *testing.T) {
|
||||
|
||||
// user1 is an admin user
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
@ -76,7 +77,7 @@ func TestAPIListGitHooksNoAccess(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
@ -90,7 +91,7 @@ func TestAPIGetGitHook(t *testing.T) {
|
||||
|
||||
// user1 is an admin user
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
@ -107,7 +108,7 @@ func TestAPIGetGitHookNoAccess(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
@ -121,7 +122,7 @@ func TestAPIEditGitHook(t *testing.T) {
|
||||
|
||||
// user1 is an admin user
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminRepoHook)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
@ -150,7 +151,7 @@ func TestAPIEditGitHookNoAccess(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepoHook)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
req := NewRequestWithJSON(t, "PATCH", urlStr, &api.EditGitHookOption{
|
||||
@ -167,7 +168,7 @@ func TestAPIDeleteGitHook(t *testing.T) {
|
||||
|
||||
// user1 is an admin user
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminRepoHook)
|
||||
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
@ -189,7 +190,7 @@ func TestAPIDeleteGitHookNoAccess(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepoHook)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -69,7 +70,7 @@ func TestAPIDeleteTagByName(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
session := loginUser(t, owner.LowerName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/tags/delete-tag?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -25,7 +26,7 @@ func TestAPICreateHook(t *testing.T) {
|
||||
|
||||
// user1 is an admin user
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepoHook)
|
||||
completeURL := func(lastSegment string) string {
|
||||
return fmt.Sprintf("/api/v1/repos/%s/%s/%s?token=%s", owner.Name, repo.Name, lastSegment, token)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
@ -30,7 +31,7 @@ func TestAPIRepoLFSMigrateLocal(t *testing.T) {
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+token, &api.MigrateRepoOptions{
|
||||
CloneAddr: path.Join(setting.RepoRootPath, "migration/lfs-test.git"),
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -59,7 +60,7 @@ func TestAPILFSMediaType(t *testing.T) {
|
||||
}
|
||||
|
||||
func createLFSTestRepository(t *testing.T, name string) *repo_model.Repository {
|
||||
ctx := NewAPITestContext(t, "user2", "lfs-"+name+"-repo")
|
||||
ctx := NewAPITestContext(t, "user2", "lfs-"+name+"-repo", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateRepo", doAPICreateRepository(ctx, false))
|
||||
|
||||
repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "lfs-"+name+"-repo")
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/tests"
|
||||
@ -19,7 +20,7 @@ func TestAPIReposRaw(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
// Login as User2.
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
for _, ref := range [...]string{
|
||||
"master", // Branch
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@ -22,7 +23,7 @@ func TestAPIRepoTags(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
// Login as User2.
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
repoName := "repo1"
|
||||
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -27,7 +28,7 @@ func TestAPIRepoTeams(t *testing.T) {
|
||||
// user4
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// ListTeams
|
||||
url := fmt.Sprintf("/api/v1/repos/%s/teams?token=%s", publicOrgRepo.FullName(), token)
|
||||
@ -67,7 +68,7 @@ func TestAPIRepoTeams(t *testing.T) {
|
||||
// AddTeam with user2
|
||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session = loginUser(t, user.Name)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
url = fmt.Sprintf("/api/v1/repos/%s/teams/%s?token=%s", publicOrgRepo.FullName(), "team1", token)
|
||||
req = NewRequest(t, "PUT", url)
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -286,24 +287,17 @@ func TestAPIOrgRepos(t *testing.T) {
|
||||
count int
|
||||
includesPrivate bool
|
||||
}{
|
||||
nil: {count: 1},
|
||||
user: {count: 1},
|
||||
user: {count: 3, 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)
|
||||
}
|
||||
testName := fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
||||
session := loginUser(t, userToLogin.Name)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
||||
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
@ -324,7 +318,7 @@ func TestAPIGetRepoByIDUnauthorized(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repositories/2?token="+token)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
@ -348,7 +342,7 @@ func TestAPIRepoMigrate(t *testing.T) {
|
||||
for _, testCase := range testCases {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+token, &api.MigrateRepoOptions{
|
||||
CloneAddr: testCase.cloneURL,
|
||||
RepoOwnerID: testCase.userID,
|
||||
@ -378,7 +372,7 @@ func TestAPIRepoMigrateConflict(t *testing.T) {
|
||||
|
||||
func testAPIRepoMigrateConflict(t *testing.T, u *url.URL) {
|
||||
username := "user2"
|
||||
baseAPITestContext := NewAPITestContext(t, username, "repo1")
|
||||
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeRepo)
|
||||
|
||||
u.Path = baseAPITestContext.GitPath()
|
||||
|
||||
@ -413,7 +407,7 @@ func TestAPIMirrorSyncNonMirrorRepo(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
var repo api.Repository
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1")
|
||||
@ -445,7 +439,7 @@ func TestAPIOrgRepoCreate(t *testing.T) {
|
||||
for _, testCase := range testCases {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminOrg)
|
||||
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos?token="+token, testCase.orgName), &api.CreateRepoOption{
|
||||
Name: testCase.repoName,
|
||||
})
|
||||
@ -459,7 +453,7 @@ func TestAPIRepoCreateConflict(t *testing.T) {
|
||||
|
||||
func testAPIRepoCreateConflict(t *testing.T, u *url.URL) {
|
||||
username := "user2"
|
||||
baseAPITestContext := NewAPITestContext(t, username, "repo1")
|
||||
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeRepo)
|
||||
|
||||
u.Path = baseAPITestContext.GitPath()
|
||||
|
||||
@ -509,7 +503,7 @@ func TestAPIRepoTransfer(t *testing.T) {
|
||||
// create repo to move
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
repoName := "moveME"
|
||||
apiRepo := new(api.Repository)
|
||||
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/repos?token=%s", token), &api.CreateRepoOption{
|
||||
@ -527,7 +521,7 @@ func TestAPIRepoTransfer(t *testing.T) {
|
||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID})
|
||||
session = loginUser(t, user.Name)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer?token=%s", repo.OwnerName, repo.Name, token), &api.TransferRepoOption{
|
||||
NewOwner: testCase.newOwner,
|
||||
TeamIDs: testCase.teams,
|
||||
@ -544,7 +538,7 @@ func transfer(t *testing.T) *repo_model.Repository {
|
||||
// create repo to move
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
repoName := "moveME"
|
||||
apiRepo := new(api.Repository)
|
||||
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/repos?token=%s", token), &api.CreateRepoOption{
|
||||
@ -574,7 +568,7 @@ func TestAPIAcceptTransfer(t *testing.T) {
|
||||
|
||||
// try to accept with not authorized user
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token))
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
|
||||
@ -584,7 +578,7 @@ func TestAPIAcceptTransfer(t *testing.T) {
|
||||
|
||||
// accept transfer
|
||||
session = loginUser(t, "user4")
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/accept?token=%s", repo.OwnerName, repo.Name, token))
|
||||
resp := MakeRequest(t, req, http.StatusAccepted)
|
||||
@ -600,7 +594,7 @@ func TestAPIRejectTransfer(t *testing.T) {
|
||||
|
||||
// try to reject with not authorized user
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token))
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
|
||||
@ -610,7 +604,7 @@ func TestAPIRejectTransfer(t *testing.T) {
|
||||
|
||||
// reject transfer
|
||||
session = loginUser(t, "user4")
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
@ -624,7 +618,7 @@ func TestAPIGenerateRepo(t *testing.T) {
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
templateRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 44})
|
||||
|
||||
@ -660,7 +654,7 @@ func TestAPIRepoGetReviewers(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/reviewers?token=%s", user.Name, repo.Name, token)
|
||||
@ -674,7 +668,7 @@ func TestAPIRepoGetAssignees(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/assignees?token=%s", user.Name, repo.Name, token)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -59,7 +60,7 @@ func TestAPIRepoTopic(t *testing.T) {
|
||||
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
||||
|
||||
// Get user2's token
|
||||
token2 := getUserToken(t, user2.Name)
|
||||
token2 := getUserToken(t, user2.Name, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Test read topics using login
|
||||
url := fmt.Sprintf("/api/v1/repos/%s/%s/topics", user2.Name, repo2.Name)
|
||||
@ -139,7 +140,7 @@ func TestAPIRepoTopic(t *testing.T) {
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
// Get user4's token
|
||||
token4 := getUserToken(t, user4.Name)
|
||||
token4 := getUserToken(t, user4.Name, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Test read topics with write access
|
||||
url = fmt.Sprintf("/api/v1/repos/%s/%s/topics?token=%s", user3.Name, repo3.Name, token4)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
@ -29,7 +30,7 @@ func TestAPITeam(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser.UID})
|
||||
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminOrg)
|
||||
req := NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
@ -43,7 +44,7 @@ func TestAPITeam(t *testing.T) {
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser2.UID})
|
||||
|
||||
session = loginUser(t, user2.Name)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
||||
req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
|
||||
_ = MakeRequest(t, req, http.StatusForbidden)
|
||||
|
||||
@ -53,7 +54,7 @@ func TestAPITeam(t *testing.T) {
|
||||
// Get an admin user able to create, update and delete teams.
|
||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
session = loginUser(t, user.Name)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminOrg)
|
||||
|
||||
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 6})
|
||||
|
||||
@ -227,7 +228,7 @@ func TestAPITeamSearch(t *testing.T) {
|
||||
|
||||
var results TeamSearchResults
|
||||
|
||||
token := getUserToken(t, user.Name)
|
||||
token := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadOrg)
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s&token=%s", org.Name, "_team", token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &results)
|
||||
@ -237,7 +238,7 @@ func TestAPITeamSearch(t *testing.T) {
|
||||
|
||||
// no access if not organization member
|
||||
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
token5 := getUserToken(t, user5.Name)
|
||||
token5 := getUserToken(t, user5.Name, auth_model.AccessTokenScopeReadOrg)
|
||||
|
||||
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s&token=%s", org.Name, "team", token5)
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
@ -252,7 +253,7 @@ func TestAPIGetTeamRepo(t *testing.T) {
|
||||
|
||||
var results api.Repository
|
||||
|
||||
token := getUserToken(t, user.Name)
|
||||
token := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadOrg)
|
||||
req := NewRequestf(t, "GET", "/api/v1/teams/%d/repos/%s/?token=%s", team.ID, teamRepo.FullName(), token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &results)
|
||||
@ -260,7 +261,7 @@ func TestAPIGetTeamRepo(t *testing.T) {
|
||||
|
||||
// no access if not organization member
|
||||
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
token5 := getUserToken(t, user5.Name)
|
||||
token5 := getUserToken(t, user5.Name, auth_model.AccessTokenScopeReadOrg)
|
||||
|
||||
req = NewRequestf(t, "GET", "/api/v1/teams/%d/repos/%s/?token=%s", team.ID, teamRepo.FullName(), token5)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
@ -22,7 +23,7 @@ func TestAPITeamUser(t *testing.T) {
|
||||
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, normalUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/1/members/user1?token="+token)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -18,7 +19,7 @@ func TestAPIListEmails(t *testing.T) {
|
||||
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, normalUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||
|
||||
req := NewRequest(t, "GET", "/api/v1/user/emails?token="+token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
@ -45,7 +46,7 @@ func TestAPIAddEmail(t *testing.T) {
|
||||
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, normalUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeUser)
|
||||
|
||||
opts := api.CreateEmailOption{
|
||||
Emails: []string{"user101@example.com"},
|
||||
@ -82,7 +83,7 @@ func TestAPIDeleteEmail(t *testing.T) {
|
||||
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, normalUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeUser)
|
||||
|
||||
opts := api.DeleteEmailOption{
|
||||
Emails: []string{"user2-3@example.com"},
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -24,7 +25,7 @@ func TestAPIFollow(t *testing.T) {
|
||||
token1 := getTokenForLoggedInUser(t, session1)
|
||||
|
||||
session2 := loginUser(t, user2)
|
||||
token2 := getTokenForLoggedInUser(t, session2)
|
||||
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeUserFollow)
|
||||
|
||||
t.Run("Follow", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -32,7 +33,7 @@ func sampleTest(t *testing.T, auoptc apiUserOrgPermTestCase) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, auoptc.LoginUser)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/%s/orgs/%s/permissions?token=%s", auoptc.User, auoptc.Organization, token))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
@ -125,7 +126,7 @@ func TestUnknowUser(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/unknow/orgs/org25/permissions?token=%s", token))
|
||||
resp := MakeRequest(t, req, http.StatusNotFound)
|
||||
@ -139,7 +140,7 @@ func TestUnknowOrganization(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/user1/orgs/unknow/permissions?token=%s", token))
|
||||
resp := MakeRequest(t, req, http.StatusNotFound)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
@ -61,15 +62,14 @@ func TestUserOrgs(t *testing.T) {
|
||||
orgs = getUserOrgs(t, unrelatedUsername, privateMemberUsername)
|
||||
assert.Len(t, orgs, 0)
|
||||
|
||||
// not authenticated call also should hide org membership
|
||||
orgs = getUserOrgs(t, "", privateMemberUsername)
|
||||
assert.Len(t, orgs, 0)
|
||||
// not authenticated call should not be allowed
|
||||
testUserOrgsUnauthenticated(t, privateMemberUsername)
|
||||
}
|
||||
|
||||
func getUserOrgs(t *testing.T, userDoer, userCheck string) (orgs []*api.Organization) {
|
||||
token := ""
|
||||
if len(userDoer) != 0 {
|
||||
token = getUserToken(t, userDoer)
|
||||
token = getUserToken(t, userDoer, auth_model.AccessTokenScopeReadOrg)
|
||||
}
|
||||
urlStr := fmt.Sprintf("/api/v1/users/%s/orgs?token=%s", userCheck, token)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
@ -78,6 +78,12 @@ func getUserOrgs(t *testing.T, userDoer, userCheck string) (orgs []*api.Organiza
|
||||
return orgs
|
||||
}
|
||||
|
||||
func testUserOrgsUnauthenticated(t *testing.T, userCheck string) {
|
||||
session := emptyTestSession(t)
|
||||
req := NewRequestf(t, "GET", "/api/v1/users/%s/orgs", userCheck)
|
||||
session.MakeRequest(t, req, http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
func TestMyOrgs(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
@ -85,7 +91,7 @@ func TestMyOrgs(t *testing.T) {
|
||||
MakeRequest(t, req, http.StatusUnauthorized)
|
||||
|
||||
normalUsername := "user2"
|
||||
token := getUserToken(t, normalUsername)
|
||||
token := getUserToken(t, normalUsername, auth_model.AccessTokenScopeReadOrg)
|
||||
req = NewRequest(t, "GET", "/api/v1/user/orgs?token="+token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
var orgs []*api.Organization
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -22,11 +23,12 @@ func TestAPIStar(t *testing.T) {
|
||||
|
||||
session := loginUser(t, user)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
tokenWithRepoScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
t.Run("Star", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, token))
|
||||
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithRepoScope))
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
})
|
||||
|
||||
@ -47,7 +49,7 @@ func TestAPIStar(t *testing.T) {
|
||||
t.Run("GetMyStarredRepos", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred?token=%s", token))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred?token=%s", tokenWithRepoScope))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Equal(t, "1", resp.Header().Get("X-Total-Count"))
|
||||
@ -61,17 +63,17 @@ func TestAPIStar(t *testing.T) {
|
||||
t.Run("IsStarring", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, token))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithRepoScope))
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo+"notexisting", token))
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo+"notexisting", tokenWithRepoScope))
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
|
||||
t.Run("Unstar", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, token))
|
||||
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithRepoScope))
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -22,11 +23,12 @@ func TestAPIWatch(t *testing.T) {
|
||||
|
||||
session := loginUser(t, user)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
tokenWithRepoScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
t.Run("Watch", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/subscription?token=%s", repo, token))
|
||||
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/subscription?token=%s", repo, tokenWithRepoScope))
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
})
|
||||
|
||||
@ -47,7 +49,7 @@ func TestAPIWatch(t *testing.T) {
|
||||
t.Run("GetMyWatchedRepos", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/subscriptions?token=%s", token))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/subscriptions?token=%s", tokenWithRepoScope))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Equal(t, "1", resp.Header().Get("X-Total-Count"))
|
||||
@ -61,17 +63,17 @@ func TestAPIWatch(t *testing.T) {
|
||||
t.Run("IsWatching", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/subscription?token=%s", repo, token))
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/subscription?token=%s", repo, tokenWithRepoScope))
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/subscription?token=%s", repo+"notexisting", token))
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/subscription?token=%s", repo+"notexisting", tokenWithRepoScope))
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
|
||||
t.Run("Unwatch", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/subscription?token=%s", repo, token))
|
||||
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/subscription?token=%s", repo, tokenWithRepoScope))
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@ -179,7 +180,7 @@ func TestAPINewWikiPage(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
username := "user2"
|
||||
session := loginUser(t, username)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new?token=%s", username, "repo1", token)
|
||||
|
||||
@ -196,7 +197,7 @@ func TestAPIEditWikiPage(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
username := "user2"
|
||||
session := loginUser(t, username)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/Page-With-Spaced-Name?token=%s", username, "repo1", token)
|
||||
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -50,7 +51,7 @@ func TestDumpRestore(t *testing.T) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame})
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
//
|
||||
// Phase 1: dump repo1 from the Gitea instance to the filesystem
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -59,7 +60,7 @@ func TestEventSourceManagerRun(t *testing.T) {
|
||||
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
||||
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
||||
session := loginUser(t, user2.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeNotification)
|
||||
|
||||
var apiNL []api.NotificationThread
|
||||
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
@ -42,11 +43,11 @@ func TestGit(t *testing.T) {
|
||||
|
||||
func testGit(t *testing.T, u *url.URL) {
|
||||
username := "user2"
|
||||
baseAPITestContext := NewAPITestContext(t, username, "repo1")
|
||||
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeWritePublicKey, auth_model.AccessTokenScopeDeleteRepo)
|
||||
|
||||
u.Path = baseAPITestContext.GitPath()
|
||||
|
||||
forkedUserCtx := NewAPITestContext(t, "user4", "repo1")
|
||||
forkedUserCtx := NewAPITestContext(t, "user4", "repo1", auth_model.AccessTokenScopeRepo)
|
||||
|
||||
t.Run("HTTP", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
@ -357,7 +358,7 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
|
||||
t.Run("CreateBranchProtected", doGitCreateBranch(dstPath, "protected"))
|
||||
t.Run("PushProtectedBranch", doGitPushTestRepository(dstPath, "origin", "protected"))
|
||||
|
||||
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame)
|
||||
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame, auth_model.AccessTokenScopeRepo)
|
||||
t.Run("ProtectProtectedBranchNoWhitelist", doProtectBranch(ctx, "protected", "", ""))
|
||||
t.Run("GenerateCommit", func(t *testing.T) {
|
||||
_, err := generateCommitWithNewData(littleSize, dstPath, "user2@example.com", "User Two", "branch-data-file-")
|
||||
@ -601,7 +602,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame)
|
||||
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
t.Run("CheckoutProtected", doGitCheckoutBranch(dstPath, "protected"))
|
||||
t.Run("PullProtected", doGitPull(dstPath, "origin", "protected"))
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
@ -69,7 +70,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("Unsigned-Initial", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned")
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||
t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
|
||||
assert.NotNil(t, branch.Commit)
|
||||
@ -93,7 +94,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned")
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
|
||||
t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
|
||||
assert.False(t, response.Verification.Verified)
|
||||
@ -110,7 +111,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("Unsigned-Initial-CRUD-Never", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned")
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateCRUDFile-Never", crudActionCreateFile(
|
||||
t, testCtx, user, "parentsigned", "parentsigned-never", "unsigned-never2.txt", func(t *testing.T, response api.FileResponse) {
|
||||
assert.False(t, response.Verification.Verified)
|
||||
@ -123,7 +124,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("Unsigned-Initial-CRUD-Always", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned")
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
|
||||
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
|
||||
assert.NotNil(t, response.Verification)
|
||||
@ -160,7 +161,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned")
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateCRUDFile-Always-ParentSigned", crudActionCreateFile(
|
||||
t, testCtx, user, "always", "always-parentsigned", "signed-always-parentsigned.txt", func(t *testing.T, response api.FileResponse) {
|
||||
assert.NotNil(t, response.Verification)
|
||||
@ -183,7 +184,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("AlwaysSign-Initial", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-always")
|
||||
testCtx := NewAPITestContext(t, username, "initial-always", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||
t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
|
||||
assert.NotNil(t, branch.Commit)
|
||||
@ -211,7 +212,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("AlwaysSign-Initial-CRUD-Never", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-always-never")
|
||||
testCtx := NewAPITestContext(t, username, "initial-always-never", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||
t.Run("CreateCRUDFile-Never", crudActionCreateFile(
|
||||
t, testCtx, user, "master", "never", "unsigned-never.txt", func(t *testing.T, response api.FileResponse) {
|
||||
@ -224,7 +225,7 @@ func TestGPGGit(t *testing.T) {
|
||||
u.Path = baseAPITestContext.GitPath()
|
||||
t.Run("AlwaysSign-Initial-CRUD-ParentSigned-On-Always", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-always-parent")
|
||||
testCtx := NewAPITestContext(t, username, "initial-always-parent", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||
t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
|
||||
t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
|
||||
@ -243,7 +244,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("AlwaysSign-Initial-CRUD-Always", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-always-always")
|
||||
testCtx := NewAPITestContext(t, username, "initial-always-always", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
|
||||
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
|
||||
@ -263,7 +264,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("UnsignedMerging", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned")
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
||||
var err error
|
||||
t.Run("CreatePullRequest", func(t *testing.T) {
|
||||
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "never2")(t)
|
||||
@ -284,7 +285,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("BaseSignedMerging", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned")
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
||||
var err error
|
||||
t.Run("CreatePullRequest", func(t *testing.T) {
|
||||
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "parentsigned2")(t)
|
||||
@ -305,7 +306,7 @@ func TestGPGGit(t *testing.T) {
|
||||
|
||||
t.Run("CommitsSignedMerging", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned")
|
||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
||||
var err error
|
||||
t.Run("CreatePullRequest", func(t *testing.T) {
|
||||
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "always-parentsigned")(t)
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
@ -217,8 +218,8 @@ func emptyTestSession(t testing.TB) *TestSession {
|
||||
return &TestSession{jar: jar}
|
||||
}
|
||||
|
||||
func getUserToken(t testing.TB, userName string) string {
|
||||
return getTokenForLoggedInUser(t, loginUser(t, userName))
|
||||
func getUserToken(t testing.TB, userName string, scope ...auth.AccessTokenScope) string {
|
||||
return getTokenForLoggedInUser(t, loginUser(t, userName), scope...)
|
||||
}
|
||||
|
||||
func loginUser(t testing.TB, userName string) *TestSession {
|
||||
@ -256,7 +257,10 @@ func loginUserWithPassword(t testing.TB, userName, password string) *TestSession
|
||||
// token has to be unique this counter take care of
|
||||
var tokenCounter int64
|
||||
|
||||
func getTokenForLoggedInUser(t testing.TB, session *TestSession) string {
|
||||
// getTokenForLoggedInUser returns a token for a logged in user.
|
||||
// The scope is an optional list of snake_case strings like the frontend form fields,
|
||||
// but without the "scope_" prefix.
|
||||
func getTokenForLoggedInUser(t testing.TB, session *TestSession, scopes ...auth.AccessTokenScope) string {
|
||||
t.Helper()
|
||||
var token string
|
||||
req := NewRequest(t, "GET", "/user/settings/applications")
|
||||
@ -274,10 +278,13 @@ func getTokenForLoggedInUser(t testing.TB, session *TestSession) string {
|
||||
csrf = doc.GetCSRF()
|
||||
}
|
||||
assert.NotEmpty(t, csrf)
|
||||
req = NewRequestWithValues(t, "POST", "/user/settings/applications", map[string]string{
|
||||
"_csrf": csrf,
|
||||
"name": fmt.Sprintf("api-testing-token-%d", atomic.AddInt64(&tokenCounter, 1)),
|
||||
})
|
||||
urlValues := url.Values{}
|
||||
urlValues.Add("_csrf", csrf)
|
||||
urlValues.Add("name", fmt.Sprintf("api-testing-token-%d", atomic.AddInt64(&tokenCounter, 1)))
|
||||
for _, scope := range scopes {
|
||||
urlValues.Add("scope", string(scope))
|
||||
}
|
||||
req = NewRequestWithURLValues(t, "POST", "/user/settings/applications", urlValues)
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// Log the flash values on failure
|
||||
@ -317,6 +324,11 @@ func NewRequestWithValues(t testing.TB, method, urlStr string, values map[string
|
||||
for key, value := range values {
|
||||
urlValues[key] = []string{value}
|
||||
}
|
||||
return NewRequestWithURLValues(t, method, urlStr, urlValues)
|
||||
}
|
||||
|
||||
func NewRequestWithURLValues(t testing.TB, method, urlStr string, urlValues url.Values) *http.Request {
|
||||
t.Helper()
|
||||
req := NewRequestWithBody(t, method, urlStr, bytes.NewBufferString(urlValues.Encode()))
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
return req
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -66,7 +67,7 @@ func TestMigrateGiteaForm(t *testing.T) {
|
||||
repoName := "repo1"
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: ownerName})
|
||||
session := loginUser(t, ownerName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Step 0: verify the repo is available
|
||||
req := NewRequestf(t, "GET", fmt.Sprintf("/%s/%s", ownerName, repoName))
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -24,7 +25,7 @@ func testOrgCounts(t *testing.T, u *url.URL) {
|
||||
orgOwner := "user2"
|
||||
orgName := "testOrg"
|
||||
orgCollaborator := "user4"
|
||||
ctx := NewAPITestContext(t, orgOwner, "repo1")
|
||||
ctx := NewAPITestContext(t, orgOwner, "repo1", auth_model.AccessTokenScopeAdminOrg)
|
||||
|
||||
var ownerCountRepos map[string]int
|
||||
var collabCountRepos map[string]int
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
@ -158,7 +159,7 @@ func TestOrgRestrictedUser(t *testing.T) {
|
||||
|
||||
// Therefore create a read-only team
|
||||
adminSession := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, adminSession)
|
||||
token := getTokenForLoggedInUser(t, adminSession, auth_model.AccessTokenScopeAdminOrg)
|
||||
|
||||
teamToCreate := &api.CreateTeamOption{
|
||||
Name: "codereader",
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -33,7 +34,7 @@ func testPrivateActivityDoSomethingForActionEntries(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID})
|
||||
|
||||
session := loginUser(t, privateActivityTestUser)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all&token=%s", owner.Name, repoBefore.Name, token)
|
||||
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{
|
||||
Body: "test",
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -217,7 +218,7 @@ func TestCantMergeConflict(t *testing.T) {
|
||||
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "base", "README.md", "Hello, World (Edited Twice)\n")
|
||||
|
||||
// Use API to create a conflicting pr
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", "user1", "repo1", token), &api.CreatePullRequestOption{
|
||||
Head: "conflict",
|
||||
Base: "base",
|
||||
@ -325,7 +326,7 @@ func TestCantMergeUnrelated(t *testing.T) {
|
||||
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "conflict", "README.md", "Hello, World (Edited Once)\n")
|
||||
|
||||
// Use API to create a conflicting pr
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", "user1", "repo1", token), &api.CreatePullRequestOption{
|
||||
Head: "unrelated",
|
||||
Base: "base",
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -63,7 +64,7 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
||||
api.CommitStatusWarning: "gitea-exclamation",
|
||||
}
|
||||
|
||||
testCtx := NewAPITestContext(t, "user1", "repo1")
|
||||
testCtx := NewAPITestContext(t, "user1", "repo1", auth_model.AccessTokenScopeRepo)
|
||||
|
||||
// Update commit status, and check if icon is updated as well
|
||||
for _, status := range statusList {
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -38,7 +39,7 @@ func TestAPIPullUpdate(t *testing.T) {
|
||||
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "POST", "/api/v1/repos/%s/%s/pulls/%d/update?token="+token, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, pr.Issue.Index)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
@ -66,7 +67,7 @@ func TestAPIPullUpdateByRebase(t *testing.T) {
|
||||
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
||||
req := NewRequestf(t, "POST", "/api/v1/repos/%s/%s/pulls/%d/update?style=rebase&token="+token, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, pr.Issue.Index)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
@ -50,7 +51,8 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
||||
assert.NotEmpty(t, commitURL)
|
||||
|
||||
// Call API to add status for commit
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(NewAPITestContext(t, "user2", "repo1"), path.Base(commitURL), api.CommitStatusState(state)))
|
||||
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CommitStatusState(state)))
|
||||
|
||||
req = NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
@ -142,7 +144,8 @@ func TestRepoCommitsStatusParallel(t *testing.T) {
|
||||
wg.Add(1)
|
||||
go func(parentT *testing.T, i int) {
|
||||
parentT.Run(fmt.Sprintf("ParallelCreateStatus_%d", i), func(t *testing.T) {
|
||||
runBody := doAPICreateCommitStatus(NewAPITestContext(t, "user2", "repo1"), path.Base(commitURL), api.CommitStatusState("pending"))
|
||||
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeRepoStatus)
|
||||
runBody := doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CommitStatusState("pending"))
|
||||
runBody(t)
|
||||
wg.Done()
|
||||
})
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
|
||||
@ -47,7 +48,9 @@ func TestPushDeployKeyOnEmptyRepo(t *testing.T) {
|
||||
|
||||
func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
|
||||
// OK login
|
||||
ctx := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1")
|
||||
ctx := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeRepo)
|
||||
ctxWithDeleteRepo := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeDeleteRepo)
|
||||
|
||||
keyname := fmt.Sprintf("%s-push", ctx.Reponame)
|
||||
u.Path = ctx.GitPath()
|
||||
|
||||
@ -72,7 +75,7 @@ func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
|
||||
|
||||
t.Run("CheckIsNotEmpty", doCheckRepositoryEmptyStatus(ctx, false))
|
||||
|
||||
t.Run("DeleteRepository", doAPIDeleteRepository(ctx))
|
||||
t.Run("DeleteRepository", doAPIDeleteRepository(ctxWithDeleteRepo))
|
||||
})
|
||||
}
|
||||
|
||||
@ -89,10 +92,13 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
|
||||
keyname := fmt.Sprintf("%s-push", reponame)
|
||||
|
||||
// OK login
|
||||
ctx := NewAPITestContext(t, username, reponame)
|
||||
ctx := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeAdminPublicKey)
|
||||
ctxWithDeleteRepo := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeAdminPublicKey, auth_model.AccessTokenScopeDeleteRepo)
|
||||
|
||||
otherCtx := ctx
|
||||
otherCtx.Reponame = "ssh-key-test-repo-2"
|
||||
otherCtxWithDeleteRepo := ctxWithDeleteRepo
|
||||
otherCtxWithDeleteRepo.Reponame = otherCtx.Reponame
|
||||
|
||||
failCtx := ctx
|
||||
failCtx.ExpectedCode = http.StatusUnprocessableEntity
|
||||
@ -160,7 +166,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
|
||||
otherSSHURL := createSSHUrl(otherCtx.GitPath(), u)
|
||||
dstOtherPath := t.TempDir()
|
||||
|
||||
t.Run("DeleteRepository", doAPIDeleteRepository(ctx))
|
||||
t.Run("DeleteRepository", doAPIDeleteRepository(ctxWithDeleteRepo))
|
||||
|
||||
t.Run("FailToCreateUserKeyAsStillDeploy", doAPICreateUserKey(failCtx, keyname, keyFile))
|
||||
|
||||
@ -170,9 +176,9 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
|
||||
|
||||
t.Run("PushToOther", doGitPushTestRepository(dstOtherPath, "origin", "master"))
|
||||
|
||||
t.Run("DeleteOtherRepository", doAPIDeleteRepository(otherCtx))
|
||||
t.Run("DeleteOtherRepository", doAPIDeleteRepository(otherCtxWithDeleteRepo))
|
||||
|
||||
t.Run("RecreateRepository", doAPICreateRepository(ctx, false))
|
||||
t.Run("RecreateRepository", doAPICreateRepository(ctxWithDeleteRepo, false))
|
||||
|
||||
t.Run("CreateUserKey", doAPICreateUserKey(ctx, keyname, keyFile, func(t *testing.T, publicKey api.PublicKey) {
|
||||
userKeyPublicKeyID = publicKey.ID
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -165,7 +166,7 @@ Note: This user hasn't uploaded any GPG keys.
|
||||
// Import key
|
||||
// User1 <user1@example.com>
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteGPGKey)
|
||||
testCreateGPGKey(t, session.MakeRequest, token, http.StatusCreated, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFyy/VUBCADJ7zbM20Z1RWmFoVgp5WkQfI2rU1Vj9cQHes9i42wVLLtcbPeo
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user