Redesign Scoped Access Tokens (#24767)
## Changes - Adds the following high level access scopes, each with `read` and `write` levels: - `activitypub` - `admin` (hidden if user is not a site admin) - `misc` - `notification` - `organization` - `package` - `issue` - `repository` - `user` - Adds new middleware function `tokenRequiresScopes()` in addition to `reqToken()` - `tokenRequiresScopes()` is used for each high-level api section - _if_ a scoped token is present, checks that the required scope is included based on the section and HTTP method - `reqToken()` is used for individual routes - checks that required authentication is present (but does not check scope levels as this will already have been handled by `tokenRequiresScopes()` - Adds migration to convert old scoped access tokens to the new set of scopes - Updates the user interface for scope selection ### User interface example <img width="903" alt="Screen Shot 2023-05-31 at 1 56 55 PM" src="https://github.com/go-gitea/gitea/assets/23248839/654766ec-2143-4f59-9037-3b51600e32f3"> <img width="917" alt="Screen Shot 2023-05-31 at 1 56 43 PM" src="https://github.com/go-gitea/gitea/assets/23248839/1ad64081-012c-4a73-b393-66b30352654c"> ## tokenRequiresScopes Design Decision - `tokenRequiresScopes()` was added to more reliably cover api routes. For an incoming request, this function uses the given scope category (say `AccessTokenScopeCategoryOrganization`) and the HTTP method (say `DELETE`) and verifies that any scoped tokens in use include `delete:organization`. - `reqToken()` is used to enforce auth for individual routes that require it. If a scoped token is not present for a request, `tokenRequiresScopes()` will not return an error ## TODO - [x] Alphabetize scope categories - [x] Change 'public repos only' to a radio button (private vs public). Also expand this to organizations - [X] Disable token creation if no scopes selected. Alternatively, show warning - [x] `reqToken()` is missing from many `POST/DELETE` routes in the api. `tokenRequiresScopes()` only checks that a given token has the correct scope, `reqToken()` must be used to check that a token (or some other auth) is present. - _This should be addressed in this PR_ - [x] The migration should be reviewed very carefully in order to minimize access changes to existing user tokens. - _This should be addressed in this PR_ - [x] Link to api to swagger documentation, clarify what read/write/delete levels correspond to - [x] Review cases where more than one scope is needed as this directly deviates from the api definition. - _This should be addressed in this PR_ - For example: ```go m.Group("/users/{username}/orgs", func() { m.Get("", reqToken(), org.ListUserOrgs) m.Get("/{org}/permissions", reqToken(), org.GetUserOrgsPermissions) }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), context_service.UserAssignmentAPI()) ``` ## Future improvements - [ ] Add required scopes to swagger documentation - [ ] Redesign `reqToken()` to be opt-out rather than opt-in - [ ] Subdivide scopes like `repository` - [ ] Once a token is created, if it has no scopes, we should display text instead of an empty bullet point - [ ] If the 'public repos only' option is selected, should read categories be selected by default Closes #24501 Closes #24799 Co-authored-by: Jonathan Tran <jon@allspice.io> Co-authored-by: Kyle D <kdumontnu@gmail.com> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
parent
520eb57d76
commit
18de83b2a3
102 changed files with 2183 additions and 1038 deletions
|
@ -44,42 +44,43 @@ To use the Authorization Code Grant as a third party application it is required
|
||||||
|
|
||||||
## Scopes
|
## Scopes
|
||||||
|
|
||||||
Gitea supports the following scopes for tokens:
|
Gitea supports scoped access tokens, which allow users the ability to restrict tokens to operate only on selected url routes. Scopes are grouped by high-level API routes, and further refined to the following:
|
||||||
|
|
||||||
| Name | Description |
|
- `read`: `GET` routes
|
||||||
| ---- | ----------- |
|
- `write`: `POST`, `PUT`, `PATCH`, and `DELETE` routes (in addition to `GET`)
|
||||||
| **(no scope)** | Grants read-only access to public user profile and public repositories. |
|
|
||||||
| **repo** | Full control over all repositories. |
|
Gitea token scopes are as follows:
|
||||||
| **repo:status** | Grants read/write access to commit status in all repositories. |
|
|
||||||
| **public_repo** | Grants read/write access to public repositories only. |
|
| Name | Description |
|
||||||
| **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 |
|
| **(no scope)** | Not supported. A scope is required even for public repositories. |
|
||||||
| **read:repo_hook** | Grants read-only access to repository hooks |
|
| **activitypub** | `activitypub` API routes: ActivityPub related operations. |
|
||||||
| **admin:org** | Grants full access to organization settings |
|
| **read:activitypub** | Grants read access for ActivityPub operations. |
|
||||||
| **write:org** | Grants read/write access to organization settings |
|
| **write:activitypub** | Grants read/write/delete access for ActivityPub operations. |
|
||||||
| **read:org** | Grants read-only access to organization settings |
|
| **admin** | `/admin/*` API routes: Site-wide administrative operations (hidden for non-admin accounts). |
|
||||||
| **admin:public_key** | Grants full access for managing public keys |
|
| **read:admin** | Grants read access for admin operations, such as getting cron jobs or registered user emails. |
|
||||||
| **write:public_key** | Grant read/write access to public keys |
|
| **write:admin** | Grants read/write/delete access for admin operations, such as running cron jobs or updating user accounts. | |
|
||||||
| **read:public_key** | Grant read-only access to public keys |
|
| **issue** | `issues/*`, `labels/*`, `milestones/*` API routes: Issue-related operations. |
|
||||||
| **admin:org_hook** | Grants full access to organizational-level hooks |
|
| **read:issue** | Grants read access for issues operations, such as getting issue comments, issue attachments, and milestones. |
|
||||||
| **admin:user_hook** | Grants full access to user-level hooks |
|
| **write:issue** | Grants read/write/delete access for issues operations, such as posting or editing an issue comment or attachment, and updating milestones. |
|
||||||
| **notification** | Grants full access to notifications |
|
| **misc** | miscellaneous and settings top-level API routes. |
|
||||||
| **user** | Grants full access to user profile info |
|
| **read:misc** | Grants read access to miscellaneous operations, such as getting label and gitignore templates. |
|
||||||
| **read:user** | Grants read access to user's profile |
|
| **write:misc** | Grants read/write/delete access to miscellaneous operations, such as markup utility operations. |
|
||||||
| **user:email** | Grants read access to user's email addresses |
|
| **notification** | `notification/*` API routes: user notification operations. |
|
||||||
| **user:follow** | Grants access to follow/un-follow a user |
|
| **read:notification** | Grants read access to user notifications, such as which notifications users are subscribed to and read new notifications. |
|
||||||
| **delete_repo** | Grants access to delete repositories as an admin |
|
| **write:notification** | Grants read/write/delete access to user notifications, such as marking notifications as read. |
|
||||||
| **package** | Grants full access to hosted packages |
|
| **organization** | `orgs/*` and `teams/*` API routes: Organization and team management operations. |
|
||||||
| **write:package** | Grants read/write access to packages |
|
| **read:organization** | Grants read access to org and team status, such as listing all orgs a user has visibility to, teams, and team members. |
|
||||||
| **read:package** | Grants read access to packages |
|
| **write:organization** | Grants read/write/delete access to org and team status, such as creating and updating teams and updating org settings. |
|
||||||
| **delete:package** | Grants delete access to packages |
|
| **package** | `/packages/*` API routes: Packages operations |
|
||||||
| **admin:gpg_key** | Grants full access for managing GPG keys |
|
| **read:package** | Grants read access to package operations, such as reading and downloading available packages. |
|
||||||
| **write:gpg_key** | Grants read/write access to GPG keys |
|
| **write:package** | Grants read/write/delete access to package operations. Currently the same as `read:package`. |
|
||||||
| **read:gpg_key** | Grants read-only access to GPG keys |
|
| **repository** | `/repos/*` API routes except `/repos/issues/*`: Repository file, pull-request, and release operations. |
|
||||||
| **admin:application** | Grants full access to manage applications |
|
| **read:repository** | Grants read access to repository operations, such as getting repository files, releases, collaborators. |
|
||||||
| **write:application** | Grants read/write access for managing applications |
|
| **write:repository** | Grants read/write/delete access to repository operations, such as getting updating repository files, creating pull requests, updating collaborators. |
|
||||||
| **read:application** | Grants read access for managing applications |
|
| **user** | `/user/*` and `/users/*` API routes: User-related operations. |
|
||||||
| **sudo** | Allows to perform actions as the site admin. |
|
| **read:user** | Grants read access to user operations, such as getting user repo subscriptions and user settings. |
|
||||||
|
| **write:user** | Grants read/write/delete access to user operations, such as updating user repo subscriptions, followed users, and user settings. |
|
||||||
|
|
||||||
## Client types
|
## Client types
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,15 @@ func NewAccessToken(t *AccessToken) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DisplayPublicOnly whether to display this as a public-only token.
|
||||||
|
func (t *AccessToken) DisplayPublicOnly() bool {
|
||||||
|
publicOnly, err := t.Scope.PublicOnly()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return publicOnly
|
||||||
|
}
|
||||||
|
|
||||||
func getAccessTokenIDFromCache(token string) int64 {
|
func getAccessTokenIDFromCache(token string) int64 {
|
||||||
if successfulAccessTokenCache == nil {
|
if successfulAccessTokenCache == nil {
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -6,113 +6,122 @@ package auth
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AccessTokenScopeCategory represents the scope category for an access token
|
||||||
|
type AccessTokenScopeCategory int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AccessTokenScopeCategoryActivityPub = iota
|
||||||
|
AccessTokenScopeCategoryAdmin
|
||||||
|
AccessTokenScopeCategoryMisc
|
||||||
|
AccessTokenScopeCategoryNotification
|
||||||
|
AccessTokenScopeCategoryOrganization
|
||||||
|
AccessTokenScopeCategoryPackage
|
||||||
|
AccessTokenScopeCategoryIssue
|
||||||
|
AccessTokenScopeCategoryRepository
|
||||||
|
AccessTokenScopeCategoryUser
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllAccessTokenScopeCategories contains all access token scope categories
|
||||||
|
var AllAccessTokenScopeCategories = []AccessTokenScopeCategory{
|
||||||
|
AccessTokenScopeCategoryActivityPub,
|
||||||
|
AccessTokenScopeCategoryAdmin,
|
||||||
|
AccessTokenScopeCategoryMisc,
|
||||||
|
AccessTokenScopeCategoryNotification,
|
||||||
|
AccessTokenScopeCategoryOrganization,
|
||||||
|
AccessTokenScopeCategoryPackage,
|
||||||
|
AccessTokenScopeCategoryIssue,
|
||||||
|
AccessTokenScopeCategoryRepository,
|
||||||
|
AccessTokenScopeCategoryUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessTokenScopeLevel represents the access levels without a given scope category
|
||||||
|
type AccessTokenScopeLevel int
|
||||||
|
|
||||||
|
const (
|
||||||
|
NoAccess AccessTokenScopeLevel = iota
|
||||||
|
Read
|
||||||
|
Write
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccessTokenScope represents the scope for an access token.
|
// AccessTokenScope represents the scope for an access token.
|
||||||
type AccessTokenScope string
|
type AccessTokenScope string
|
||||||
|
|
||||||
|
// for all categories, write implies read
|
||||||
const (
|
const (
|
||||||
AccessTokenScopeAll AccessTokenScope = "all"
|
AccessTokenScopeAll AccessTokenScope = "all"
|
||||||
|
AccessTokenScopePublicOnly AccessTokenScope = "public-only" // limited to public orgs/repos
|
||||||
|
|
||||||
AccessTokenScopeRepo AccessTokenScope = "repo"
|
AccessTokenScopeReadActivityPub AccessTokenScope = "read:activitypub"
|
||||||
AccessTokenScopeRepoStatus AccessTokenScope = "repo:status"
|
AccessTokenScopeWriteActivityPub AccessTokenScope = "write:activitypub"
|
||||||
AccessTokenScopePublicRepo AccessTokenScope = "public_repo"
|
|
||||||
|
|
||||||
AccessTokenScopeAdminOrg AccessTokenScope = "admin:org"
|
AccessTokenScopeReadAdmin AccessTokenScope = "read:admin"
|
||||||
AccessTokenScopeWriteOrg AccessTokenScope = "write:org"
|
AccessTokenScopeWriteAdmin AccessTokenScope = "write:admin"
|
||||||
AccessTokenScopeReadOrg AccessTokenScope = "read:org"
|
|
||||||
|
|
||||||
AccessTokenScopeAdminPublicKey AccessTokenScope = "admin:public_key"
|
AccessTokenScopeReadMisc AccessTokenScope = "read:misc"
|
||||||
AccessTokenScopeWritePublicKey AccessTokenScope = "write:public_key"
|
AccessTokenScopeWriteMisc AccessTokenScope = "write:misc"
|
||||||
AccessTokenScopeReadPublicKey AccessTokenScope = "read:public_key"
|
|
||||||
|
|
||||||
AccessTokenScopeAdminRepoHook AccessTokenScope = "admin:repo_hook"
|
AccessTokenScopeReadNotification AccessTokenScope = "read:notification"
|
||||||
AccessTokenScopeWriteRepoHook AccessTokenScope = "write:repo_hook"
|
AccessTokenScopeWriteNotification AccessTokenScope = "write:notification"
|
||||||
AccessTokenScopeReadRepoHook AccessTokenScope = "read:repo_hook"
|
|
||||||
|
|
||||||
AccessTokenScopeAdminOrgHook AccessTokenScope = "admin:org_hook"
|
AccessTokenScopeReadOrganization AccessTokenScope = "read:organization"
|
||||||
|
AccessTokenScopeWriteOrganization AccessTokenScope = "write:organization"
|
||||||
|
|
||||||
AccessTokenScopeAdminUserHook AccessTokenScope = "admin:user_hook"
|
AccessTokenScopeReadPackage AccessTokenScope = "read:package"
|
||||||
|
AccessTokenScopeWritePackage AccessTokenScope = "write:package"
|
||||||
|
|
||||||
AccessTokenScopeNotification AccessTokenScope = "notification"
|
AccessTokenScopeReadIssue AccessTokenScope = "read:issue"
|
||||||
|
AccessTokenScopeWriteIssue AccessTokenScope = "write:issue"
|
||||||
|
|
||||||
AccessTokenScopeUser AccessTokenScope = "user"
|
AccessTokenScopeReadRepository AccessTokenScope = "read:repository"
|
||||||
AccessTokenScopeReadUser AccessTokenScope = "read:user"
|
AccessTokenScopeWriteRepository AccessTokenScope = "write:repository"
|
||||||
AccessTokenScopeUserEmail AccessTokenScope = "user:email"
|
|
||||||
AccessTokenScopeUserFollow AccessTokenScope = "user:follow"
|
|
||||||
|
|
||||||
AccessTokenScopeDeleteRepo AccessTokenScope = "delete_repo"
|
AccessTokenScopeReadUser AccessTokenScope = "read:user"
|
||||||
|
AccessTokenScopeWriteUser AccessTokenScope = "write:user"
|
||||||
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.
|
// accessTokenScopeBitmap represents a bitmap of access token scopes.
|
||||||
type AccessTokenScopeBitmap uint64
|
type accessTokenScopeBitmap uint64
|
||||||
|
|
||||||
// Bitmap of each scope, including the child scopes.
|
// Bitmap of each scope, including the child scopes.
|
||||||
const (
|
const (
|
||||||
// AccessTokenScopeAllBits is the bitmap of all access token scopes, except `sudo`.
|
// AccessTokenScopeAllBits is the bitmap of all access token scopes
|
||||||
AccessTokenScopeAllBits AccessTokenScopeBitmap = AccessTokenScopeRepoBits |
|
accessTokenScopeAllBits accessTokenScopeBitmap = accessTokenScopeWriteActivityPubBits |
|
||||||
AccessTokenScopeAdminOrgBits | AccessTokenScopeAdminPublicKeyBits | AccessTokenScopeAdminOrgHookBits | AccessTokenScopeAdminUserHookBits |
|
accessTokenScopeWriteAdminBits | accessTokenScopeWriteMiscBits | accessTokenScopeWriteNotificationBits |
|
||||||
AccessTokenScopeNotificationBits | AccessTokenScopeUserBits | AccessTokenScopeDeleteRepoBits |
|
accessTokenScopeWriteOrganizationBits | accessTokenScopeWritePackageBits | accessTokenScopeWriteIssueBits |
|
||||||
AccessTokenScopePackageBits | AccessTokenScopeAdminGPGKeyBits | AccessTokenScopeAdminApplicationBits
|
accessTokenScopeWriteRepositoryBits | accessTokenScopeWriteUserBits
|
||||||
|
|
||||||
AccessTokenScopeRepoBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeRepoStatusBits | AccessTokenScopePublicRepoBits | AccessTokenScopeAdminRepoHookBits
|
accessTokenScopePublicOnlyBits accessTokenScopeBitmap = 1 << iota
|
||||||
AccessTokenScopeRepoStatusBits AccessTokenScopeBitmap = 1 << iota
|
|
||||||
AccessTokenScopePublicRepoBits AccessTokenScopeBitmap = 1 << iota
|
|
||||||
|
|
||||||
AccessTokenScopeAdminOrgBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWriteOrgBits
|
accessTokenScopeReadActivityPubBits accessTokenScopeBitmap = 1 << iota
|
||||||
AccessTokenScopeWriteOrgBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadOrgBits
|
accessTokenScopeWriteActivityPubBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadActivityPubBits
|
||||||
AccessTokenScopeReadOrgBits AccessTokenScopeBitmap = 1 << iota
|
|
||||||
|
|
||||||
AccessTokenScopeAdminPublicKeyBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWritePublicKeyBits
|
accessTokenScopeReadAdminBits accessTokenScopeBitmap = 1 << iota
|
||||||
AccessTokenScopeWritePublicKeyBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadPublicKeyBits
|
accessTokenScopeWriteAdminBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadAdminBits
|
||||||
AccessTokenScopeReadPublicKeyBits AccessTokenScopeBitmap = 1 << iota
|
|
||||||
|
|
||||||
AccessTokenScopeAdminRepoHookBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWriteRepoHookBits
|
accessTokenScopeReadMiscBits accessTokenScopeBitmap = 1 << iota
|
||||||
AccessTokenScopeWriteRepoHookBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadRepoHookBits
|
accessTokenScopeWriteMiscBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadMiscBits
|
||||||
AccessTokenScopeReadRepoHookBits AccessTokenScopeBitmap = 1 << iota
|
|
||||||
|
|
||||||
AccessTokenScopeAdminOrgHookBits AccessTokenScopeBitmap = 1 << iota
|
accessTokenScopeReadNotificationBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteNotificationBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadNotificationBits
|
||||||
|
|
||||||
AccessTokenScopeAdminUserHookBits AccessTokenScopeBitmap = 1 << iota
|
accessTokenScopeReadOrganizationBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteOrganizationBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadOrganizationBits
|
||||||
|
|
||||||
AccessTokenScopeNotificationBits AccessTokenScopeBitmap = 1 << iota
|
accessTokenScopeReadPackageBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWritePackageBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadPackageBits
|
||||||
|
|
||||||
AccessTokenScopeUserBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadUserBits | AccessTokenScopeUserEmailBits | AccessTokenScopeUserFollowBits
|
accessTokenScopeReadIssueBits accessTokenScopeBitmap = 1 << iota
|
||||||
AccessTokenScopeReadUserBits AccessTokenScopeBitmap = 1 << iota
|
accessTokenScopeWriteIssueBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadIssueBits
|
||||||
AccessTokenScopeUserEmailBits AccessTokenScopeBitmap = 1 << iota
|
|
||||||
AccessTokenScopeUserFollowBits AccessTokenScopeBitmap = 1 << iota
|
|
||||||
|
|
||||||
AccessTokenScopeDeleteRepoBits AccessTokenScopeBitmap = 1 << iota
|
accessTokenScopeReadRepositoryBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteRepositoryBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadRepositoryBits
|
||||||
|
|
||||||
AccessTokenScopePackageBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeWritePackageBits | AccessTokenScopeDeletePackageBits
|
accessTokenScopeReadUserBits accessTokenScopeBitmap = 1 << iota
|
||||||
AccessTokenScopeWritePackageBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadPackageBits
|
accessTokenScopeWriteUserBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadUserBits
|
||||||
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.
|
// The current implementation only supports up to 64 token scopes.
|
||||||
// If we need to support > 64 scopes,
|
// If we need to support > 64 scopes,
|
||||||
|
@ -120,61 +129,110 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// allAccessTokenScopes contains all access token scopes.
|
// allAccessTokenScopes contains all access token scopes.
|
||||||
// The order is important: parent scope must precedes child scopes.
|
// The order is important: parent scope must precede child scopes.
|
||||||
var allAccessTokenScopes = []AccessTokenScope{
|
var allAccessTokenScopes = []AccessTokenScope{
|
||||||
AccessTokenScopeRepo, AccessTokenScopeRepoStatus, AccessTokenScopePublicRepo,
|
AccessTokenScopePublicOnly,
|
||||||
AccessTokenScopeAdminOrg, AccessTokenScopeWriteOrg, AccessTokenScopeReadOrg,
|
AccessTokenScopeWriteActivityPub, AccessTokenScopeReadActivityPub,
|
||||||
AccessTokenScopeAdminPublicKey, AccessTokenScopeWritePublicKey, AccessTokenScopeReadPublicKey,
|
AccessTokenScopeWriteAdmin, AccessTokenScopeReadAdmin,
|
||||||
AccessTokenScopeAdminRepoHook, AccessTokenScopeWriteRepoHook, AccessTokenScopeReadRepoHook,
|
AccessTokenScopeWriteMisc, AccessTokenScopeReadMisc,
|
||||||
AccessTokenScopeAdminOrgHook,
|
AccessTokenScopeWriteNotification, AccessTokenScopeReadNotification,
|
||||||
AccessTokenScopeAdminUserHook,
|
AccessTokenScopeWriteOrganization, AccessTokenScopeReadOrganization,
|
||||||
AccessTokenScopeNotification,
|
AccessTokenScopeWritePackage, AccessTokenScopeReadPackage,
|
||||||
AccessTokenScopeUser, AccessTokenScopeReadUser, AccessTokenScopeUserEmail, AccessTokenScopeUserFollow,
|
AccessTokenScopeWriteIssue, AccessTokenScopeReadIssue,
|
||||||
AccessTokenScopeDeleteRepo,
|
AccessTokenScopeWriteRepository, AccessTokenScopeReadRepository,
|
||||||
AccessTokenScopePackage, AccessTokenScopeWritePackage, AccessTokenScopeReadPackage, AccessTokenScopeDeletePackage,
|
AccessTokenScopeWriteUser, AccessTokenScopeReadUser,
|
||||||
AccessTokenScopeAdminGPGKey, AccessTokenScopeWriteGPGKey, AccessTokenScopeReadGPGKey,
|
|
||||||
AccessTokenScopeAdminApplication, AccessTokenScopeWriteApplication, AccessTokenScopeReadApplication,
|
|
||||||
AccessTokenScopeSudo,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// allAccessTokenScopeBits contains all access token scopes.
|
// allAccessTokenScopeBits contains all access token scopes.
|
||||||
var allAccessTokenScopeBits = map[AccessTokenScope]AccessTokenScopeBitmap{
|
var allAccessTokenScopeBits = map[AccessTokenScope]accessTokenScopeBitmap{
|
||||||
AccessTokenScopeRepo: AccessTokenScopeRepoBits,
|
AccessTokenScopeAll: accessTokenScopeAllBits,
|
||||||
AccessTokenScopeRepoStatus: AccessTokenScopeRepoStatusBits,
|
AccessTokenScopePublicOnly: accessTokenScopePublicOnlyBits,
|
||||||
AccessTokenScopePublicRepo: AccessTokenScopePublicRepoBits,
|
AccessTokenScopeReadActivityPub: accessTokenScopeReadActivityPubBits,
|
||||||
AccessTokenScopeAdminOrg: AccessTokenScopeAdminOrgBits,
|
AccessTokenScopeWriteActivityPub: accessTokenScopeWriteActivityPubBits,
|
||||||
AccessTokenScopeWriteOrg: AccessTokenScopeWriteOrgBits,
|
AccessTokenScopeReadAdmin: accessTokenScopeReadAdminBits,
|
||||||
AccessTokenScopeReadOrg: AccessTokenScopeReadOrgBits,
|
AccessTokenScopeWriteAdmin: accessTokenScopeWriteAdminBits,
|
||||||
AccessTokenScopeAdminPublicKey: AccessTokenScopeAdminPublicKeyBits,
|
AccessTokenScopeReadMisc: accessTokenScopeReadMiscBits,
|
||||||
AccessTokenScopeWritePublicKey: AccessTokenScopeWritePublicKeyBits,
|
AccessTokenScopeWriteMisc: accessTokenScopeWriteMiscBits,
|
||||||
AccessTokenScopeReadPublicKey: AccessTokenScopeReadPublicKeyBits,
|
AccessTokenScopeReadNotification: accessTokenScopeReadNotificationBits,
|
||||||
AccessTokenScopeAdminRepoHook: AccessTokenScopeAdminRepoHookBits,
|
AccessTokenScopeWriteNotification: accessTokenScopeWriteNotificationBits,
|
||||||
AccessTokenScopeWriteRepoHook: AccessTokenScopeWriteRepoHookBits,
|
AccessTokenScopeReadOrganization: accessTokenScopeReadOrganizationBits,
|
||||||
AccessTokenScopeReadRepoHook: AccessTokenScopeReadRepoHookBits,
|
AccessTokenScopeWriteOrganization: accessTokenScopeWriteOrganizationBits,
|
||||||
AccessTokenScopeAdminOrgHook: AccessTokenScopeAdminOrgHookBits,
|
AccessTokenScopeReadPackage: accessTokenScopeReadPackageBits,
|
||||||
AccessTokenScopeAdminUserHook: AccessTokenScopeAdminUserHookBits,
|
AccessTokenScopeWritePackage: accessTokenScopeWritePackageBits,
|
||||||
AccessTokenScopeNotification: AccessTokenScopeNotificationBits,
|
AccessTokenScopeReadIssue: accessTokenScopeReadIssueBits,
|
||||||
AccessTokenScopeUser: AccessTokenScopeUserBits,
|
AccessTokenScopeWriteIssue: accessTokenScopeWriteIssueBits,
|
||||||
AccessTokenScopeReadUser: AccessTokenScopeReadUserBits,
|
AccessTokenScopeReadRepository: accessTokenScopeReadRepositoryBits,
|
||||||
AccessTokenScopeUserEmail: AccessTokenScopeUserEmailBits,
|
AccessTokenScopeWriteRepository: accessTokenScopeWriteRepositoryBits,
|
||||||
AccessTokenScopeUserFollow: AccessTokenScopeUserFollowBits,
|
AccessTokenScopeReadUser: accessTokenScopeReadUserBits,
|
||||||
AccessTokenScopeDeleteRepo: AccessTokenScopeDeleteRepoBits,
|
AccessTokenScopeWriteUser: accessTokenScopeWriteUserBits,
|
||||||
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.
|
// readAccessTokenScopes maps a scope category to the read permission scope
|
||||||
func (s AccessTokenScope) Parse() (AccessTokenScopeBitmap, error) {
|
var accessTokenScopes = map[AccessTokenScopeLevel]map[AccessTokenScopeCategory]AccessTokenScope{
|
||||||
var bitmap AccessTokenScopeBitmap
|
Read: {
|
||||||
|
AccessTokenScopeCategoryActivityPub: AccessTokenScopeReadActivityPub,
|
||||||
|
AccessTokenScopeCategoryAdmin: AccessTokenScopeReadAdmin,
|
||||||
|
AccessTokenScopeCategoryMisc: AccessTokenScopeReadMisc,
|
||||||
|
AccessTokenScopeCategoryNotification: AccessTokenScopeReadNotification,
|
||||||
|
AccessTokenScopeCategoryOrganization: AccessTokenScopeReadOrganization,
|
||||||
|
AccessTokenScopeCategoryPackage: AccessTokenScopeReadPackage,
|
||||||
|
AccessTokenScopeCategoryIssue: AccessTokenScopeReadIssue,
|
||||||
|
AccessTokenScopeCategoryRepository: AccessTokenScopeReadRepository,
|
||||||
|
AccessTokenScopeCategoryUser: AccessTokenScopeReadUser,
|
||||||
|
},
|
||||||
|
Write: {
|
||||||
|
AccessTokenScopeCategoryActivityPub: AccessTokenScopeWriteActivityPub,
|
||||||
|
AccessTokenScopeCategoryAdmin: AccessTokenScopeWriteAdmin,
|
||||||
|
AccessTokenScopeCategoryMisc: AccessTokenScopeWriteMisc,
|
||||||
|
AccessTokenScopeCategoryNotification: AccessTokenScopeWriteNotification,
|
||||||
|
AccessTokenScopeCategoryOrganization: AccessTokenScopeWriteOrganization,
|
||||||
|
AccessTokenScopeCategoryPackage: AccessTokenScopeWritePackage,
|
||||||
|
AccessTokenScopeCategoryIssue: AccessTokenScopeWriteIssue,
|
||||||
|
AccessTokenScopeCategoryRepository: AccessTokenScopeWriteRepository,
|
||||||
|
AccessTokenScopeCategoryUser: AccessTokenScopeWriteUser,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRequiredScopes gets the specific scopes for a given level and categories
|
||||||
|
func GetRequiredScopes(level AccessTokenScopeLevel, scopeCategories ...AccessTokenScopeCategory) []AccessTokenScope {
|
||||||
|
scopes := make([]AccessTokenScope, 0, len(scopeCategories))
|
||||||
|
for _, cat := range scopeCategories {
|
||||||
|
scopes = append(scopes, accessTokenScopes[level][cat])
|
||||||
|
}
|
||||||
|
return scopes
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsCategory checks if a list of categories contains a specific category
|
||||||
|
func ContainsCategory(categories []AccessTokenScopeCategory, category AccessTokenScopeCategory) bool {
|
||||||
|
for _, c := range categories {
|
||||||
|
if c == category {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetScopeLevelFromAccessMode converts permission access mode to scope level
|
||||||
|
func GetScopeLevelFromAccessMode(mode perm.AccessMode) AccessTokenScopeLevel {
|
||||||
|
switch mode {
|
||||||
|
case perm.AccessModeNone:
|
||||||
|
return NoAccess
|
||||||
|
case perm.AccessModeRead:
|
||||||
|
return Read
|
||||||
|
case perm.AccessModeWrite:
|
||||||
|
return Write
|
||||||
|
case perm.AccessModeAdmin:
|
||||||
|
return Write
|
||||||
|
case perm.AccessModeOwner:
|
||||||
|
return Write
|
||||||
|
default:
|
||||||
|
return NoAccess
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the scope string into a bitmap, thus removing possible duplicates.
|
||||||
|
func (s AccessTokenScope) parse() (accessTokenScopeBitmap, error) {
|
||||||
|
var bitmap accessTokenScopeBitmap
|
||||||
|
|
||||||
// The following is the more performant equivalent of 'for _, v := range strings.Split(remainingScope, ",")' as this is hot code
|
// The following is the more performant equivalent of 'for _, v := range strings.Split(remainingScope, ",")' as this is hot code
|
||||||
remainingScopes := string(s)
|
remainingScopes := string(s)
|
||||||
|
@ -196,7 +254,7 @@ func (s AccessTokenScope) Parse() (AccessTokenScopeBitmap, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if singleScope == AccessTokenScopeAll {
|
if singleScope == AccessTokenScopeAll {
|
||||||
bitmap |= AccessTokenScopeAllBits
|
bitmap |= accessTokenScopeAllBits
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,26 +275,42 @@ func (s AccessTokenScope) StringSlice() []string {
|
||||||
|
|
||||||
// Normalize returns a normalized scope string without any duplicates.
|
// Normalize returns a normalized scope string without any duplicates.
|
||||||
func (s AccessTokenScope) Normalize() (AccessTokenScope, error) {
|
func (s AccessTokenScope) Normalize() (AccessTokenScope, error) {
|
||||||
bitmap, err := s.Parse()
|
bitmap, err := s.parse()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitmap.ToScope(), nil
|
return bitmap.toScope(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasScope returns true if the string has the given scope
|
// PublicOnly checks if this token scope is limited to public resources
|
||||||
func (s AccessTokenScope) HasScope(scope AccessTokenScope) (bool, error) {
|
func (s AccessTokenScope) PublicOnly() (bool, error) {
|
||||||
bitmap, err := s.Parse()
|
bitmap, err := s.parse()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitmap.HasScope(scope)
|
return bitmap.hasScope(AccessTokenScopePublicOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasScope returns true if the string has the given scope
|
// HasScope returns true if the string has the given scope
|
||||||
func (bitmap AccessTokenScopeBitmap) HasScope(scope AccessTokenScope) (bool, error) {
|
func (s AccessTokenScope) HasScope(scopes ...AccessTokenScope) (bool, error) {
|
||||||
|
bitmap, err := s.parse()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scopes {
|
||||||
|
if has, err := bitmap.hasScope(s); !has || err != nil {
|
||||||
|
return has, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasScope returns true if the string has the given scope
|
||||||
|
func (bitmap accessTokenScopeBitmap) hasScope(scope AccessTokenScope) (bool, error) {
|
||||||
expectedBits, ok := allAccessTokenScopeBits[scope]
|
expectedBits, ok := allAccessTokenScopeBits[scope]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, fmt.Errorf("invalid access token scope: %s", scope)
|
return false, fmt.Errorf("invalid access token scope: %s", scope)
|
||||||
|
@ -245,17 +319,17 @@ func (bitmap AccessTokenScopeBitmap) HasScope(scope AccessTokenScope) (bool, err
|
||||||
return bitmap&expectedBits == expectedBits, nil
|
return bitmap&expectedBits == expectedBits, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToScope returns a normalized scope string without any duplicates.
|
// toScope returns a normalized scope string without any duplicates.
|
||||||
func (bitmap AccessTokenScopeBitmap) ToScope() AccessTokenScope {
|
func (bitmap accessTokenScopeBitmap) toScope() AccessTokenScope {
|
||||||
var scopes []string
|
var scopes []string
|
||||||
|
|
||||||
// iterate over all scopes, and reconstruct the bitmap
|
// iterate over all scopes, and reconstruct the bitmap
|
||||||
// if the reconstructed bitmap doesn't change, then the scope is already included
|
// if the reconstructed bitmap doesn't change, then the scope is already included
|
||||||
var reconstruct AccessTokenScopeBitmap
|
var reconstruct accessTokenScopeBitmap
|
||||||
|
|
||||||
for _, singleScope := range allAccessTokenScopes {
|
for _, singleScope := range allAccessTokenScopes {
|
||||||
// no need for error checking here, since we know the scope is valid
|
// no need for error checking here, since we know the scope is valid
|
||||||
if ok, _ := bitmap.HasScope(singleScope); ok {
|
if ok, _ := bitmap.hasScope(singleScope); ok {
|
||||||
current := reconstruct | allAccessTokenScopeBits[singleScope]
|
current := reconstruct | allAccessTokenScopeBits[singleScope]
|
||||||
if current == reconstruct {
|
if current == reconstruct {
|
||||||
continue
|
continue
|
||||||
|
@ -269,7 +343,7 @@ func (bitmap AccessTokenScopeBitmap) ToScope() AccessTokenScope {
|
||||||
scope := AccessTokenScope(strings.Join(scopes, ","))
|
scope := AccessTokenScope(strings.Join(scopes, ","))
|
||||||
scope = AccessTokenScope(strings.ReplaceAll(
|
scope = AccessTokenScope(strings.ReplaceAll(
|
||||||
string(scope),
|
string(scope),
|
||||||
"repo,admin:org,admin:public_key,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application",
|
"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user",
|
||||||
"all",
|
"all",
|
||||||
))
|
))
|
||||||
return scope
|
return scope
|
||||||
|
|
|
@ -4,44 +4,35 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type scopeTestNormalize struct {
|
||||||
|
in AccessTokenScope
|
||||||
|
out AccessTokenScope
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
func TestAccessTokenScope_Normalize(t *testing.T) {
|
func TestAccessTokenScope_Normalize(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []scopeTestNormalize{
|
||||||
in AccessTokenScope
|
|
||||||
out AccessTokenScope
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
{"", "", nil},
|
{"", "", nil},
|
||||||
{"repo", "repo", nil},
|
{"write:misc,write:notification,read:package,write:notification,public-only", "public-only,write:misc,write:notification,read:package", 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},
|
{"all", "all", nil},
|
||||||
{"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application", "all", nil},
|
{"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user", "all", nil},
|
||||||
{"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application,sudo", "all,sudo", nil},
|
{"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user,public-only", "public-only,all", nil},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, scope := range []string{"activitypub", "admin", "misc", "notification", "organization", "package", "issue", "repository", "user"} {
|
||||||
|
tests = append(tests,
|
||||||
|
scopeTestNormalize{AccessTokenScope(fmt.Sprintf("read:%s", scope)), AccessTokenScope(fmt.Sprintf("read:%s", scope)), nil},
|
||||||
|
scopeTestNormalize{AccessTokenScope(fmt.Sprintf("write:%s", scope)), AccessTokenScope(fmt.Sprintf("write:%s", scope)), nil},
|
||||||
|
scopeTestNormalize{AccessTokenScope(fmt.Sprintf("write:%[1]s,read:%[1]s", scope)), AccessTokenScope(fmt.Sprintf("write:%s", scope)), nil},
|
||||||
|
scopeTestNormalize{AccessTokenScope(fmt.Sprintf("read:%[1]s,write:%[1]s", scope)), AccessTokenScope(fmt.Sprintf("write:%s", scope)), nil},
|
||||||
|
scopeTestNormalize{AccessTokenScope(fmt.Sprintf("read:%[1]s,write:%[1]s,write:%[1]s", scope)), AccessTokenScope(fmt.Sprintf("write:%s", scope)), nil},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -53,31 +44,46 @@ func TestAccessTokenScope_Normalize(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type scopeTestHasScope struct {
|
||||||
|
in AccessTokenScope
|
||||||
|
scope AccessTokenScope
|
||||||
|
out bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
func TestAccessTokenScope_HasScope(t *testing.T) {
|
func TestAccessTokenScope_HasScope(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []scopeTestHasScope{
|
||||||
in AccessTokenScope
|
{"read:admin", "write:package", false, nil},
|
||||||
scope AccessTokenScope
|
{"all", "write:package", true, nil},
|
||||||
out bool
|
{"write:package", "all", false, nil},
|
||||||
err error
|
{"public-only", "read:issue", false, nil},
|
||||||
}{
|
}
|
||||||
{"repo", "repo", true, nil},
|
|
||||||
{"repo", "repo:status", true, nil},
|
for _, scope := range []string{"activitypub", "admin", "misc", "notification", "organization", "package", "issue", "repository", "user"} {
|
||||||
{"repo", "public_repo", true, nil},
|
tests = append(tests,
|
||||||
{"repo", "admin:org", false, nil},
|
scopeTestHasScope{
|
||||||
{"repo", "admin:public_key", false, nil},
|
AccessTokenScope(fmt.Sprintf("read:%s", scope)),
|
||||||
{"repo:status", "repo", false, nil},
|
AccessTokenScope(fmt.Sprintf("read:%s", scope)), true, nil,
|
||||||
{"repo:status", "public_repo", false, nil},
|
},
|
||||||
{"admin:org", "write:org", true, nil},
|
scopeTestHasScope{
|
||||||
{"admin:org", "read:org", true, nil},
|
AccessTokenScope(fmt.Sprintf("write:%s", scope)),
|
||||||
{"admin:org", "admin:org", true, nil},
|
AccessTokenScope(fmt.Sprintf("write:%s", scope)), true, nil,
|
||||||
{"user", "read:user", true, nil},
|
},
|
||||||
{"package", "write:package", true, nil},
|
scopeTestHasScope{
|
||||||
|
AccessTokenScope(fmt.Sprintf("write:%s", scope)),
|
||||||
|
AccessTokenScope(fmt.Sprintf("read:%s", scope)), true, nil,
|
||||||
|
},
|
||||||
|
scopeTestHasScope{
|
||||||
|
AccessTokenScope(fmt.Sprintf("read:%s", scope)),
|
||||||
|
AccessTokenScope(fmt.Sprintf("write:%s", scope)), false, nil,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(string(test.in), func(t *testing.T) {
|
t.Run(string(test.in), func(t *testing.T) {
|
||||||
scope, err := test.in.HasScope(test.scope)
|
hasScope, err := test.in.HasScope(test.scope)
|
||||||
assert.Equal(t, test.out, scope)
|
assert.Equal(t, test.out, hasScope)
|
||||||
assert.Equal(t, test.err, err)
|
assert.Equal(t, test.err, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -495,6 +495,8 @@ var migrations = []Migration{
|
||||||
NewMigration("Add Actions Artifact table", v1_20.CreateActionArtifactTable),
|
NewMigration("Add Actions Artifact table", v1_20.CreateActionArtifactTable),
|
||||||
// v258 -> 259
|
// v258 -> 259
|
||||||
NewMigration("Add PinOrder Column", v1_20.AddPinOrderToIssue),
|
NewMigration("Add PinOrder Column", v1_20.AddPinOrderToIssue),
|
||||||
|
// v259 -> 260
|
||||||
|
NewMigration("Convert scoped access tokens", v1_20.ConvertScopedAccessTokens),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentDBVersion returns the current db version
|
// GetCurrentDBVersion returns the current db version
|
||||||
|
|
14
models/migrations/v1_20/main_test.go
Normal file
14
models/migrations/v1_20/main_test.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package v1_20 //nolint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/migrations/base"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
base.MainTest(m)
|
||||||
|
}
|
360
models/migrations/v1_20/v259.go
Normal file
360
models/migrations/v1_20/v259.go
Normal file
|
@ -0,0 +1,360 @@
|
||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package v1_20 //nolint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// unknownAccessTokenScope represents the scope for an access token that isn't
|
||||||
|
// known be an old token or a new token.
|
||||||
|
type unknownAccessTokenScope string
|
||||||
|
|
||||||
|
// AccessTokenScope represents the scope for an access token.
|
||||||
|
type AccessTokenScope string
|
||||||
|
|
||||||
|
// for all categories, write implies read
|
||||||
|
const (
|
||||||
|
AccessTokenScopeAll AccessTokenScope = "all"
|
||||||
|
AccessTokenScopePublicOnly AccessTokenScope = "public-only" // limited to public orgs/repos
|
||||||
|
|
||||||
|
AccessTokenScopeReadActivityPub AccessTokenScope = "read:activitypub"
|
||||||
|
AccessTokenScopeWriteActivityPub AccessTokenScope = "write:activitypub"
|
||||||
|
|
||||||
|
AccessTokenScopeReadAdmin AccessTokenScope = "read:admin"
|
||||||
|
AccessTokenScopeWriteAdmin AccessTokenScope = "write:admin"
|
||||||
|
|
||||||
|
AccessTokenScopeReadMisc AccessTokenScope = "read:misc"
|
||||||
|
AccessTokenScopeWriteMisc AccessTokenScope = "write:misc"
|
||||||
|
|
||||||
|
AccessTokenScopeReadNotification AccessTokenScope = "read:notification"
|
||||||
|
AccessTokenScopeWriteNotification AccessTokenScope = "write:notification"
|
||||||
|
|
||||||
|
AccessTokenScopeReadOrganization AccessTokenScope = "read:organization"
|
||||||
|
AccessTokenScopeWriteOrganization AccessTokenScope = "write:organization"
|
||||||
|
|
||||||
|
AccessTokenScopeReadPackage AccessTokenScope = "read:package"
|
||||||
|
AccessTokenScopeWritePackage AccessTokenScope = "write:package"
|
||||||
|
|
||||||
|
AccessTokenScopeReadIssue AccessTokenScope = "read:issue"
|
||||||
|
AccessTokenScopeWriteIssue AccessTokenScope = "write:issue"
|
||||||
|
|
||||||
|
AccessTokenScopeReadRepository AccessTokenScope = "read:repository"
|
||||||
|
AccessTokenScopeWriteRepository AccessTokenScope = "write:repository"
|
||||||
|
|
||||||
|
AccessTokenScopeReadUser AccessTokenScope = "read:user"
|
||||||
|
AccessTokenScopeWriteUser AccessTokenScope = "write:user"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
accessTokenScopeAllBits accessTokenScopeBitmap = accessTokenScopeWriteActivityPubBits |
|
||||||
|
accessTokenScopeWriteAdminBits | accessTokenScopeWriteMiscBits | accessTokenScopeWriteNotificationBits |
|
||||||
|
accessTokenScopeWriteOrganizationBits | accessTokenScopeWritePackageBits | accessTokenScopeWriteIssueBits |
|
||||||
|
accessTokenScopeWriteRepositoryBits | accessTokenScopeWriteUserBits
|
||||||
|
|
||||||
|
accessTokenScopePublicOnlyBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
|
||||||
|
accessTokenScopeReadActivityPubBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteActivityPubBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadActivityPubBits
|
||||||
|
|
||||||
|
accessTokenScopeReadAdminBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteAdminBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadAdminBits
|
||||||
|
|
||||||
|
accessTokenScopeReadMiscBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteMiscBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadMiscBits
|
||||||
|
|
||||||
|
accessTokenScopeReadNotificationBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteNotificationBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadNotificationBits
|
||||||
|
|
||||||
|
accessTokenScopeReadOrganizationBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteOrganizationBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadOrganizationBits
|
||||||
|
|
||||||
|
accessTokenScopeReadPackageBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWritePackageBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadPackageBits
|
||||||
|
|
||||||
|
accessTokenScopeReadIssueBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteIssueBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadIssueBits
|
||||||
|
|
||||||
|
accessTokenScopeReadRepositoryBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteRepositoryBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadRepositoryBits
|
||||||
|
|
||||||
|
accessTokenScopeReadUserBits accessTokenScopeBitmap = 1 << iota
|
||||||
|
accessTokenScopeWriteUserBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadUserBits
|
||||||
|
|
||||||
|
// 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 precede child scopes.
|
||||||
|
var allAccessTokenScopes = []AccessTokenScope{
|
||||||
|
AccessTokenScopePublicOnly,
|
||||||
|
AccessTokenScopeWriteActivityPub, AccessTokenScopeReadActivityPub,
|
||||||
|
AccessTokenScopeWriteAdmin, AccessTokenScopeReadAdmin,
|
||||||
|
AccessTokenScopeWriteMisc, AccessTokenScopeReadMisc,
|
||||||
|
AccessTokenScopeWriteNotification, AccessTokenScopeReadNotification,
|
||||||
|
AccessTokenScopeWriteOrganization, AccessTokenScopeReadOrganization,
|
||||||
|
AccessTokenScopeWritePackage, AccessTokenScopeReadPackage,
|
||||||
|
AccessTokenScopeWriteIssue, AccessTokenScopeReadIssue,
|
||||||
|
AccessTokenScopeWriteRepository, AccessTokenScopeReadRepository,
|
||||||
|
AccessTokenScopeWriteUser, AccessTokenScopeReadUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
// allAccessTokenScopeBits contains all access token scopes.
|
||||||
|
var allAccessTokenScopeBits = map[AccessTokenScope]accessTokenScopeBitmap{
|
||||||
|
AccessTokenScopeAll: accessTokenScopeAllBits,
|
||||||
|
AccessTokenScopePublicOnly: accessTokenScopePublicOnlyBits,
|
||||||
|
AccessTokenScopeReadActivityPub: accessTokenScopeReadActivityPubBits,
|
||||||
|
AccessTokenScopeWriteActivityPub: accessTokenScopeWriteActivityPubBits,
|
||||||
|
AccessTokenScopeReadAdmin: accessTokenScopeReadAdminBits,
|
||||||
|
AccessTokenScopeWriteAdmin: accessTokenScopeWriteAdminBits,
|
||||||
|
AccessTokenScopeReadMisc: accessTokenScopeReadMiscBits,
|
||||||
|
AccessTokenScopeWriteMisc: accessTokenScopeWriteMiscBits,
|
||||||
|
AccessTokenScopeReadNotification: accessTokenScopeReadNotificationBits,
|
||||||
|
AccessTokenScopeWriteNotification: accessTokenScopeWriteNotificationBits,
|
||||||
|
AccessTokenScopeReadOrganization: accessTokenScopeReadOrganizationBits,
|
||||||
|
AccessTokenScopeWriteOrganization: accessTokenScopeWriteOrganizationBits,
|
||||||
|
AccessTokenScopeReadPackage: accessTokenScopeReadPackageBits,
|
||||||
|
AccessTokenScopeWritePackage: accessTokenScopeWritePackageBits,
|
||||||
|
AccessTokenScopeReadIssue: accessTokenScopeReadIssueBits,
|
||||||
|
AccessTokenScopeWriteIssue: accessTokenScopeWriteIssueBits,
|
||||||
|
AccessTokenScopeReadRepository: accessTokenScopeReadRepositoryBits,
|
||||||
|
AccessTokenScopeWriteRepository: accessTokenScopeWriteRepositoryBits,
|
||||||
|
AccessTokenScopeReadUser: accessTokenScopeReadUserBits,
|
||||||
|
AccessTokenScopeWriteUser: accessTokenScopeWriteUserBits,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(unknownScopes *[]unknownAccessTokenScope) AccessTokenScope {
|
||||||
|
var scopes []string
|
||||||
|
|
||||||
|
// Preserve unknown scopes, and put them at the beginning so that it's clear
|
||||||
|
// when debugging.
|
||||||
|
if unknownScopes != nil {
|
||||||
|
for _, unknownScope := range *unknownScopes {
|
||||||
|
scopes = append(scopes, string(unknownScope))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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),
|
||||||
|
"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user",
|
||||||
|
"all",
|
||||||
|
))
|
||||||
|
return scope
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the scope string into a bitmap, thus removing possible duplicates.
|
||||||
|
func (s AccessTokenScope) parse() (accessTokenScopeBitmap, *[]unknownAccessTokenScope) {
|
||||||
|
var bitmap accessTokenScopeBitmap
|
||||||
|
var unknownScopes []unknownAccessTokenScope
|
||||||
|
|
||||||
|
// The following is the more performant equivalent of 'for _, v := range strings.Split(remainingScope, ",")' as this is hot code
|
||||||
|
remainingScopes := string(s)
|
||||||
|
for len(remainingScopes) > 0 {
|
||||||
|
i := strings.IndexByte(remainingScopes, ',')
|
||||||
|
var v string
|
||||||
|
if i < 0 {
|
||||||
|
v = remainingScopes
|
||||||
|
remainingScopes = ""
|
||||||
|
} else if i+1 >= len(remainingScopes) {
|
||||||
|
v = remainingScopes[:i]
|
||||||
|
remainingScopes = ""
|
||||||
|
} else {
|
||||||
|
v = remainingScopes[:i]
|
||||||
|
remainingScopes = remainingScopes[i+1:]
|
||||||
|
}
|
||||||
|
singleScope := AccessTokenScope(v)
|
||||||
|
if singleScope == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if singleScope == AccessTokenScopeAll {
|
||||||
|
bitmap |= accessTokenScopeAllBits
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bits, ok := allAccessTokenScopeBits[singleScope]
|
||||||
|
if !ok {
|
||||||
|
unknownScopes = append(unknownScopes, unknownAccessTokenScope(string(singleScope)))
|
||||||
|
}
|
||||||
|
bitmap |= bits
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmap, &unknownScopes
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalizePreservingUnknown returns a normalized scope string without any
|
||||||
|
// duplicates. Unknown scopes are included.
|
||||||
|
func (s AccessTokenScope) NormalizePreservingUnknown() AccessTokenScope {
|
||||||
|
bitmap, unknownScopes := s.parse()
|
||||||
|
|
||||||
|
return bitmap.toScope(unknownScopes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OldAccessTokenScope represents the scope for an access token.
|
||||||
|
type OldAccessTokenScope string
|
||||||
|
|
||||||
|
const (
|
||||||
|
OldAccessTokenScopeAll OldAccessTokenScope = "all"
|
||||||
|
|
||||||
|
OldAccessTokenScopeRepo OldAccessTokenScope = "repo"
|
||||||
|
OldAccessTokenScopeRepoStatus OldAccessTokenScope = "repo:status"
|
||||||
|
OldAccessTokenScopePublicRepo OldAccessTokenScope = "public_repo"
|
||||||
|
|
||||||
|
OldAccessTokenScopeAdminOrg OldAccessTokenScope = "admin:org"
|
||||||
|
OldAccessTokenScopeWriteOrg OldAccessTokenScope = "write:org"
|
||||||
|
OldAccessTokenScopeReadOrg OldAccessTokenScope = "read:org"
|
||||||
|
|
||||||
|
OldAccessTokenScopeAdminPublicKey OldAccessTokenScope = "admin:public_key"
|
||||||
|
OldAccessTokenScopeWritePublicKey OldAccessTokenScope = "write:public_key"
|
||||||
|
OldAccessTokenScopeReadPublicKey OldAccessTokenScope = "read:public_key"
|
||||||
|
|
||||||
|
OldAccessTokenScopeAdminRepoHook OldAccessTokenScope = "admin:repo_hook"
|
||||||
|
OldAccessTokenScopeWriteRepoHook OldAccessTokenScope = "write:repo_hook"
|
||||||
|
OldAccessTokenScopeReadRepoHook OldAccessTokenScope = "read:repo_hook"
|
||||||
|
|
||||||
|
OldAccessTokenScopeAdminOrgHook OldAccessTokenScope = "admin:org_hook"
|
||||||
|
|
||||||
|
OldAccessTokenScopeNotification OldAccessTokenScope = "notification"
|
||||||
|
|
||||||
|
OldAccessTokenScopeUser OldAccessTokenScope = "user"
|
||||||
|
OldAccessTokenScopeReadUser OldAccessTokenScope = "read:user"
|
||||||
|
OldAccessTokenScopeUserEmail OldAccessTokenScope = "user:email"
|
||||||
|
OldAccessTokenScopeUserFollow OldAccessTokenScope = "user:follow"
|
||||||
|
|
||||||
|
OldAccessTokenScopeDeleteRepo OldAccessTokenScope = "delete_repo"
|
||||||
|
|
||||||
|
OldAccessTokenScopePackage OldAccessTokenScope = "package"
|
||||||
|
OldAccessTokenScopeWritePackage OldAccessTokenScope = "write:package"
|
||||||
|
OldAccessTokenScopeReadPackage OldAccessTokenScope = "read:package"
|
||||||
|
OldAccessTokenScopeDeletePackage OldAccessTokenScope = "delete:package"
|
||||||
|
|
||||||
|
OldAccessTokenScopeAdminGPGKey OldAccessTokenScope = "admin:gpg_key"
|
||||||
|
OldAccessTokenScopeWriteGPGKey OldAccessTokenScope = "write:gpg_key"
|
||||||
|
OldAccessTokenScopeReadGPGKey OldAccessTokenScope = "read:gpg_key"
|
||||||
|
|
||||||
|
OldAccessTokenScopeAdminApplication OldAccessTokenScope = "admin:application"
|
||||||
|
OldAccessTokenScopeWriteApplication OldAccessTokenScope = "write:application"
|
||||||
|
OldAccessTokenScopeReadApplication OldAccessTokenScope = "read:application"
|
||||||
|
|
||||||
|
OldAccessTokenScopeSudo OldAccessTokenScope = "sudo"
|
||||||
|
)
|
||||||
|
|
||||||
|
var accessTokenScopeMap = map[OldAccessTokenScope][]AccessTokenScope{
|
||||||
|
OldAccessTokenScopeAll: {AccessTokenScopeAll},
|
||||||
|
OldAccessTokenScopeRepo: {AccessTokenScopeWriteRepository},
|
||||||
|
OldAccessTokenScopeRepoStatus: {AccessTokenScopeWriteRepository},
|
||||||
|
OldAccessTokenScopePublicRepo: {AccessTokenScopePublicOnly, AccessTokenScopeWriteRepository},
|
||||||
|
OldAccessTokenScopeAdminOrg: {AccessTokenScopeWriteOrganization},
|
||||||
|
OldAccessTokenScopeWriteOrg: {AccessTokenScopeWriteOrganization},
|
||||||
|
OldAccessTokenScopeReadOrg: {AccessTokenScopeReadOrganization},
|
||||||
|
OldAccessTokenScopeAdminPublicKey: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeWritePublicKey: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeReadPublicKey: {AccessTokenScopeReadUser},
|
||||||
|
OldAccessTokenScopeAdminRepoHook: {AccessTokenScopeWriteRepository},
|
||||||
|
OldAccessTokenScopeWriteRepoHook: {AccessTokenScopeWriteRepository},
|
||||||
|
OldAccessTokenScopeReadRepoHook: {AccessTokenScopeReadRepository},
|
||||||
|
OldAccessTokenScopeAdminOrgHook: {AccessTokenScopeWriteOrganization},
|
||||||
|
OldAccessTokenScopeNotification: {AccessTokenScopeWriteNotification},
|
||||||
|
OldAccessTokenScopeUser: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeReadUser: {AccessTokenScopeReadUser},
|
||||||
|
OldAccessTokenScopeUserEmail: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeUserFollow: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeDeleteRepo: {AccessTokenScopeWriteRepository},
|
||||||
|
OldAccessTokenScopePackage: {AccessTokenScopeWritePackage},
|
||||||
|
OldAccessTokenScopeWritePackage: {AccessTokenScopeWritePackage},
|
||||||
|
OldAccessTokenScopeReadPackage: {AccessTokenScopeReadPackage},
|
||||||
|
OldAccessTokenScopeDeletePackage: {AccessTokenScopeWritePackage},
|
||||||
|
OldAccessTokenScopeAdminGPGKey: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeWriteGPGKey: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeReadGPGKey: {AccessTokenScopeReadUser},
|
||||||
|
OldAccessTokenScopeAdminApplication: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeWriteApplication: {AccessTokenScopeWriteUser},
|
||||||
|
OldAccessTokenScopeReadApplication: {AccessTokenScopeReadUser},
|
||||||
|
OldAccessTokenScopeSudo: {AccessTokenScopeWriteAdmin},
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccessToken struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
Scope string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertScopedAccessTokens(x *xorm.Engine) error {
|
||||||
|
var tokens []*AccessToken
|
||||||
|
|
||||||
|
if err := x.Find(&tokens); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, token := range tokens {
|
||||||
|
var scopes []string
|
||||||
|
allNewScopesMap := make(map[AccessTokenScope]bool)
|
||||||
|
for _, oldScope := range strings.Split(token.Scope, ",") {
|
||||||
|
if newScopes, exists := accessTokenScopeMap[OldAccessTokenScope(oldScope)]; exists {
|
||||||
|
for _, newScope := range newScopes {
|
||||||
|
allNewScopesMap[newScope] = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Debug("access token scope not recognized as old token scope %s; preserving it", oldScope)
|
||||||
|
scopes = append(scopes, oldScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for s := range allNewScopesMap {
|
||||||
|
scopes = append(scopes, string(s))
|
||||||
|
}
|
||||||
|
scope := AccessTokenScope(strings.Join(scopes, ","))
|
||||||
|
|
||||||
|
// normalize the scope
|
||||||
|
normScope := scope.NormalizePreservingUnknown()
|
||||||
|
|
||||||
|
token.Scope = string(normScope)
|
||||||
|
|
||||||
|
// update the db entry with the new scope
|
||||||
|
if _, err := x.Cols("scope").ID(token.ID).Update(token); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
110
models/migrations/v1_20/v259_test.go
Normal file
110
models/migrations/v1_20/v259_test.go
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package v1_20 //nolint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/migrations/base"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type testCase struct {
|
||||||
|
Old OldAccessTokenScope
|
||||||
|
New AccessTokenScope
|
||||||
|
}
|
||||||
|
|
||||||
|
func createOldTokenScope(scopes ...OldAccessTokenScope) OldAccessTokenScope {
|
||||||
|
s := make([]string, 0, len(scopes))
|
||||||
|
for _, os := range scopes {
|
||||||
|
s = append(s, string(os))
|
||||||
|
}
|
||||||
|
return OldAccessTokenScope(strings.Join(s, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNewTokenScope(scopes ...AccessTokenScope) AccessTokenScope {
|
||||||
|
s := make([]string, 0, len(scopes))
|
||||||
|
for _, os := range scopes {
|
||||||
|
s = append(s, string(os))
|
||||||
|
}
|
||||||
|
return AccessTokenScope(strings.Join(s, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_ConvertScopedAccessTokens(t *testing.T) {
|
||||||
|
tests := []testCase{
|
||||||
|
{
|
||||||
|
createOldTokenScope(OldAccessTokenScopeRepo, OldAccessTokenScopeUserFollow),
|
||||||
|
createNewTokenScope(AccessTokenScopeWriteRepository, AccessTokenScopeWriteUser),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
createOldTokenScope(OldAccessTokenScopeUser, OldAccessTokenScopeWritePackage, OldAccessTokenScopeSudo),
|
||||||
|
createNewTokenScope(AccessTokenScopeWriteAdmin, AccessTokenScopeWritePackage, AccessTokenScopeWriteUser),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
createOldTokenScope(),
|
||||||
|
createNewTokenScope(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
createOldTokenScope(OldAccessTokenScopeReadGPGKey, OldAccessTokenScopeReadOrg, OldAccessTokenScopeAll),
|
||||||
|
createNewTokenScope(AccessTokenScopeAll),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
createOldTokenScope(OldAccessTokenScopeReadGPGKey, "invalid"),
|
||||||
|
createNewTokenScope("invalid", AccessTokenScopeReadUser),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a test for each individual mapping
|
||||||
|
for oldScope, newScope := range accessTokenScopeMap {
|
||||||
|
tests = append(tests, testCase{
|
||||||
|
oldScope,
|
||||||
|
createNewTokenScope(newScope...),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
x, deferable := base.PrepareTestEnv(t, 0, new(AccessToken))
|
||||||
|
defer deferable()
|
||||||
|
if x == nil || t.Failed() {
|
||||||
|
t.Skip()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify that no fixtures were loaded
|
||||||
|
count, err := x.Count(&AccessToken{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, int64(0), count)
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
_, err = x.Insert(&AccessToken{
|
||||||
|
Scope: string(tc.Old),
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// migrate the scopes
|
||||||
|
err = ConvertScopedAccessTokens(x)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// migrate the scopes again (migration should be idempotent)
|
||||||
|
err = ConvertScopedAccessTokens(x)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
tokens := make([]AccessToken, 0)
|
||||||
|
err = x.Find(&tokens)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(tests), len(tokens))
|
||||||
|
|
||||||
|
// sort the tokens (insertion order by auto-incrementing primary key)
|
||||||
|
sort.Slice(tokens, func(i, j int) bool {
|
||||||
|
return tokens[i].ID < tokens[j].ID
|
||||||
|
})
|
||||||
|
|
||||||
|
// verify that the converted scopes are equal to the expected test result
|
||||||
|
for idx, newToken := range tokens {
|
||||||
|
assert.Equal(t, string(tests[idx].New), newToken.Scope)
|
||||||
|
}
|
||||||
|
}
|
|
@ -111,28 +111,36 @@ func RequireRepoReaderOr(unitTypes ...unit.Type) func(ctx *Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequireRepoScopedToken check whether personal access token has repo scope
|
// CheckRepoScopedToken check whether personal access token has repo scope
|
||||||
func CheckRepoScopedToken(ctx *Context, repo *repo_model.Repository) {
|
func CheckRepoScopedToken(ctx *Context, repo *repo_model.Repository, level auth_model.AccessTokenScopeLevel) {
|
||||||
if !ctx.IsBasicAuth || ctx.Data["IsApiToken"] != true {
|
if !ctx.IsBasicAuth || ctx.Data["IsApiToken"] != true {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
|
scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
|
||||||
if ok { // it's a personal access token but not oauth2 token
|
if ok { // it's a personal access token but not oauth2 token
|
||||||
var scopeMatched bool
|
var scopeMatched bool
|
||||||
scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopeRepo)
|
|
||||||
|
requiredScopes := auth_model.GetRequiredScopes(level, auth_model.AccessTokenScopeCategoryRepository)
|
||||||
|
|
||||||
|
// check if scope only applies to public resources
|
||||||
|
publicOnly, err := scope.PublicOnly()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("HasScope", err)
|
ctx.ServerError("HasScope", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !scopeMatched && !repo.IsPrivate {
|
|
||||||
scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopePublicRepo)
|
if publicOnly && repo.IsPrivate {
|
||||||
if err != nil {
|
ctx.Error(http.StatusForbidden)
|
||||||
ctx.ServerError("HasScope", err)
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scopeMatched, err = scope.HasScope(requiredScopes...)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("HasScope", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !scopeMatched {
|
if !scopeMatched {
|
||||||
ctx.Error(http.StatusForbidden)
|
ctx.Error(http.StatusForbidden)
|
||||||
return
|
return
|
||||||
|
|
|
@ -796,7 +796,6 @@ unbind_success = The social account has been unlinked from your Gitea account.
|
||||||
manage_access_token = Manage Access Tokens
|
manage_access_token = Manage Access Tokens
|
||||||
generate_new_token = Generate New Token
|
generate_new_token = Generate New Token
|
||||||
tokens_desc = These tokens grant access to your account using the Gitea API.
|
tokens_desc = These tokens grant access to your account using the Gitea API.
|
||||||
new_token_desc = Applications using a token have full access to your account.
|
|
||||||
token_name = Token Name
|
token_name = Token Name
|
||||||
generate_token = Generate Token
|
generate_token = Generate Token
|
||||||
generate_token_success = Your new token has been generated. Copy it now as it will not be shown again.
|
generate_token_success = Your new token has been generated. Copy it now as it will not be shown again.
|
||||||
|
@ -807,8 +806,13 @@ access_token_deletion_cancel_action = Cancel
|
||||||
access_token_deletion_confirm_action = Delete
|
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?
|
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.
|
delete_token_success = The token has been deleted. Applications using it no longer have access to your account.
|
||||||
select_scopes = Select scopes
|
repo_and_org_access = Repository and Organization Access
|
||||||
scopes_list = Scopes:
|
permissions_public_only = Public only
|
||||||
|
permissions_access_all = All (public, private, and limited)
|
||||||
|
select_permissions = Select permissions
|
||||||
|
scoped_token_desc = Selected token scopes limit authentication only to the corresponding <a %s>API</a> routes. Read the <a %s>documentation</a> for more information.
|
||||||
|
at_least_one_permission = You must select at least one permission to create a token
|
||||||
|
permissions_list = Permissions:
|
||||||
|
|
||||||
manage_oauth2_applications = Manage OAuth2 Applications
|
manage_oauth2_applications = Manage OAuth2 Applications
|
||||||
edit_oauth2_application = Edit OAuth2 Application
|
edit_oauth2_application = Edit OAuth2 Application
|
||||||
|
|
|
@ -236,44 +236,85 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.APIContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if a token is being used for auth, we check that it contains the required scope
|
||||||
|
// if a token is not being used, reqToken will enforce other sign in methods
|
||||||
|
func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeCategory) func(ctx *context.APIContext) {
|
||||||
|
return func(ctx *context.APIContext) {
|
||||||
|
// no scope required
|
||||||
|
if len(requiredScopeCategories) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need OAuth2 token to be present.
|
||||||
|
scope, scopeExists := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
|
||||||
|
if ctx.Data["IsApiToken"] != true || !scopeExists {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Data["ApiTokenScopePublicRepoOnly"] = false
|
||||||
|
ctx.Data["ApiTokenScopePublicOrgOnly"] = false
|
||||||
|
|
||||||
|
// use the http method to determine the access level
|
||||||
|
requiredScopeLevel := auth_model.Read
|
||||||
|
if ctx.Req.Method == "POST" || ctx.Req.Method == "PUT" || ctx.Req.Method == "PATCH" || ctx.Req.Method == "DELETE" {
|
||||||
|
requiredScopeLevel = auth_model.Write
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the required scope for the given access level and category
|
||||||
|
requiredScopes := auth_model.GetRequiredScopes(requiredScopeLevel, requiredScopeCategories...)
|
||||||
|
|
||||||
|
// check if scope only applies to public resources
|
||||||
|
publicOnly, err := scope.PublicOnly()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "parsing public resource scope failed: "+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// this context is used by the middleware in the specific route
|
||||||
|
ctx.Data["ApiTokenScopePublicRepoOnly"] = publicOnly && auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryRepository)
|
||||||
|
ctx.Data["ApiTokenScopePublicOrgOnly"] = publicOnly && auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryOrganization)
|
||||||
|
|
||||||
|
allow, err := scope.HasScope(requiredScopes...)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "checking scope failed: "+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if allow {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Error(http.StatusForbidden, "tokenRequiresScope", fmt.Sprintf("token does not have at least one of required scope(s): %v", requiredScopes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Contexter middleware already checks token for user sign in process.
|
// Contexter middleware already checks token for user sign in process.
|
||||||
func reqToken(requiredScope auth_model.AccessTokenScope) func(ctx *context.APIContext) {
|
func reqToken() func(ctx *context.APIContext) {
|
||||||
return func(ctx *context.APIContext) {
|
return func(ctx *context.APIContext) {
|
||||||
// If actions token is present
|
// If actions token is present
|
||||||
if true == ctx.Data["IsActionsToken"] {
|
if true == ctx.Data["IsActionsToken"] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If OAuth2 token is present
|
if true == ctx.Data["IsApiToken"] {
|
||||||
if _, ok := ctx.Data["ApiTokenScope"]; ctx.Data["IsApiToken"] == true && ok {
|
publicRepo, pubRepoExists := ctx.Data["ApiTokenScopePublicRepoOnly"]
|
||||||
// no scope required
|
publicOrg, pubOrgExists := ctx.Data["ApiTokenScopePublicOrgOnly"]
|
||||||
if requiredScope == "" {
|
|
||||||
|
if pubRepoExists && publicRepo.(bool) &&
|
||||||
|
ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
|
||||||
|
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public repos")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check scope
|
if pubOrgExists && publicOrg.(bool) &&
|
||||||
scope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
|
ctx.Org.Organization != nil && ctx.Org.Organization.Visibility != api.VisibleTypePublic {
|
||||||
allow, err := scope.HasScope(requiredScope)
|
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public orgs")
|
||||||
if err != nil {
|
|
||||||
ctx.Error(http.StatusForbidden, "reqToken", "parsing token failed: "+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if allow {
|
|
||||||
return
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsBasicAuth {
|
if ctx.IsBasicAuth {
|
||||||
ctx.CheckForOTP()
|
ctx.CheckForOTP()
|
||||||
return
|
return
|
||||||
|
@ -700,7 +741,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
ctx.Redirect(setting.AppSubURL + "/api/swagger")
|
ctx.Redirect(setting.AppSubURL + "/api/swagger")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
m.Get("/version", misc.Version)
|
|
||||||
if setting.Federation.Enabled {
|
if setting.Federation.Enabled {
|
||||||
m.Get("/nodeinfo", misc.NodeInfo)
|
m.Get("/nodeinfo", misc.NodeInfo)
|
||||||
m.Group("/activitypub", func() {
|
m.Group("/activitypub", func() {
|
||||||
|
@ -713,37 +754,43 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
m.Get("", activitypub.Person)
|
m.Get("", activitypub.Person)
|
||||||
m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.PersonInbox)
|
m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.PersonInbox)
|
||||||
}, context_service.UserIDAssignmentAPI())
|
}, context_service.UserIDAssignmentAPI())
|
||||||
})
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryActivityPub))
|
||||||
}
|
}
|
||||||
m.Get("/signing-key.gpg", misc.SigningKey)
|
|
||||||
m.Post("/markup", bind(api.MarkupOption{}), misc.Markup)
|
|
||||||
m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown)
|
|
||||||
m.Post("/markdown/raw", misc.MarkdownRaw)
|
|
||||||
m.Get("/gitignore/templates", misc.ListGitignoresTemplates)
|
|
||||||
m.Get("/gitignore/templates/{name}", misc.GetGitignoreTemplateInfo)
|
|
||||||
m.Get("/licenses", misc.ListLicenseTemplates)
|
|
||||||
m.Get("/licenses/{name}", misc.GetLicenseTemplateInfo)
|
|
||||||
m.Get("/label/templates", misc.ListLabelTemplates)
|
|
||||||
m.Get("/label/templates/{name}", misc.GetLabelTemplate)
|
|
||||||
m.Group("/settings", func() {
|
|
||||||
m.Get("/ui", settings.GetGeneralUISettings)
|
|
||||||
m.Get("/api", settings.GetGeneralAPISettings)
|
|
||||||
m.Get("/attachment", settings.GetGeneralAttachmentSettings)
|
|
||||||
m.Get("/repository", settings.GetGeneralRepoSettings)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Notifications (requires 'notification' scope)
|
// Misc (requires 'misc' scope)
|
||||||
|
m.Group("", func() {
|
||||||
|
m.Get("/version", misc.Version)
|
||||||
|
m.Get("/signing-key.gpg", misc.SigningKey)
|
||||||
|
m.Post("/markup", reqToken(), bind(api.MarkupOption{}), misc.Markup)
|
||||||
|
m.Post("/markdown", reqToken(), bind(api.MarkdownOption{}), misc.Markdown)
|
||||||
|
m.Post("/markdown/raw", reqToken(), misc.MarkdownRaw)
|
||||||
|
m.Get("/gitignore/templates", misc.ListGitignoresTemplates)
|
||||||
|
m.Get("/gitignore/templates/{name}", misc.GetGitignoreTemplateInfo)
|
||||||
|
m.Get("/licenses", misc.ListLicenseTemplates)
|
||||||
|
m.Get("/licenses/{name}", misc.GetLicenseTemplateInfo)
|
||||||
|
m.Get("/label/templates", misc.ListLabelTemplates)
|
||||||
|
m.Get("/label/templates/{name}", misc.GetLabelTemplate)
|
||||||
|
|
||||||
|
m.Group("/settings", func() {
|
||||||
|
m.Get("/ui", settings.GetGeneralUISettings)
|
||||||
|
m.Get("/api", settings.GetGeneralAPISettings)
|
||||||
|
m.Get("/attachment", settings.GetGeneralAttachmentSettings)
|
||||||
|
m.Get("/repository", settings.GetGeneralRepoSettings)
|
||||||
|
})
|
||||||
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryMisc))
|
||||||
|
|
||||||
|
// Notifications (requires 'notifications' scope)
|
||||||
m.Group("/notifications", func() {
|
m.Group("/notifications", func() {
|
||||||
m.Combo("").
|
m.Combo("").
|
||||||
Get(notify.ListNotifications).
|
Get(notify.ListNotifications).
|
||||||
Put(notify.ReadNotifications)
|
Put(notify.ReadNotifications, reqToken())
|
||||||
m.Get("/new", notify.NewAvailable)
|
m.Get("/new", notify.NewAvailable)
|
||||||
m.Combo("/threads/{id}").
|
m.Combo("/threads/{id}").
|
||||||
Get(notify.GetThread).
|
Get(notify.GetThread).
|
||||||
Patch(notify.ReadThread)
|
Patch(notify.ReadThread, reqToken())
|
||||||
}, reqToken(auth_model.AccessTokenScopeNotification))
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryNotification))
|
||||||
|
|
||||||
// Users (no scope required)
|
// Users (requires user scope)
|
||||||
m.Group("/users", func() {
|
m.Group("/users", func() {
|
||||||
m.Get("/search", reqExploreSignIn(), user.Search)
|
m.Get("/search", reqExploreSignIn(), user.Search)
|
||||||
|
|
||||||
|
@ -754,18 +801,18 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
m.Get("/heatmap", user.GetUserHeatmapData)
|
m.Get("/heatmap", user.GetUserHeatmapData)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Get("/repos", reqExploreSignIn(), user.ListUserRepos)
|
m.Get("/repos", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository), reqExploreSignIn(), user.ListUserRepos)
|
||||||
m.Group("/tokens", func() {
|
m.Group("/tokens", func() {
|
||||||
m.Combo("").Get(user.ListAccessTokens).
|
m.Combo("").Get(user.ListAccessTokens).
|
||||||
Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
|
Post(bind(api.CreateAccessTokenOption{}), reqToken(), user.CreateAccessToken)
|
||||||
m.Combo("/{id}").Delete(user.DeleteAccessToken)
|
m.Combo("/{id}").Delete(reqToken(), user.DeleteAccessToken)
|
||||||
}, reqBasicAuth())
|
}, reqBasicAuth())
|
||||||
|
|
||||||
m.Get("/activities/feeds", user.ListUserActivityFeeds)
|
m.Get("/activities/feeds", user.ListUserActivityFeeds)
|
||||||
}, context_service.UserAssignmentAPI())
|
}, context_service.UserAssignmentAPI())
|
||||||
})
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser))
|
||||||
|
|
||||||
// (no scope required)
|
// Users (requires user scope)
|
||||||
m.Group("/users", func() {
|
m.Group("/users", func() {
|
||||||
m.Group("/{username}", func() {
|
m.Group("/{username}", func() {
|
||||||
m.Get("/keys", user.ListPublicKeys)
|
m.Get("/keys", user.ListPublicKeys)
|
||||||
|
@ -781,59 +828,61 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
|
|
||||||
m.Get("/subscriptions", user.GetWatchedRepos)
|
m.Get("/subscriptions", user.GetWatchedRepos)
|
||||||
}, context_service.UserAssignmentAPI())
|
}, context_service.UserAssignmentAPI())
|
||||||
}, reqToken(""))
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
|
||||||
|
|
||||||
|
// Users (requires user scope)
|
||||||
m.Group("/user", func() {
|
m.Group("/user", func() {
|
||||||
m.Get("", user.GetAuthenticatedUser)
|
m.Get("", user.GetAuthenticatedUser)
|
||||||
m.Group("/settings", func() {
|
m.Group("/settings", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadUser), user.GetUserSettings)
|
m.Get("", user.GetUserSettings)
|
||||||
m.Patch("", reqToken(auth_model.AccessTokenScopeUser), bind(api.UserSettingsOptions{}), user.UpdateUserSettings)
|
m.Patch("", bind(api.UserSettingsOptions{}), user.UpdateUserSettings)
|
||||||
})
|
}, reqToken())
|
||||||
m.Combo("/emails").Get(reqToken(auth_model.AccessTokenScopeReadUser), user.ListEmails).
|
m.Combo("/emails").
|
||||||
Post(reqToken(auth_model.AccessTokenScopeUser), bind(api.CreateEmailOption{}), user.AddEmail).
|
Get(user.ListEmails).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeUser), bind(api.DeleteEmailOption{}), user.DeleteEmail)
|
Post(bind(api.CreateEmailOption{}), user.AddEmail).
|
||||||
|
Delete(bind(api.DeleteEmailOption{}), user.DeleteEmail)
|
||||||
|
|
||||||
m.Get("/followers", user.ListMyFollowers)
|
m.Get("/followers", user.ListMyFollowers)
|
||||||
m.Group("/following", func() {
|
m.Group("/following", func() {
|
||||||
m.Get("", user.ListMyFollowing)
|
m.Get("", user.ListMyFollowing)
|
||||||
m.Group("/{username}", func() {
|
m.Group("/{username}", func() {
|
||||||
m.Get("", user.CheckMyFollowing)
|
m.Get("", user.CheckMyFollowing)
|
||||||
m.Put("", reqToken(auth_model.AccessTokenScopeUserFollow), user.Follow) // requires 'user:follow' scope
|
m.Put("", user.Follow)
|
||||||
m.Delete("", reqToken(auth_model.AccessTokenScopeUserFollow), user.Unfollow) // requires 'user:follow' scope
|
m.Delete("", user.Unfollow)
|
||||||
}, context_service.UserAssignmentAPI())
|
}, context_service.UserAssignmentAPI())
|
||||||
})
|
})
|
||||||
|
|
||||||
// (admin:public_key scope)
|
// (admin:public_key scope)
|
||||||
m.Group("/keys", func() {
|
m.Group("/keys", func() {
|
||||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadPublicKey), user.ListMyPublicKeys).
|
m.Combo("").Get(user.ListMyPublicKeys).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeWritePublicKey), bind(api.CreateKeyOption{}), user.CreatePublicKey)
|
Post(bind(api.CreateKeyOption{}), user.CreatePublicKey)
|
||||||
m.Combo("/{id}").Get(reqToken(auth_model.AccessTokenScopeReadPublicKey), user.GetPublicKey).
|
m.Combo("/{id}").Get(user.GetPublicKey).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWritePublicKey), user.DeletePublicKey)
|
Delete(user.DeletePublicKey)
|
||||||
})
|
})
|
||||||
|
|
||||||
// (admin:application scope)
|
// (admin:application scope)
|
||||||
m.Group("/applications", func() {
|
m.Group("/applications", func() {
|
||||||
m.Combo("/oauth2").
|
m.Combo("/oauth2").
|
||||||
Get(reqToken(auth_model.AccessTokenScopeReadApplication), user.ListOauth2Applications).
|
Get(user.ListOauth2Applications).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeWriteApplication), bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application)
|
Post(bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application)
|
||||||
m.Combo("/oauth2/{id}").
|
m.Combo("/oauth2/{id}").
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteApplication), user.DeleteOauth2Application).
|
Delete(user.DeleteOauth2Application).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeWriteApplication), bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application).
|
Patch(bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application).
|
||||||
Get(reqToken(auth_model.AccessTokenScopeReadApplication), user.GetOauth2Application)
|
Get(user.GetOauth2Application)
|
||||||
})
|
})
|
||||||
|
|
||||||
// (admin:gpg_key scope)
|
// (admin:gpg_key scope)
|
||||||
m.Group("/gpg_keys", func() {
|
m.Group("/gpg_keys", func() {
|
||||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadGPGKey), user.ListMyGPGKeys).
|
m.Combo("").Get(user.ListMyGPGKeys).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeWriteGPGKey), bind(api.CreateGPGKeyOption{}), user.CreateGPGKey)
|
Post(bind(api.CreateGPGKeyOption{}), user.CreateGPGKey)
|
||||||
m.Combo("/{id}").Get(reqToken(auth_model.AccessTokenScopeReadGPGKey), user.GetGPGKey).
|
m.Combo("/{id}").Get(user.GetGPGKey).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteGPGKey), user.DeleteGPGKey)
|
Delete(user.DeleteGPGKey)
|
||||||
})
|
})
|
||||||
m.Get("/gpg_key_token", reqToken(auth_model.AccessTokenScopeReadGPGKey), user.GetVerificationToken)
|
m.Get("/gpg_key_token", user.GetVerificationToken)
|
||||||
m.Post("/gpg_key_verify", reqToken(auth_model.AccessTokenScopeReadGPGKey), bind(api.VerifyGPGKeyOption{}), user.VerifyUserGPGKey)
|
m.Post("/gpg_key_verify", bind(api.VerifyGPGKeyOption{}), user.VerifyUserGPGKey)
|
||||||
|
|
||||||
// (repo scope)
|
// (repo scope)
|
||||||
m.Combo("/repos", reqToken(auth_model.AccessTokenScopeRepo)).Get(user.ListMyRepos).
|
m.Combo("/repos", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)).Get(user.ListMyRepos).
|
||||||
Post(bind(api.CreateRepoOption{}), repo.Create)
|
Post(bind(api.CreateRepoOption{}), repo.Create)
|
||||||
|
|
||||||
// (repo scope)
|
// (repo scope)
|
||||||
|
@ -844,64 +893,65 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
m.Put("", user.Star)
|
m.Put("", user.Star)
|
||||||
m.Delete("", user.Unstar)
|
m.Delete("", user.Unstar)
|
||||||
}, repoAssignment())
|
}, repoAssignment())
|
||||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
|
||||||
m.Get("/times", reqToken(auth_model.AccessTokenScopeRepo), repo.ListMyTrackedTimes)
|
m.Get("/times", repo.ListMyTrackedTimes)
|
||||||
m.Get("/stopwatches", reqToken(auth_model.AccessTokenScopeRepo), repo.GetStopwatches)
|
m.Get("/stopwatches", repo.GetStopwatches)
|
||||||
m.Get("/subscriptions", reqToken(auth_model.AccessTokenScopeRepo), user.GetMyWatchedRepos)
|
m.Get("/subscriptions", user.GetMyWatchedRepos)
|
||||||
m.Get("/teams", reqToken(auth_model.AccessTokenScopeRepo), org.ListUserTeams)
|
m.Get("/teams", org.ListUserTeams)
|
||||||
m.Group("/hooks", func() {
|
m.Group("/hooks", func() {
|
||||||
m.Combo("").Get(user.ListHooks).
|
m.Combo("").Get(user.ListHooks).
|
||||||
Post(bind(api.CreateHookOption{}), user.CreateHook)
|
Post(bind(api.CreateHookOption{}), user.CreateHook)
|
||||||
m.Combo("/{id}").Get(user.GetHook).
|
m.Combo("/{id}").Get(user.GetHook).
|
||||||
Patch(bind(api.EditHookOption{}), user.EditHook).
|
Patch(bind(api.EditHookOption{}), user.EditHook).
|
||||||
Delete(user.DeleteHook)
|
Delete(user.DeleteHook)
|
||||||
}, reqToken(auth_model.AccessTokenScopeAdminUserHook), reqWebhooksEnabled())
|
}, reqWebhooksEnabled())
|
||||||
}, reqToken(""))
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
|
||||||
|
|
||||||
// Repositories
|
// Repositories (requires repo scope, org scope)
|
||||||
m.Post("/org/{org}/repos", reqToken(auth_model.AccessTokenScopeAdminOrg), bind(api.CreateRepoOption{}), repo.CreateOrgRepoDeprecated)
|
m.Post("/org/{org}/repos",
|
||||||
|
tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization, auth_model.AccessTokenScopeCategoryRepository),
|
||||||
|
reqToken(),
|
||||||
|
bind(api.CreateRepoOption{}),
|
||||||
|
repo.CreateOrgRepoDeprecated)
|
||||||
|
|
||||||
m.Combo("/repositories/{id}", reqToken(auth_model.AccessTokenScopeRepo)).Get(repo.GetByID)
|
// requires repo scope
|
||||||
|
m.Combo("/repositories/{id}", reqToken(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)).Get(repo.GetByID)
|
||||||
|
|
||||||
|
// Repos (requires repo scope)
|
||||||
m.Group("/repos", func() {
|
m.Group("/repos", func() {
|
||||||
m.Get("/search", repo.Search)
|
m.Get("/search", repo.Search)
|
||||||
|
|
||||||
m.Get("/issues/search", repo.SearchIssues)
|
|
||||||
|
|
||||||
// (repo scope)
|
// (repo scope)
|
||||||
m.Post("/migrate", reqToken(auth_model.AccessTokenScopeRepo), bind(api.MigrateRepoOptions{}), repo.Migrate)
|
m.Post("/migrate", reqToken(), bind(api.MigrateRepoOptions{}), repo.Migrate)
|
||||||
|
|
||||||
m.Group("/{username}/{reponame}", func() {
|
m.Group("/{username}/{reponame}", func() {
|
||||||
m.Combo("").Get(reqAnyRepoReader(), repo.Get).
|
m.Combo("").Get(reqAnyRepoReader(), repo.Get).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeDeleteRepo), reqOwner(), repo.Delete).
|
Delete(reqToken(), reqOwner(), repo.Delete).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit)
|
Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit)
|
||||||
m.Post("/generate", reqToken(auth_model.AccessTokenScopeRepo), reqRepoReader(unit.TypeCode), bind(api.GenerateRepoOption{}), repo.Generate)
|
m.Post("/generate", reqToken(), reqRepoReader(unit.TypeCode), bind(api.GenerateRepoOption{}), repo.Generate)
|
||||||
m.Group("/transfer", func() {
|
m.Group("/transfer", func() {
|
||||||
m.Post("", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer)
|
m.Post("", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer)
|
||||||
m.Post("/accept", repo.AcceptTransfer)
|
m.Post("/accept", repo.AcceptTransfer)
|
||||||
m.Post("/reject", repo.RejectTransfer)
|
m.Post("/reject", repo.RejectTransfer)
|
||||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
}, reqToken())
|
||||||
m.Combo("/notifications", reqToken(auth_model.AccessTokenScopeNotification)).
|
|
||||||
Get(notify.ListRepoNotifications).
|
|
||||||
Put(notify.ReadRepoNotifications)
|
|
||||||
m.Group("/hooks/git", func() {
|
m.Group("/hooks/git", func() {
|
||||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadRepoHook), repo.ListGitHooks)
|
m.Combo("").Get(repo.ListGitHooks)
|
||||||
m.Group("/{id}", func() {
|
m.Group("/{id}", func() {
|
||||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadRepoHook), repo.GetGitHook).
|
m.Combo("").Get(repo.GetGitHook).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeWriteRepoHook), bind(api.EditGitHookOption{}), repo.EditGitHook).
|
Patch(bind(api.EditGitHookOption{}), repo.EditGitHook).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteRepoHook), repo.DeleteGitHook)
|
Delete(repo.DeleteGitHook)
|
||||||
})
|
})
|
||||||
}, reqAdmin(), reqGitHook(), context.ReferencesGitRepo(true))
|
}, reqToken(), reqAdmin(), reqGitHook(), context.ReferencesGitRepo(true))
|
||||||
m.Group("/hooks", func() {
|
m.Group("/hooks", func() {
|
||||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadRepoHook), repo.ListHooks).
|
m.Combo("").Get(repo.ListHooks).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeWriteRepoHook), bind(api.CreateHookOption{}), repo.CreateHook)
|
Post(bind(api.CreateHookOption{}), repo.CreateHook)
|
||||||
m.Group("/{id}", func() {
|
m.Group("/{id}", func() {
|
||||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadRepoHook), repo.GetHook).
|
m.Combo("").Get(repo.GetHook).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeWriteRepoHook), bind(api.EditHookOption{}), repo.EditHook).
|
Patch(bind(api.EditHookOption{}), repo.EditHook).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteRepoHook), repo.DeleteHook)
|
Delete(repo.DeleteHook)
|
||||||
m.Post("/tests", reqToken(auth_model.AccessTokenScopeReadRepoHook), context.ReferencesGitRepo(), context.RepoRefForAPI, repo.TestHook)
|
m.Post("/tests", context.ReferencesGitRepo(), context.RepoRefForAPI, repo.TestHook)
|
||||||
})
|
})
|
||||||
}, reqAdmin(), reqWebhooksEnabled())
|
}, reqToken(), reqAdmin(), reqWebhooksEnabled())
|
||||||
m.Group("/collaborators", func() {
|
m.Group("/collaborators", func() {
|
||||||
m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
|
m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
|
||||||
m.Group("/{collaborator}", func() {
|
m.Group("/{collaborator}", func() {
|
||||||
|
@ -910,25 +960,25 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
Delete(reqAdmin(), repo.DeleteCollaborator)
|
Delete(reqAdmin(), repo.DeleteCollaborator)
|
||||||
m.Get("/permission", repo.GetRepoPermissions)
|
m.Get("/permission", repo.GetRepoPermissions)
|
||||||
})
|
})
|
||||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
}, reqToken())
|
||||||
m.Get("/assignees", reqToken(auth_model.AccessTokenScopeRepo), reqAnyRepoReader(), repo.GetAssignees)
|
m.Get("/assignees", reqToken(), reqAnyRepoReader(), repo.GetAssignees)
|
||||||
m.Get("/reviewers", reqToken(auth_model.AccessTokenScopeRepo), reqAnyRepoReader(), repo.GetReviewers)
|
m.Get("/reviewers", reqToken(), reqAnyRepoReader(), repo.GetReviewers)
|
||||||
m.Group("/teams", func() {
|
m.Group("/teams", func() {
|
||||||
m.Get("", reqAnyRepoReader(), repo.ListTeams)
|
m.Get("", reqAnyRepoReader(), repo.ListTeams)
|
||||||
m.Combo("/{team}").Get(reqAnyRepoReader(), repo.IsTeam).
|
m.Combo("/{team}").Get(reqAnyRepoReader(), repo.IsTeam).
|
||||||
Put(reqAdmin(), repo.AddTeam).
|
Put(reqAdmin(), repo.AddTeam).
|
||||||
Delete(reqAdmin(), repo.DeleteTeam)
|
Delete(reqAdmin(), repo.DeleteTeam)
|
||||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
}, reqToken())
|
||||||
m.Get("/raw/*", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetRawFile)
|
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("/media/*", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetRawFileOrLFS)
|
||||||
m.Get("/archive/*", reqRepoReader(unit.TypeCode), repo.GetArchive)
|
m.Get("/archive/*", reqRepoReader(unit.TypeCode), repo.GetArchive)
|
||||||
m.Combo("/forks").Get(repo.ListForks).
|
m.Combo("/forks").Get(repo.ListForks).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoReader(unit.TypeCode), bind(api.CreateForkOption{}), repo.CreateFork)
|
Post(reqToken(), reqRepoReader(unit.TypeCode), bind(api.CreateForkOption{}), repo.CreateFork)
|
||||||
m.Group("/branches", func() {
|
m.Group("/branches", func() {
|
||||||
m.Get("", repo.ListBranches)
|
m.Get("", repo.ListBranches)
|
||||||
m.Get("/*", repo.GetBranch)
|
m.Get("/*", repo.GetBranch)
|
||||||
m.Delete("/*", reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeCode), repo.DeleteBranch)
|
m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), repo.DeleteBranch)
|
||||||
m.Post("", reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeCode), bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
|
m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
|
||||||
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
|
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
|
||||||
m.Group("/branch_protections", func() {
|
m.Group("/branch_protections", func() {
|
||||||
m.Get("", repo.ListBranchProtections)
|
m.Get("", repo.ListBranchProtections)
|
||||||
|
@ -938,218 +988,112 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
m.Patch("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection)
|
m.Patch("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection)
|
||||||
m.Delete("", repo.DeleteBranchProtection)
|
m.Delete("", repo.DeleteBranchProtection)
|
||||||
})
|
})
|
||||||
}, reqToken(auth_model.AccessTokenScopeRepo), reqAdmin())
|
}, reqToken(), reqAdmin())
|
||||||
m.Group("/tags", func() {
|
m.Group("/tags", func() {
|
||||||
m.Get("", repo.ListTags)
|
m.Get("", repo.ListTags)
|
||||||
m.Get("/*", repo.GetTag)
|
m.Get("/*", repo.GetTag)
|
||||||
m.Post("", reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeCode), bind(api.CreateTagOption{}), repo.CreateTag)
|
m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), bind(api.CreateTagOption{}), repo.CreateTag)
|
||||||
m.Delete("/*", reqToken(auth_model.AccessTokenScopeRepo), repo.DeleteTag)
|
m.Delete("/*", reqToken(), repo.DeleteTag)
|
||||||
}, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo(true))
|
}, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo(true))
|
||||||
m.Group("/keys", func() {
|
m.Group("/keys", func() {
|
||||||
m.Combo("").Get(repo.ListDeployKeys).
|
m.Combo("").Get(repo.ListDeployKeys).
|
||||||
Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey)
|
Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey)
|
||||||
m.Combo("/{id}").Get(repo.GetDeployKey).
|
m.Combo("/{id}").Get(repo.GetDeployKey).
|
||||||
Delete(repo.DeleteDeploykey)
|
Delete(repo.DeleteDeploykey)
|
||||||
}, reqToken(auth_model.AccessTokenScopeRepo), reqAdmin())
|
}, reqToken(), reqAdmin())
|
||||||
m.Group("/times", func() {
|
m.Group("/times", func() {
|
||||||
m.Combo("").Get(repo.ListTrackedTimesByRepository)
|
m.Combo("").Get(repo.ListTrackedTimesByRepository)
|
||||||
m.Combo("/{timetrackingusername}").Get(repo.ListTrackedTimesByUser)
|
m.Combo("/{timetrackingusername}").Get(repo.ListTrackedTimesByUser)
|
||||||
}, mustEnableIssues, reqToken(auth_model.AccessTokenScopeRepo))
|
}, mustEnableIssues, reqToken())
|
||||||
m.Group("/wiki", func() {
|
m.Group("/wiki", func() {
|
||||||
m.Combo("/page/{pageName}").
|
m.Combo("/page/{pageName}").
|
||||||
Get(repo.GetWikiPage).
|
Get(repo.GetWikiPage).
|
||||||
Patch(mustNotBeArchived, reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeWiki), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage).
|
Patch(mustNotBeArchived, reqToken(), reqRepoWriter(unit.TypeWiki), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage).
|
||||||
Delete(mustNotBeArchived, reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeWiki), repo.DeleteWikiPage)
|
Delete(mustNotBeArchived, reqToken(), reqRepoWriter(unit.TypeWiki), repo.DeleteWikiPage)
|
||||||
m.Get("/revisions/{pageName}", repo.ListPageRevisions)
|
m.Get("/revisions/{pageName}", repo.ListPageRevisions)
|
||||||
m.Post("/new", mustNotBeArchived, reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeWiki), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage)
|
m.Post("/new", reqToken(), mustNotBeArchived, reqRepoWriter(unit.TypeWiki), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage)
|
||||||
m.Get("/pages", repo.ListWikiPages)
|
m.Get("/pages", repo.ListWikiPages)
|
||||||
}, mustEnableWiki)
|
}, mustEnableWiki)
|
||||||
m.Group("/issues", func() {
|
m.Post("/markup", reqToken(), bind(api.MarkupOption{}), misc.Markup)
|
||||||
m.Combo("").Get(repo.ListIssues).
|
m.Post("/markdown", reqToken(), bind(api.MarkdownOption{}), misc.Markdown)
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
|
m.Post("/markdown/raw", reqToken(), misc.MarkdownRaw)
|
||||||
m.Get("/pinned", repo.ListPinnedIssues)
|
|
||||||
m.Group("/comments", func() {
|
|
||||||
m.Get("", repo.ListRepoIssueComments)
|
|
||||||
m.Group("/{id}", func() {
|
|
||||||
m.Combo("").
|
|
||||||
Get(repo.GetIssueComment).
|
|
||||||
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(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(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.CreateIssueCommentAttachment)
|
|
||||||
m.Combo("/{asset}").
|
|
||||||
Get(repo.GetIssueCommentAttachment).
|
|
||||||
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(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(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(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("").
|
|
||||||
Get(repo.ListTrackedTimes).
|
|
||||||
Post(bind(api.AddTimeOption{}), repo.AddTime).
|
|
||||||
Delete(repo.ResetIssueTime)
|
|
||||||
m.Delete("/{id}", repo.DeleteTime)
|
|
||||||
}, 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(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(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(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(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.CreateIssueAttachment)
|
|
||||||
m.Combo("/{asset}").
|
|
||||||
Get(repo.GetIssueAttachment).
|
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueAttachment).
|
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.DeleteIssueAttachment)
|
|
||||||
}, mustEnableAttachments)
|
|
||||||
m.Combo("/dependencies").
|
|
||||||
Get(repo.GetIssueDependencies).
|
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.IssueMeta{}), repo.CreateIssueDependency).
|
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.IssueMeta{}), repo.RemoveIssueDependency)
|
|
||||||
m.Combo("/blocks").
|
|
||||||
Get(repo.GetIssueBlocks).
|
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.IssueMeta{}), repo.CreateIssueBlocking).
|
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), bind(api.IssueMeta{}), repo.RemoveIssueBlocking)
|
|
||||||
m.Group("/pin", func() {
|
|
||||||
m.Combo("").
|
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), repo.PinIssue).
|
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), repo.UnpinIssue)
|
|
||||||
m.Patch("/{position}", reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), repo.MoveIssuePin)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}, mustEnableIssuesOrPulls)
|
|
||||||
m.Group("/labels", func() {
|
|
||||||
m.Combo("").Get(repo.ListLabels).
|
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateLabelOption{}), repo.CreateLabel)
|
|
||||||
m.Combo("/{id}").Get(repo.GetLabel).
|
|
||||||
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("/markup", reqToken(auth_model.AccessTokenScopeRepo), bind(api.MarkupOption{}), misc.Markup)
|
|
||||||
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(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateMilestoneOption{}), repo.CreateMilestone)
|
|
||||||
m.Combo("/{id}").Get(repo.GetMilestone).
|
|
||||||
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("/stargazers", repo.ListStargazers)
|
||||||
m.Get("/subscribers", repo.ListSubscribers)
|
m.Get("/subscribers", repo.ListSubscribers)
|
||||||
m.Group("/subscription", func() {
|
m.Group("/subscription", func() {
|
||||||
m.Get("", user.IsWatching)
|
m.Get("", user.IsWatching)
|
||||||
m.Put("", reqToken(auth_model.AccessTokenScopeRepo), user.Watch)
|
m.Put("", reqToken(), user.Watch)
|
||||||
m.Delete("", reqToken(auth_model.AccessTokenScopeRepo), user.Unwatch)
|
m.Delete("", reqToken(), user.Unwatch)
|
||||||
})
|
})
|
||||||
m.Group("/releases", func() {
|
m.Group("/releases", func() {
|
||||||
m.Combo("").Get(repo.ListReleases).
|
m.Combo("").Get(repo.ListReleases).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.CreateReleaseOption{}), repo.CreateRelease)
|
Post(reqToken(), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.CreateReleaseOption{}), repo.CreateRelease)
|
||||||
m.Combo("/latest").Get(repo.GetLatestRelease)
|
m.Combo("/latest").Get(repo.GetLatestRelease)
|
||||||
m.Group("/{id}", func() {
|
m.Group("/{id}", func() {
|
||||||
m.Combo("").Get(repo.GetRelease).
|
m.Combo("").Get(repo.GetRelease).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.EditReleaseOption{}), repo.EditRelease).
|
Patch(reqToken(), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.EditReleaseOption{}), repo.EditRelease).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), repo.DeleteRelease)
|
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteRelease)
|
||||||
m.Group("/assets", func() {
|
m.Group("/assets", func() {
|
||||||
m.Combo("").Get(repo.ListReleaseAttachments).
|
m.Combo("").Get(repo.ListReleaseAttachments).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), repo.CreateReleaseAttachment)
|
Post(reqToken(), reqRepoWriter(unit.TypeReleases), repo.CreateReleaseAttachment)
|
||||||
m.Combo("/{asset}").Get(repo.GetReleaseAttachment).
|
m.Combo("/{asset}").Get(repo.GetReleaseAttachment).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment).
|
Patch(reqToken(), reqRepoWriter(unit.TypeReleases), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseAttachment)
|
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseAttachment)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
m.Group("/tags", func() {
|
m.Group("/tags", func() {
|
||||||
m.Combo("/{tag}").
|
m.Combo("/{tag}").
|
||||||
Get(repo.GetReleaseByTag).
|
Get(repo.GetReleaseByTag).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseByTag)
|
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseByTag)
|
||||||
})
|
})
|
||||||
}, reqRepoReader(unit.TypeReleases))
|
}, reqRepoReader(unit.TypeReleases))
|
||||||
m.Post("/mirror-sync", reqToken(auth_model.AccessTokenScopeRepo), reqRepoWriter(unit.TypeCode), repo.MirrorSync)
|
m.Post("/mirror-sync", reqToken(), reqRepoWriter(unit.TypeCode), repo.MirrorSync)
|
||||||
m.Post("/push_mirrors-sync", reqAdmin(), reqToken(auth_model.AccessTokenScopeRepo), repo.PushMirrorSync)
|
m.Post("/push_mirrors-sync", reqAdmin(), reqToken(), repo.PushMirrorSync)
|
||||||
m.Group("/push_mirrors", func() {
|
m.Group("/push_mirrors", func() {
|
||||||
m.Combo("").Get(repo.ListPushMirrors).
|
m.Combo("").Get(repo.ListPushMirrors).
|
||||||
Post(bind(api.CreatePushMirrorOption{}), repo.AddPushMirror)
|
Post(bind(api.CreatePushMirrorOption{}), repo.AddPushMirror)
|
||||||
m.Combo("/{name}").
|
m.Combo("/{name}").
|
||||||
Delete(repo.DeletePushMirrorByRemoteName).
|
Delete(repo.DeletePushMirrorByRemoteName).
|
||||||
Get(repo.GetPushMirrorByName)
|
Get(repo.GetPushMirrorByName)
|
||||||
}, reqAdmin(), reqToken(auth_model.AccessTokenScopeRepo))
|
}, reqAdmin(), reqToken())
|
||||||
|
|
||||||
m.Get("/editorconfig/{filename}", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetEditorconfig)
|
m.Get("/editorconfig/{filename}", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetEditorconfig)
|
||||||
m.Group("/pulls", func() {
|
m.Group("/pulls", func() {
|
||||||
m.Combo("").Get(repo.ListPullRequests).
|
m.Combo("").Get(repo.ListPullRequests).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(api.CreatePullRequestOption{}), repo.CreatePullRequest)
|
Post(reqToken(), mustNotBeArchived, bind(api.CreatePullRequestOption{}), repo.CreatePullRequest)
|
||||||
m.Get("/pinned", repo.ListPinnedPullRequests)
|
m.Get("/pinned", repo.ListPinnedPullRequests)
|
||||||
m.Group("/{index}", func() {
|
m.Group("/{index}", func() {
|
||||||
m.Combo("").Get(repo.GetPullRequest).
|
m.Combo("").Get(repo.GetPullRequest).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeRepo), bind(api.EditPullRequestOption{}), repo.EditPullRequest)
|
Patch(reqToken(), bind(api.EditPullRequestOption{}), repo.EditPullRequest)
|
||||||
m.Get(".{diffType:diff|patch}", repo.DownloadPullDiffOrPatch)
|
m.Get(".{diffType:diff|patch}", repo.DownloadPullDiffOrPatch)
|
||||||
m.Post("/update", reqToken(auth_model.AccessTokenScopeRepo), repo.UpdatePullRequest)
|
m.Post("/update", reqToken(), repo.UpdatePullRequest)
|
||||||
m.Get("/commits", repo.GetPullRequestCommits)
|
m.Get("/commits", repo.GetPullRequestCommits)
|
||||||
m.Get("/files", repo.GetPullRequestFiles)
|
m.Get("/files", repo.GetPullRequestFiles)
|
||||||
m.Combo("/merge").Get(repo.IsPullRequestMerged).
|
m.Combo("/merge").Get(repo.IsPullRequestMerged).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, bind(forms.MergePullRequestForm{}), repo.MergePullRequest).
|
Post(reqToken(), mustNotBeArchived, bind(forms.MergePullRequestForm{}), repo.MergePullRequest).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), mustNotBeArchived, repo.CancelScheduledAutoMerge)
|
Delete(reqToken(), mustNotBeArchived, repo.CancelScheduledAutoMerge)
|
||||||
m.Group("/reviews", func() {
|
m.Group("/reviews", func() {
|
||||||
m.Combo("").
|
m.Combo("").
|
||||||
Get(repo.ListPullReviews).
|
Get(repo.ListPullReviews).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.CreatePullReviewOptions{}), repo.CreatePullReview)
|
Post(reqToken(), bind(api.CreatePullReviewOptions{}), repo.CreatePullReview)
|
||||||
m.Group("/{id}", func() {
|
m.Group("/{id}", func() {
|
||||||
m.Combo("").
|
m.Combo("").
|
||||||
Get(repo.GetPullReview).
|
Get(repo.GetPullReview).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), repo.DeletePullReview).
|
Delete(reqToken(), repo.DeletePullReview).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepo), bind(api.SubmitPullReviewOptions{}), repo.SubmitPullReview)
|
Post(reqToken(), bind(api.SubmitPullReviewOptions{}), repo.SubmitPullReview)
|
||||||
m.Combo("/comments").
|
m.Combo("/comments").
|
||||||
Get(repo.GetPullReviewComments)
|
Get(repo.GetPullReviewComments)
|
||||||
m.Post("/dismissals", reqToken(auth_model.AccessTokenScopeRepo), bind(api.DismissPullReviewOptions{}), repo.DismissPullReview)
|
m.Post("/dismissals", reqToken(), bind(api.DismissPullReviewOptions{}), repo.DismissPullReview)
|
||||||
m.Post("/undismissals", reqToken(auth_model.AccessTokenScopeRepo), repo.UnDismissPullReview)
|
m.Post("/undismissals", reqToken(), repo.UnDismissPullReview)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
m.Combo("/requested_reviewers", reqToken(auth_model.AccessTokenScopeRepo)).
|
m.Combo("/requested_reviewers", reqToken()).
|
||||||
Delete(bind(api.PullReviewRequestOptions{}), repo.DeleteReviewRequests).
|
Delete(bind(api.PullReviewRequestOptions{}), repo.DeleteReviewRequests).
|
||||||
Post(bind(api.PullReviewRequestOptions{}), repo.CreateReviewRequests)
|
Post(bind(api.PullReviewRequestOptions{}), repo.CreateReviewRequests)
|
||||||
})
|
})
|
||||||
}, mustAllowPulls, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo())
|
}, mustAllowPulls, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo())
|
||||||
m.Group("/statuses", func() {
|
m.Group("/statuses", func() {
|
||||||
m.Combo("/{sha}").Get(repo.GetCommitStatuses).
|
m.Combo("/{sha}").Get(repo.GetCommitStatuses).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeRepoStatus), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
|
Post(reqToken(), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
|
||||||
}, reqRepoReader(unit.TypeCode))
|
}, reqRepoReader(unit.TypeCode))
|
||||||
m.Group("/commits", func() {
|
m.Group("/commits", func() {
|
||||||
m.Get("", context.ReferencesGitRepo(), repo.GetAllCommits)
|
m.Get("", context.ReferencesGitRepo(), repo.GetAllCommits)
|
||||||
|
@ -1170,24 +1114,24 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
m.Get("/tags/{sha}", repo.GetAnnotatedTag)
|
m.Get("/tags/{sha}", repo.GetAnnotatedTag)
|
||||||
m.Get("/notes/{sha}", repo.GetNote)
|
m.Get("/notes/{sha}", repo.GetNote)
|
||||||
}, context.ReferencesGitRepo(true), reqRepoReader(unit.TypeCode))
|
}, context.ReferencesGitRepo(true), reqRepoReader(unit.TypeCode))
|
||||||
m.Post("/diffpatch", reqRepoWriter(unit.TypeCode), reqToken(auth_model.AccessTokenScopeRepo), bind(api.ApplyDiffPatchFileOptions{}), repo.ApplyDiffPatch)
|
m.Post("/diffpatch", reqRepoWriter(unit.TypeCode), reqToken(), bind(api.ApplyDiffPatchFileOptions{}), repo.ApplyDiffPatch)
|
||||||
m.Group("/contents", func() {
|
m.Group("/contents", func() {
|
||||||
m.Get("", repo.GetContentsList)
|
m.Get("", repo.GetContentsList)
|
||||||
m.Post("", reqToken(auth_model.AccessTokenScopeRepo), bind(api.ChangeFilesOptions{}), reqRepoBranchWriter, repo.ChangeFiles)
|
m.Post("", reqToken(), bind(api.ChangeFilesOptions{}), reqRepoBranchWriter, repo.ChangeFiles)
|
||||||
m.Get("/*", repo.GetContents)
|
m.Get("/*", repo.GetContents)
|
||||||
m.Group("/*", func() {
|
m.Group("/*", func() {
|
||||||
m.Post("", bind(api.CreateFileOptions{}), reqRepoBranchWriter, repo.CreateFile)
|
m.Post("", bind(api.CreateFileOptions{}), reqRepoBranchWriter, repo.CreateFile)
|
||||||
m.Put("", bind(api.UpdateFileOptions{}), reqRepoBranchWriter, repo.UpdateFile)
|
m.Put("", bind(api.UpdateFileOptions{}), reqRepoBranchWriter, repo.UpdateFile)
|
||||||
m.Delete("", bind(api.DeleteFileOptions{}), reqRepoBranchWriter, repo.DeleteFile)
|
m.Delete("", bind(api.DeleteFileOptions{}), reqRepoBranchWriter, repo.DeleteFile)
|
||||||
}, reqToken(auth_model.AccessTokenScopeRepo))
|
}, reqToken())
|
||||||
}, reqRepoReader(unit.TypeCode))
|
}, reqRepoReader(unit.TypeCode))
|
||||||
m.Get("/signing-key.gpg", misc.SigningKey)
|
m.Get("/signing-key.gpg", misc.SigningKey)
|
||||||
m.Group("/topics", func() {
|
m.Group("/topics", func() {
|
||||||
m.Combo("").Get(repo.ListTopics).
|
m.Combo("").Get(repo.ListTopics).
|
||||||
Put(reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics)
|
Put(reqToken(), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics)
|
||||||
m.Group("/{topic}", func() {
|
m.Group("/{topic}", func() {
|
||||||
m.Combo("").Put(reqToken(auth_model.AccessTokenScopeRepo), repo.AddTopic).
|
m.Combo("").Put(reqToken(), repo.AddTopic).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeRepo), repo.DeleteTopic)
|
Delete(reqToken(), repo.DeleteTopic)
|
||||||
}, reqAdmin())
|
}, reqAdmin())
|
||||||
}, reqAnyRepoReader())
|
}, reqAnyRepoReader())
|
||||||
m.Get("/issue_templates", context.ReferencesGitRepo(), repo.GetIssueTemplates)
|
m.Get("/issue_templates", context.ReferencesGitRepo(), repo.GetIssueTemplates)
|
||||||
|
@ -1197,54 +1141,177 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
m.Get("/activities/feeds", repo.ListRepoActivityFeeds)
|
m.Get("/activities/feeds", repo.ListRepoActivityFeeds)
|
||||||
m.Get("/new_pin_allowed", repo.AreNewIssuePinsAllowed)
|
m.Get("/new_pin_allowed", repo.AreNewIssuePinsAllowed)
|
||||||
}, repoAssignment())
|
}, repoAssignment())
|
||||||
})
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
|
||||||
|
|
||||||
|
// Notifications (requires notifications scope)
|
||||||
|
m.Group("/repos", func() {
|
||||||
|
m.Group("/{username}/{reponame}", func() {
|
||||||
|
m.Combo("/notifications", reqToken()).
|
||||||
|
Get(notify.ListRepoNotifications).
|
||||||
|
Put(notify.ReadRepoNotifications)
|
||||||
|
}, repoAssignment())
|
||||||
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryNotification))
|
||||||
|
|
||||||
|
// Issue (requires issue scope)
|
||||||
|
m.Group("/repos", func() {
|
||||||
|
m.Get("/issues/search", repo.SearchIssues)
|
||||||
|
|
||||||
|
m.Group("/{username}/{reponame}", func() {
|
||||||
|
m.Group("/issues", func() {
|
||||||
|
m.Combo("").Get(repo.ListIssues).
|
||||||
|
Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
|
||||||
|
m.Get("/pinned", repo.ListPinnedIssues)
|
||||||
|
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)
|
||||||
|
m.Combo("/reactions").
|
||||||
|
Get(repo.GetIssueCommentReactions).
|
||||||
|
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueCommentReaction).
|
||||||
|
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueCommentReaction)
|
||||||
|
m.Group("/assets", func() {
|
||||||
|
m.Combo("").
|
||||||
|
Get(repo.ListIssueCommentAttachments).
|
||||||
|
Post(reqToken(), mustNotBeArchived, repo.CreateIssueCommentAttachment)
|
||||||
|
m.Combo("/{asset}").
|
||||||
|
Get(repo.GetIssueCommentAttachment).
|
||||||
|
Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueCommentAttachment).
|
||||||
|
Delete(reqToken(), 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)
|
||||||
|
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).
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
m.Group("/times", func() {
|
||||||
|
m.Combo("").
|
||||||
|
Get(repo.ListTrackedTimes).
|
||||||
|
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)
|
||||||
|
m.Group("/stopwatch", func() {
|
||||||
|
m.Post("/start", repo.StartIssueStopwatch)
|
||||||
|
m.Post("/stop", repo.StopIssueStopwatch)
|
||||||
|
m.Delete("/delete", repo.DeleteIssueStopwatch)
|
||||||
|
}, reqToken())
|
||||||
|
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.Combo("/reactions").
|
||||||
|
Get(repo.GetIssueReactions).
|
||||||
|
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueReaction).
|
||||||
|
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueReaction)
|
||||||
|
m.Group("/assets", func() {
|
||||||
|
m.Combo("").
|
||||||
|
Get(repo.ListIssueAttachments).
|
||||||
|
Post(reqToken(), mustNotBeArchived, repo.CreateIssueAttachment)
|
||||||
|
m.Combo("/{asset}").
|
||||||
|
Get(repo.GetIssueAttachment).
|
||||||
|
Patch(reqToken(), mustNotBeArchived, bind(api.EditAttachmentOptions{}), repo.EditIssueAttachment).
|
||||||
|
Delete(reqToken(), mustNotBeArchived, repo.DeleteIssueAttachment)
|
||||||
|
}, mustEnableAttachments)
|
||||||
|
m.Combo("/dependencies").
|
||||||
|
Get(repo.GetIssueDependencies).
|
||||||
|
Post(reqToken(), mustNotBeArchived, bind(api.IssueMeta{}), repo.CreateIssueDependency).
|
||||||
|
Delete(reqToken(), mustNotBeArchived, bind(api.IssueMeta{}), repo.RemoveIssueDependency)
|
||||||
|
m.Combo("/blocks").
|
||||||
|
Get(repo.GetIssueBlocks).
|
||||||
|
Post(reqToken(), bind(api.IssueMeta{}), repo.CreateIssueBlocking).
|
||||||
|
Delete(reqToken(), bind(api.IssueMeta{}), repo.RemoveIssueBlocking)
|
||||||
|
m.Group("/pin", func() {
|
||||||
|
m.Combo("").
|
||||||
|
Post(reqToken(), reqAdmin(), repo.PinIssue).
|
||||||
|
Delete(reqToken(), reqAdmin(), repo.UnpinIssue)
|
||||||
|
m.Patch("/{position}", reqToken(), reqAdmin(), repo.MoveIssuePin)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}, mustEnableIssuesOrPulls)
|
||||||
|
m.Group("/labels", func() {
|
||||||
|
m.Combo("").Get(repo.ListLabels).
|
||||||
|
Post(reqToken(), 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)
|
||||||
|
})
|
||||||
|
m.Group("/milestones", func() {
|
||||||
|
m.Combo("").Get(repo.ListMilestones).
|
||||||
|
Post(reqToken(), 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)
|
||||||
|
})
|
||||||
|
}, repoAssignment())
|
||||||
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryIssue))
|
||||||
|
|
||||||
// NOTE: these are Gitea package management API - see packages.CommonRoutes and packages.DockerContainerRoutes for endpoints that implement package manager APIs
|
// 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("/packages/{username}", func() {
|
||||||
m.Group("/{type}/{name}/{version}", func() {
|
m.Group("/{type}/{name}/{version}", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadPackage), packages.GetPackage)
|
m.Get("", reqToken(), packages.GetPackage)
|
||||||
m.Delete("", reqToken(auth_model.AccessTokenScopeDeletePackage), reqPackageAccess(perm.AccessModeWrite), packages.DeletePackage)
|
m.Delete("", reqToken(), reqPackageAccess(perm.AccessModeWrite), packages.DeletePackage)
|
||||||
m.Get("/files", reqToken(auth_model.AccessTokenScopeReadPackage), packages.ListPackageFiles)
|
m.Get("/files", reqToken(), packages.ListPackageFiles)
|
||||||
})
|
})
|
||||||
m.Get("/", reqToken(auth_model.AccessTokenScopeReadPackage), packages.ListPackages)
|
m.Get("/", reqToken(), packages.ListPackages)
|
||||||
}, context_service.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead))
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryPackage), context_service.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead))
|
||||||
|
|
||||||
// Organizations
|
// Organizations
|
||||||
m.Get("/user/orgs", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListMyOrgs)
|
m.Get("/user/orgs", reqToken(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), org.ListMyOrgs)
|
||||||
m.Group("/users/{username}/orgs", func() {
|
m.Group("/users/{username}/orgs", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListUserOrgs)
|
m.Get("", reqToken(), org.ListUserOrgs)
|
||||||
m.Get("/{org}/permissions", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetUserOrgsPermissions)
|
m.Get("/{org}/permissions", reqToken(), org.GetUserOrgsPermissions)
|
||||||
}, context_service.UserAssignmentAPI())
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), context_service.UserAssignmentAPI())
|
||||||
m.Post("/orgs", reqToken(auth_model.AccessTokenScopeWriteOrg), bind(api.CreateOrgOption{}), org.Create)
|
m.Post("/orgs", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), reqToken(), bind(api.CreateOrgOption{}), org.Create)
|
||||||
m.Get("/orgs", org.GetAll)
|
m.Get("/orgs", org.GetAll, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization))
|
||||||
m.Group("/orgs/{org}", func() {
|
m.Group("/orgs/{org}", func() {
|
||||||
m.Combo("").Get(org.Get).
|
m.Combo("").Get(org.Get).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
|
Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.Delete)
|
Delete(reqToken(), reqOrgOwnership(), org.Delete)
|
||||||
m.Combo("/repos").Get(user.ListOrgRepos).
|
m.Combo("/repos").Get(user.ListOrgRepos).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeWriteOrg), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
|
Post(reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
|
||||||
m.Group("/members", func() {
|
m.Group("/members", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListMembers)
|
m.Get("", reqToken(), org.ListMembers)
|
||||||
m.Combo("/{username}").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.IsMember).
|
m.Combo("/{username}").Get(reqToken(), org.IsMember).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.DeleteMember)
|
Delete(reqToken(), reqOrgOwnership(), org.DeleteMember)
|
||||||
})
|
})
|
||||||
m.Group("/public_members", func() {
|
m.Group("/public_members", func() {
|
||||||
m.Get("", org.ListPublicMembers)
|
m.Get("", org.ListPublicMembers)
|
||||||
m.Combo("/{username}").Get(org.IsPublicMember).
|
m.Combo("/{username}").Get(org.IsPublicMember).
|
||||||
Put(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgMembership(), org.PublicizeMember).
|
Put(reqToken(), reqOrgMembership(), org.PublicizeMember).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgMembership(), org.ConcealMember)
|
Delete(reqToken(), reqOrgMembership(), org.ConcealMember)
|
||||||
})
|
})
|
||||||
m.Group("/teams", func() {
|
m.Group("/teams", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListTeams)
|
m.Get("", reqToken(), org.ListTeams)
|
||||||
m.Post("", reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam)
|
m.Post("", reqToken(), reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam)
|
||||||
m.Get("/search", reqToken(auth_model.AccessTokenScopeReadOrg), org.SearchTeam)
|
m.Get("/search", reqToken(), org.SearchTeam)
|
||||||
}, reqOrgMembership())
|
}, reqOrgMembership())
|
||||||
m.Group("/labels", func() {
|
m.Group("/labels", func() {
|
||||||
m.Get("", org.ListLabels)
|
m.Get("", org.ListLabels)
|
||||||
m.Post("", reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel)
|
m.Post("", reqToken(), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel)
|
||||||
m.Combo("/{id}").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetLabel).
|
m.Combo("/{id}").Get(reqToken(), org.GetLabel).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel).
|
Patch(reqToken(), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.DeleteLabel)
|
Delete(reqToken(), reqOrgOwnership(), org.DeleteLabel)
|
||||||
})
|
})
|
||||||
m.Group("/hooks", func() {
|
m.Group("/hooks", func() {
|
||||||
m.Combo("").Get(org.ListHooks).
|
m.Combo("").Get(org.ListHooks).
|
||||||
|
@ -1252,29 +1319,29 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
m.Combo("/{id}").Get(org.GetHook).
|
m.Combo("/{id}").Get(org.GetHook).
|
||||||
Patch(bind(api.EditHookOption{}), org.EditHook).
|
Patch(bind(api.EditHookOption{}), org.EditHook).
|
||||||
Delete(org.DeleteHook)
|
Delete(org.DeleteHook)
|
||||||
}, reqToken(auth_model.AccessTokenScopeAdminOrgHook), reqOrgOwnership(), reqWebhooksEnabled())
|
}, reqToken(), reqOrgOwnership(), reqWebhooksEnabled())
|
||||||
m.Get("/activities/feeds", org.ListOrgActivityFeeds)
|
m.Get("/activities/feeds", org.ListOrgActivityFeeds)
|
||||||
}, orgAssignment(true))
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true))
|
||||||
m.Group("/teams/{teamid}", func() {
|
m.Group("/teams/{teamid}", func() {
|
||||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeam).
|
m.Combo("").Get(reqToken(), org.GetTeam).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditTeamOption{}), org.EditTeam).
|
Patch(reqToken(), reqOrgOwnership(), bind(api.EditTeamOption{}), org.EditTeam).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.DeleteTeam)
|
Delete(reqToken(), reqOrgOwnership(), org.DeleteTeam)
|
||||||
m.Group("/members", func() {
|
m.Group("/members", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamMembers)
|
m.Get("", reqToken(), org.GetTeamMembers)
|
||||||
m.Combo("/{username}").
|
m.Combo("/{username}").
|
||||||
Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamMember).
|
Get(reqToken(), org.GetTeamMember).
|
||||||
Put(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.AddTeamMember).
|
Put(reqToken(), reqOrgOwnership(), org.AddTeamMember).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.RemoveTeamMember)
|
Delete(reqToken(), reqOrgOwnership(), org.RemoveTeamMember)
|
||||||
})
|
})
|
||||||
m.Group("/repos", func() {
|
m.Group("/repos", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamRepos)
|
m.Get("", reqToken(), org.GetTeamRepos)
|
||||||
m.Combo("/{org}/{reponame}").
|
m.Combo("/{org}/{reponame}").
|
||||||
Put(reqToken(auth_model.AccessTokenScopeWriteOrg), org.AddTeamRepository).
|
Put(reqToken(), org.AddTeamRepository).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), org.RemoveTeamRepository).
|
Delete(reqToken(), org.RemoveTeamRepository).
|
||||||
Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamRepo)
|
Get(reqToken(), org.GetTeamRepo)
|
||||||
})
|
})
|
||||||
m.Get("/activities/feeds", org.ListTeamActivityFeeds)
|
m.Get("/activities/feeds", org.ListTeamActivityFeeds)
|
||||||
}, orgAssignment(false, true), reqToken(""), reqTeamMembership())
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(false, true), reqToken(), reqTeamMembership())
|
||||||
|
|
||||||
m.Group("/admin", func() {
|
m.Group("/admin", func() {
|
||||||
m.Group("/cron", func() {
|
m.Group("/cron", func() {
|
||||||
|
@ -1314,11 +1381,11 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
Patch(bind(api.EditHookOption{}), admin.EditHook).
|
Patch(bind(api.EditHookOption{}), admin.EditHook).
|
||||||
Delete(admin.DeleteHook)
|
Delete(admin.DeleteHook)
|
||||||
})
|
})
|
||||||
}, reqToken(auth_model.AccessTokenScopeSudo), reqSiteAdmin())
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryAdmin), reqToken(), reqSiteAdmin())
|
||||||
|
|
||||||
m.Group("/topics", func() {
|
m.Group("/topics", func() {
|
||||||
m.Get("/search", repo.TopicSearch)
|
m.Get("/search", repo.TopicSearch)
|
||||||
})
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
|
||||||
}, sudo())
|
}, sudo())
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
|
@ -152,7 +152,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
context.CheckRepoScopedToken(ctx, repo)
|
context.CheckRepoScopedToken(ctx, repo, auth_model.GetScopeLevelFromAccessMode(accessMode))
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ func DeleteApplication(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadApplicationsData(ctx *context.Context) {
|
func loadApplicationsData(ctx *context.Context) {
|
||||||
|
ctx.Data["AccessTokenScopePublicOnly"] = auth_model.AccessTokenScopePublicOnly
|
||||||
tokens, err := auth_model.ListAccessTokens(auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID})
|
tokens, err := auth_model.ListAccessTokens(auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListAccessTokens", err)
|
ctx.ServerError("ListAccessTokens", err)
|
||||||
|
@ -96,6 +97,7 @@ func loadApplicationsData(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
ctx.Data["Tokens"] = tokens
|
ctx.Data["Tokens"] = tokens
|
||||||
ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable
|
ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable
|
||||||
|
ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin
|
||||||
if setting.OAuth2.Enable {
|
if setting.OAuth2.Enable {
|
||||||
ctx.Data["Applications"], err = auth_model.GetOAuth2ApplicationsByUserID(ctx, ctx.Doer.ID)
|
ctx.Data["Applications"], err = auth_model.GetOAuth2ApplicationsByUserID(ctx, ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -112,12 +112,12 @@ func TestNewAccessTokenForm_GetScope(t *testing.T) {
|
||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
form: NewAccessTokenForm{Name: "test", Scope: []string{"repo"}},
|
form: NewAccessTokenForm{Name: "test", Scope: []string{"read:repository"}},
|
||||||
scope: "repo",
|
scope: "read:repository",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
form: NewAccessTokenForm{Name: "test", Scope: []string{"repo", "user"}},
|
form: NewAccessTokenForm{Name: "test", Scope: []string{"read:repository", "write:user"}},
|
||||||
scope: "repo,user",
|
scope: "read:repository,write:user",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -58,7 +59,7 @@ func GetListLockHandler(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
repository.MustOwner(ctx)
|
repository.MustOwner(ctx)
|
||||||
|
|
||||||
context.CheckRepoScopedToken(ctx, repository)
|
context.CheckRepoScopedToken(ctx, repository, auth_model.Read)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -150,7 +151,7 @@ func PostLockHandler(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
repository.MustOwner(ctx)
|
repository.MustOwner(ctx)
|
||||||
|
|
||||||
context.CheckRepoScopedToken(ctx, repository)
|
context.CheckRepoScopedToken(ctx, repository, auth_model.Write)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -222,7 +223,7 @@ func VerifyLockHandler(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
repository.MustOwner(ctx)
|
repository.MustOwner(ctx)
|
||||||
|
|
||||||
context.CheckRepoScopedToken(ctx, repository)
|
context.CheckRepoScopedToken(ctx, repository, auth_model.Read)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -293,7 +294,7 @@ func UnLockHandler(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
repository.MustOwner(ctx)
|
repository.MustOwner(ctx)
|
||||||
|
|
||||||
context.CheckRepoScopedToken(ctx, repository)
|
context.CheckRepoScopedToken(ctx, repository, auth_model.Write)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
actions_model "code.gitea.io/gitea/models/actions"
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
access_model "code.gitea.io/gitea/models/perm/access"
|
||||||
|
@ -423,7 +424,12 @@ func getAuthenticatedRepository(ctx *context.Context, rc *requestContext, requir
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
context.CheckRepoScopedToken(ctx, repository)
|
if requireWrite {
|
||||||
|
context.CheckRepoScopedToken(ctx, repository, auth_model.Write)
|
||||||
|
} else {
|
||||||
|
context.CheckRepoScopedToken(ctx, repository, auth_model.Read)
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,21 @@
|
||||||
</div>
|
</div>
|
||||||
<i class="text {{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-tooltip-content="{{$.locale.Tr "settings.token_state_desc"}}"{{end}}>{{svg "fontawesome-send" 36}}</i>
|
<i class="text {{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-tooltip-content="{{$.locale.Tr "settings.token_state_desc"}}"{{end}}>{{svg "fontawesome-send" 36}}</i>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<!--Temporarily disable-->
|
<details><summary><strong>{{.Name}}</strong></summary>
|
||||||
<strong>{{.Name}}</strong>
|
<p class="gt-my-2">
|
||||||
<details class="gt-hidden"><summary><strong>{{.Name}}</strong></summary>
|
{{$.locale.Tr "settings.repo_and_org_access"}}:
|
||||||
<p class="gt-my-2">{{$.locale.Tr "settings.scopes_list"}}</p>
|
{{if .DisplayPublicOnly}}
|
||||||
|
{{$.locale.Tr "settings.permissions_public_only"}}
|
||||||
|
{{else}}
|
||||||
|
{{$.locale.Tr "settings.permissions_access_all"}}
|
||||||
|
{{end}}
|
||||||
|
</p>
|
||||||
|
<p class="gt-my-2">{{$.locale.Tr "settings.permissions_list"}}</p>
|
||||||
<ul class="gt-my-2">
|
<ul class="gt-my-2">
|
||||||
{{range .Scope.StringSlice}}
|
{{range .Scope.StringSlice}}
|
||||||
<li>{{.}}</li>
|
{{if (ne . $.AccessTokenScopePublicOnly)}}
|
||||||
|
<li>{{.}}</li>
|
||||||
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
|
@ -40,222 +48,46 @@
|
||||||
<h5 class="ui top header">
|
<h5 class="ui top header">
|
||||||
{{.locale.Tr "settings.generate_new_token"}}
|
{{.locale.Tr "settings.generate_new_token"}}
|
||||||
</h5>
|
</h5>
|
||||||
<p>{{.locale.Tr "settings.new_token_desc"}}</p>
|
<form id="scoped-access-form" class="ui form ignore-dirty" action="{{.Link}}" method="post">
|
||||||
<form class="ui form ignore-dirty" action="{{.Link}}" method="post">
|
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<div class="field {{if .Err_Name}}error{{end}}">
|
<div class="field {{if .Err_Name}}error{{end}}">
|
||||||
<label for="name">{{.locale.Tr "settings.token_name"}}</label>
|
<label for="name">{{.locale.Tr "settings.token_name"}}</label>
|
||||||
<input id="name" name="name" value="{{.name}}" autofocus required maxlength="255">
|
<input id="name" name="name" value="{{.name}}" autofocus required maxlength="255">
|
||||||
</div>
|
</div>
|
||||||
<!--Temporarily disable-->
|
<div class="field">
|
||||||
<details class="gt-hidden ui optional field">
|
<label>{{.locale.Tr "settings.repo_and_org_access"}}</label>
|
||||||
<summary class="gt-p-2">
|
<label class="gt-cursor-pointer">
|
||||||
{{.locale.Tr "settings.select_scopes"}}
|
<input class="enable-system gt-mt-2 gt-mr-2" type="radio" name="scope" value="{{$.AccessTokenScopePublicOnly}}">
|
||||||
|
{{.locale.Tr "settings.permissions_public_only"}}
|
||||||
|
</label>
|
||||||
|
<label class="gt-cursor-pointer">
|
||||||
|
<input class="enable-system gt-mt-2 gt-mr-2" type="radio" name="scope" value="" checked>
|
||||||
|
{{.locale.Tr "settings.permissions_access_all"}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<details class="ui optional field">
|
||||||
|
<summary class="gt-pb-4 gt-pl-2">
|
||||||
|
{{.locale.Tr "settings.select_permissions"}}
|
||||||
</summary>
|
</summary>
|
||||||
<div class="field gt-pl-2">
|
<div class="activity meta">
|
||||||
<div class="ui checkbox">
|
<i>{{$.locale.Tr "settings.scoped_token_desc" (printf `href="/api/swagger" target="_blank"`) (printf `href="https://docs.gitea.com/development/oauth2-provider#scopes" target="_blank"`) | Str2html}}</i>
|
||||||
<input class="enable-system" type="checkbox" name="scope" value="repo">
|
|
||||||
<label>repo</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field gt-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 gt-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:org">
|
|
||||||
<label>read:org</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 gt-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 gt-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="admin:user_hook">
|
|
||||||
<label>admin:user_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 gt-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 gt-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 gt-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 gt-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>
|
</div>
|
||||||
|
<scoped-access-token-category category="activitypub"></scoped-access-token-category>
|
||||||
|
{{if .IsAdmin}}
|
||||||
|
<scoped-access-token-category category="admin"></scoped-access-token-category>
|
||||||
|
{{end}}
|
||||||
|
<scoped-access-token-category category="issue"></scoped-access-token-category>
|
||||||
|
<scoped-access-token-category category="misc"></scoped-access-token-category>
|
||||||
|
<scoped-access-token-category category="notification"></scoped-access-token-category>
|
||||||
|
<scoped-access-token-category category="organization"></scoped-access-token-category>
|
||||||
|
<scoped-access-token-category category="package"></scoped-access-token-category>
|
||||||
|
<scoped-access-token-category category="repository"></scoped-access-token-category>
|
||||||
|
<scoped-access-token-category category="user"></scoped-access-token-category>
|
||||||
</details>
|
</details>
|
||||||
<button class="ui green button">
|
<div id="scoped-access-warning" class="ui warning message center gt-db gt-hidden">
|
||||||
|
{{.locale.Tr "settings.at_least_one_permission"}}
|
||||||
|
</div>
|
||||||
|
<button id="scoped-access-submit" class="ui green button">
|
||||||
{{.locale.Tr "settings.generate_token"}}
|
{{.locale.Tr "settings.generate_token"}}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
func TestAPIAdminOrgCreate(t *testing.T) {
|
func TestAPIAdminOrgCreate(t *testing.T) {
|
||||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeSudo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
|
|
||||||
org := api.CreateOrgOption{
|
org := api.CreateOrgOption{
|
||||||
UserName: "user2_org",
|
UserName: "user2_org",
|
||||||
|
@ -55,7 +55,7 @@ func TestAPIAdminOrgCreate(t *testing.T) {
|
||||||
func TestAPIAdminOrgCreateBadVisibility(t *testing.T) {
|
func TestAPIAdminOrgCreateBadVisibility(t *testing.T) {
|
||||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeSudo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
|
|
||||||
org := api.CreateOrgOption{
|
org := api.CreateOrgOption{
|
||||||
UserName: "user2_org",
|
UserName: "user2_org",
|
||||||
|
|
|
@ -25,7 +25,7 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
keyOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
|
keyOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
|
||||||
|
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeSudo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", keyOwner.Name, token)
|
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", keyOwner.Name, token)
|
||||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
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",
|
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM= nocomment\n",
|
||||||
|
@ -52,7 +52,7 @@ func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
// user1 is an admin user
|
// user1 is an admin user
|
||||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteAdmin)
|
||||||
req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d?token=%s", unittest.NonexistentID, token)
|
req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d?token=%s", unittest.NonexistentID, token)
|
||||||
MakeRequest(t, req, http.StatusNotFound)
|
MakeRequest(t, req, http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
normalUsername := "user2"
|
normalUsername := "user2"
|
||||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", adminUsername, token)
|
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", adminUsername, token)
|
||||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||||
|
@ -82,7 +82,7 @@ func TestAPISudoUser(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
normalUsername := "user2"
|
normalUsername := "user2"
|
||||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s&token=%s", normalUsername, token)
|
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s&token=%s", normalUsername, token)
|
||||||
req := NewRequest(t, "GET", urlStr)
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
@ -98,7 +98,7 @@ func TestAPISudoUserForbidden(t *testing.T) {
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
normalUsername := "user2"
|
normalUsername := "user2"
|
||||||
|
|
||||||
token := getUserToken(t, normalUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, normalUsername, auth_model.AccessTokenScopeReadAdmin)
|
||||||
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s&token=%s", adminUsername, token)
|
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s&token=%s", adminUsername, token)
|
||||||
req := NewRequest(t, "GET", urlStr)
|
req := NewRequest(t, "GET", urlStr)
|
||||||
MakeRequest(t, req, http.StatusForbidden)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
@ -107,7 +107,7 @@ func TestAPISudoUserForbidden(t *testing.T) {
|
||||||
func TestAPIListUsers(t *testing.T) {
|
func TestAPIListUsers(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeReadAdmin)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/admin/users?token=%s", token)
|
urlStr := fmt.Sprintf("/api/v1/admin/users?token=%s", token)
|
||||||
req := NewRequest(t, "GET", urlStr)
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
@ -143,7 +143,7 @@ func TestAPIListUsersNonAdmin(t *testing.T) {
|
||||||
func TestAPICreateUserInvalidEmail(t *testing.T) {
|
func TestAPICreateUserInvalidEmail(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
urlStr := fmt.Sprintf("/api/v1/admin/users?token=%s", token)
|
urlStr := fmt.Sprintf("/api/v1/admin/users?token=%s", token)
|
||||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||||
"email": "invalid_email@domain.com\r\n",
|
"email": "invalid_email@domain.com\r\n",
|
||||||
|
@ -161,7 +161,7 @@ func TestAPICreateUserInvalidEmail(t *testing.T) {
|
||||||
func TestAPICreateAndDeleteUser(t *testing.T) {
|
func TestAPICreateAndDeleteUser(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
|
|
||||||
req := NewRequestWithValues(
|
req := NewRequestWithValues(
|
||||||
t,
|
t,
|
||||||
|
@ -187,7 +187,7 @@ func TestAPICreateAndDeleteUser(t *testing.T) {
|
||||||
func TestAPIEditUser(t *testing.T) {
|
func TestAPIEditUser(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s?token=%s", "user2", token)
|
urlStr := fmt.Sprintf("/api/v1/admin/users/%s?token=%s", "user2", token)
|
||||||
|
|
||||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||||
|
@ -229,7 +229,7 @@ func TestAPIEditUser(t *testing.T) {
|
||||||
func TestAPICreateRepoForUser(t *testing.T) {
|
func TestAPICreateRepoForUser(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
|
|
||||||
req := NewRequestWithJSON(
|
req := NewRequestWithJSON(
|
||||||
t,
|
t,
|
||||||
|
@ -245,7 +245,7 @@ func TestAPICreateRepoForUser(t *testing.T) {
|
||||||
func TestAPIRenameUser(t *testing.T) {
|
func TestAPIRenameUser(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeSudo)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/rename?token=%s", "user2", token)
|
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/rename?token=%s", "user2", token)
|
||||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||||
// required
|
// required
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
|
func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
|
||||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token)
|
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token)
|
||||||
resp := MakeRequest(t, req, NoExpectedStatus)
|
resp := MakeRequest(t, req, NoExpectedStatus)
|
||||||
if !exists {
|
if !exists {
|
||||||
|
@ -32,7 +32,7 @@ func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token)
|
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token)
|
||||||
resp := MakeRequest(t, req, expectedHTTPStatus)
|
resp := MakeRequest(t, req, expectedHTTPStatus)
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPSta
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections?token="+token, &api.BranchProtection{
|
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections?token="+token, &api.BranchProtection{
|
||||||
RuleName: branchName,
|
RuleName: branchName,
|
||||||
})
|
})
|
||||||
|
@ -58,7 +58,7 @@ func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTP
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.BranchProtection, expectedHTTPStatus int) {
|
func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.BranchProtection, expectedHTTPStatus int) {
|
||||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, "PATCH", "/api/v1/repos/user2/repo1/branch_protections/"+branchName+"?token="+token, body)
|
req := NewRequestWithJSON(t, "PATCH", "/api/v1/repos/user2/repo1/branch_protections/"+branchName+"?token="+token, body)
|
||||||
resp := MakeRequest(t, req, expectedHTTPStatus)
|
resp := MakeRequest(t, req, expectedHTTPStatus)
|
||||||
|
|
||||||
|
@ -70,13 +70,13 @@ func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.Bran
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAPIDeleteBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
func testAPIDeleteBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token)
|
req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token)
|
||||||
MakeRequest(t, req, expectedHTTPStatus)
|
MakeRequest(t, req, expectedHTTPStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAPIDeleteBranch(t *testing.T, branchName string, expectedHTTPStatus int) {
|
func testAPIDeleteBranch(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token)
|
req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token)
|
||||||
MakeRequest(t, req, expectedHTTPStatus)
|
MakeRequest(t, req, expectedHTTPStatus)
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ func TestAPICreateBranch(t *testing.T) {
|
||||||
|
|
||||||
func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
|
func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
|
||||||
username := "user2"
|
username := "user2"
|
||||||
ctx := NewAPITestContext(t, username, "my-noo-repo", auth_model.AccessTokenScopeRepo)
|
ctx := NewAPITestContext(t, username, "my-noo-repo", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
giteaURL.Path = ctx.GitPath()
|
giteaURL.Path = ctx.GitPath()
|
||||||
|
|
||||||
t.Run("CreateRepo", doAPICreateRepository(ctx, false))
|
t.Run("CreateRepo", doAPICreateRepository(ctx, false))
|
||||||
|
@ -149,7 +149,7 @@ func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBranch, newBranch string, status int) bool {
|
func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBranch, newBranch string, status int) bool {
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+user+"/"+repo+"/branches?token="+token, &api.CreateBranchRepoOption{
|
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+user+"/"+repo+"/branches?token="+token, &api.CreateBranchRepoOption{
|
||||||
BranchName: newBranch,
|
BranchName: newBranch,
|
||||||
OldBranchName: oldBranch,
|
OldBranchName: oldBranch,
|
||||||
|
|
|
@ -36,8 +36,8 @@ func TestAPIGetCommentAttachment(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d/assets/%d", repoOwner.Name, repo.Name, comment.ID, attachment.ID)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s", repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
||||||
session.MakeRequest(t, req, http.StatusOK)
|
session.MakeRequest(t, req, http.StatusOK)
|
||||||
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s", repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s", repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -61,8 +61,9 @@ func TestAPIListCommentAttachments(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d/assets",
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
|
||||||
repoOwner.Name, repo.Name, comment.ID)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d/assets?token=%s",
|
||||||
|
repoOwner.Name, repo.Name, comment.ID, token)
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
var apiAttachments []*api.Attachment
|
var apiAttachments []*api.Attachment
|
||||||
|
@ -82,7 +83,7 @@ func TestAPICreateCommentAttachment(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets?token=%s",
|
||||||
repoOwner.Name, repo.Name, comment.ID, token)
|
repoOwner.Name, repo.Name, comment.ID, token)
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@ func TestAPIEditCommentAttachment(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s",
|
||||||
repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
||||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||||
|
@ -144,7 +145,7 @@ func TestAPIDeleteCommentAttachment(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s",
|
||||||
repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ func TestAPIListIssueComments(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeReadIssue)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/comments?token=%s",
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/comments?token=%s",
|
||||||
repoOwner.Name, repo.Name, issue.Index, token)
|
repoOwner.Name, repo.Name, issue.Index, token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -96,7 +96,7 @@ func TestAPICreateComment(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments?token=%s",
|
||||||
repoOwner.Name, repo.Name, issue.Index, token)
|
repoOwner.Name, repo.Name, issue.Index, token)
|
||||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||||
|
@ -118,7 +118,7 @@ func TestAPIGetComment(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID})
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeReadIssue)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID)
|
||||||
MakeRequest(t, req, http.StatusOK)
|
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)
|
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s", repoOwner.Name, repo.Name, comment.ID, token)
|
||||||
|
@ -146,7 +146,7 @@ func TestAPIEditComment(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
|
||||||
repoOwner.Name, repo.Name, comment.ID, token)
|
repoOwner.Name, repo.Name, comment.ID, token)
|
||||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||||
|
@ -170,7 +170,7 @@ func TestAPIDeleteComment(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
|
||||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
|
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
|
||||||
repoOwner.Name, repo.Name, comment.ID, token)
|
repoOwner.Name, repo.Name, comment.ID, token)
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
|
@ -21,8 +21,8 @@ type makeRequestFunc func(testing.TB, *http.Request, int) *httptest.ResponseReco
|
||||||
func TestGPGKeys(t *testing.T) {
|
func TestGPGKeys(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
tokenWithGPGKeyScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminGPGKey, auth_model.AccessTokenScopeRepo)
|
tokenWithGPGKeyScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
tt := []struct {
|
tt := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -36,7 +36,7 @@ func TestGPGKeys(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "LoggedAsUser2", makeRequest: session.MakeRequest, token: token,
|
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},
|
results: []int{http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden, http.StatusForbidden},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "LoggedAsUser2WithScope", makeRequest: session.MakeRequest, token: tokenWithGPGKeyScope,
|
name: "LoggedAsUser2WithScope", makeRequest: session.MakeRequest, token: tokenWithGPGKeyScope,
|
||||||
|
|
|
@ -53,7 +53,7 @@ func TestHTTPSigPubKey(t *testing.T) {
|
||||||
// Add our public key to user1
|
// Add our public key to user1
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := url.QueryEscape(getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminPublicKey, auth_model.AccessTokenScopeSudo))
|
token := url.QueryEscape(getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser))
|
||||||
keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)
|
keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)
|
||||||
keyType := "ssh-rsa"
|
keyType := "ssh-rsa"
|
||||||
keyContent := "AAAAB3NzaC1yc2EAAAADAQABAAABAQCqOZB5vkRvXFXups1/0StDRdG8plbNSwsWEnNnP4Bvurxa0+z3W9B8GLKnDiLw5MbpbMNyBlpXw13GfuIeciy10DWTz0xUbiy3J3KabCaT36asIw2y7k6Z0jL0UBnrVENwq5/lUbZYqSZ4rRU744wkhh8TULpzM14npQCZwg6aEbG+MwjzddQ72fR+3BPBrKn5dTmmu8rH99O+U+Nuto81Tg7PA+NUupcHOmhdiEGq49plgVFXK98Vks5tiybL4GuzFyWgyX73Dg/QBMn2eMHt1EMv5Gs3i6GFhKKGo4rjDi9qI6PX5oDR4LTNe6cR8td8YhVD8WFZwLLl/vaYyIqd"
|
keyContent := "AAAAB3NzaC1yc2EAAAADAQABAAABAQCqOZB5vkRvXFXups1/0StDRdG8plbNSwsWEnNnP4Bvurxa0+z3W9B8GLKnDiLw5MbpbMNyBlpXw13GfuIeciy10DWTz0xUbiy3J3KabCaT36asIw2y7k6Z0jL0UBnrVENwq5/lUbZYqSZ4rRU744wkhh8TULpzM14npQCZwg6aEbG+MwjzddQ72fR+3BPBrKn5dTmmu8rH99O+U+Nuto81Tg7PA+NUupcHOmhdiEGq49plgVFXK98Vks5tiybL4GuzFyWgyX73Dg/QBMn2eMHt1EMv5Gs3i6GFhKKGo4rjDi9qI6PX5oDR4LTNe6cR8td8YhVD8WFZwLLl/vaYyIqd"
|
||||||
|
@ -69,7 +69,8 @@ func TestHTTPSigPubKey(t *testing.T) {
|
||||||
keyID := ssh.FingerprintSHA256(sshSigner.PublicKey())
|
keyID := ssh.FingerprintSHA256(sshSigner.PublicKey())
|
||||||
|
|
||||||
// create the request
|
// create the request
|
||||||
req = NewRequest(t, "GET", "/api/v1/admin/users")
|
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadAdmin)
|
||||||
|
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/admin/users?token=%s", token))
|
||||||
|
|
||||||
signer, _, err := httpsig.NewSSHSigner(sshSigner, httpsig.DigestSha512, []string{httpsig.RequestTarget, "(created)", "(expires)"}, httpsig.Signature, 10)
|
signer, _, err := httpsig.NewSSHSigner(sshSigner, httpsig.DigestSha512, []string{httpsig.RequestTarget, "(created)", "(expires)"}, httpsig.Signature, 10)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -32,7 +32,7 @@ func TestAPIGetIssueAttachment(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d?token=%s",
|
||||||
repoOwner.Name, repo.Name, issue.Index, attachment.ID, token)
|
repoOwner.Name, repo.Name, issue.Index, attachment.ID, token)
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ func TestAPIListIssueAttachments(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets?token=%s",
|
||||||
repoOwner.Name, repo.Name, issue.Index, token)
|
repoOwner.Name, repo.Name, issue.Index, token)
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ func TestAPICreateIssueAttachment(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets?token=%s",
|
||||||
repoOwner.Name, repo.Name, issue.Index, token)
|
repoOwner.Name, repo.Name, issue.Index, token)
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ func TestAPIEditIssueAttachment(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d?token=%s",
|
||||||
repoOwner.Name, repo.Name, issue.Index, attachment.ID, token)
|
repoOwner.Name, repo.Name, issue.Index, attachment.ID, token)
|
||||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||||
|
@ -133,7 +133,7 @@ func TestAPIDeleteIssueAttachment(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d?token=%s",
|
||||||
repoOwner.Name, repo.Name, issue.Index, attachment.ID, token)
|
repoOwner.Name, repo.Name, issue.Index, attachment.ID, token)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ func TestAPIModifyLabels(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/labels?token=%s", owner.Name, repo.Name, token)
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/labels?token=%s", owner.Name, repo.Name, token)
|
||||||
|
|
||||||
// CreateLabel
|
// CreateLabel
|
||||||
|
@ -97,7 +97,7 @@ func TestAPIAddIssueLabels(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels?token=%s",
|
||||||
repo.OwnerName, repo.Name, issue.Index, token)
|
repo.OwnerName, repo.Name, issue.Index, token)
|
||||||
req := NewRequestWithJSON(t, "POST", urlStr, &api.IssueLabelsOption{
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.IssueLabelsOption{
|
||||||
|
@ -120,7 +120,7 @@ func TestAPIReplaceIssueLabels(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels?token=%s",
|
||||||
owner.Name, repo.Name, issue.Index, token)
|
owner.Name, repo.Name, issue.Index, token)
|
||||||
req := NewRequestWithJSON(t, "PUT", urlStr, &api.IssueLabelsOption{
|
req := NewRequestWithJSON(t, "PUT", urlStr, &api.IssueLabelsOption{
|
||||||
|
@ -144,7 +144,7 @@ func TestAPIModifyOrgLabels(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
user := "user1"
|
user := "user1"
|
||||||
session := loginUser(t, user)
|
session := loginUser(t, user)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeAdminOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteOrganization)
|
||||||
urlStr := fmt.Sprintf("/api/v1/orgs/%s/labels?token=%s", owner.Name, token)
|
urlStr := fmt.Sprintf("/api/v1/orgs/%s/labels?token=%s", owner.Name, token)
|
||||||
|
|
||||||
// CreateLabel
|
// CreateLabel
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestAPIIssuesMilestone(t *testing.T) {
|
||||||
assert.Equal(t, structs.StateOpen, milestone.State())
|
assert.Equal(t, structs.StateOpen, milestone.State())
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
// update values of issue
|
// update values of issue
|
||||||
milestoneState := "closed"
|
milestoneState := "closed"
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestAPIPinIssue(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
// Pin the Issue
|
// Pin the Issue
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/pin?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/pin?token=%s",
|
||||||
|
@ -56,7 +56,7 @@ func TestAPIUnpinIssue(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
// Pin the Issue
|
// Pin the Issue
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/pin?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/pin?token=%s",
|
||||||
|
@ -97,7 +97,7 @@ func TestAPIMoveIssuePin(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
// Pin the first Issue
|
// Pin the first Issue
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/pin?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/pin?token=%s",
|
||||||
|
@ -152,7 +152,7 @@ func TestAPIListPinnedIssues(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
// Pin the Issue
|
// Pin the Issue
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/pin?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/pin?token=%s",
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestAPIIssuesReactions(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/reactions?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/reactions?token=%s",
|
||||||
|
@ -88,7 +88,7 @@ func TestAPICommentReactions(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestAPIListStopWatches(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository, auth_model.AccessTokenScopeReadUser)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/user/stopwatches?token=%s", token)
|
req := NewRequestf(t, "GET", "/api/v1/user/stopwatches?token=%s", token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
var apiWatches []*api.StopWatch
|
var apiWatches []*api.StopWatch
|
||||||
|
@ -52,7 +52,7 @@ func TestAPIStopStopWatches(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
req := NewRequestf(t, "POST", "/api/v1/repos/%s/%s/issues/%d/stopwatch/stop?token=%s", owner.Name, issue.Repo.Name, issue.Index, token)
|
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)
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
@ -68,7 +68,7 @@ func TestAPICancelStopWatches(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/%d/stopwatch/delete?token=%s", owner.Name, issue.Repo.Name, issue.Index, token)
|
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)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
@ -84,7 +84,7 @@ func TestAPIStartStopWatches(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
req := NewRequestf(t, "POST", "/api/v1/repos/%s/%s/issues/%d/stopwatch/start?token=%s", owner.Name, issue.Repo.Name, issue.Index, token)
|
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)
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
|
|
@ -31,7 +31,7 @@ func TestAPIIssueSubscriptions(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue1.PosterID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue1.PosterID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
testSubscription := func(issue *issues_model.Issue, isWatching bool) {
|
testSubscription := func(issue *issues_model.Issue, isWatching bool) {
|
||||||
issueRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
issueRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestAPIListIssues(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
|
||||||
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/issues", owner.Name, repo.Name))
|
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/issues", owner.Name, repo.Name))
|
||||||
|
|
||||||
link.RawQuery = url.Values{"token": {token}, "state": {"all"}}.Encode()
|
link.RawQuery = url.Values{"token": {token}, "state": {"all"}}.Encode()
|
||||||
|
@ -81,7 +81,7 @@ func TestAPICreateIssue(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all&token=%s", owner.Name, repoBefore.Name, token)
|
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{
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{
|
||||||
Body: body,
|
Body: body,
|
||||||
|
@ -117,7 +117,7 @@ func TestAPIEditIssue(t *testing.T) {
|
||||||
assert.Equal(t, api.StateOpen, issueBefore.State())
|
assert.Equal(t, api.StateOpen, issueBefore.State())
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
// update values of issue
|
// update values of issue
|
||||||
issueState := "closed"
|
issueState := "closed"
|
||||||
|
@ -171,7 +171,7 @@ func TestAPIEditIssue(t *testing.T) {
|
||||||
func TestAPISearchIssues(t *testing.T) {
|
func TestAPISearchIssues(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
token := getUserToken(t, "user2")
|
token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadIssue)
|
||||||
|
|
||||||
// as this API was used in the frontend, it uses UI page size
|
// as this API was used in the frontend, it uses UI page size
|
||||||
expectedIssueCount := 16 // from the fixtures
|
expectedIssueCount := 16 // from the fixtures
|
||||||
|
@ -180,7 +180,7 @@ func TestAPISearchIssues(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
link, _ := url.Parse("/api/v1/repos/issues/search")
|
link, _ := url.Parse("/api/v1/repos/issues/search")
|
||||||
query := url.Values{"token": {getUserToken(t, "user1")}}
|
query := url.Values{"token": {getUserToken(t, "user1", auth_model.AccessTokenScopeReadIssue)}}
|
||||||
var apiIssues []*api.Issue
|
var apiIssues []*api.Issue
|
||||||
|
|
||||||
link.RawQuery = query.Encode()
|
link.RawQuery = query.Encode()
|
||||||
|
@ -278,7 +278,7 @@ func TestAPISearchIssuesWithLabels(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
link, _ := url.Parse("/api/v1/repos/issues/search")
|
link, _ := url.Parse("/api/v1/repos/issues/search")
|
||||||
query := url.Values{"token": {getUserToken(t, "user1")}}
|
query := url.Values{"token": {getUserToken(t, "user1", auth_model.AccessTokenScopeReadIssue)}}
|
||||||
var apiIssues []*api.Issue
|
var apiIssues []*api.Issue
|
||||||
|
|
||||||
link.RawQuery = query.Encode()
|
link.RawQuery = query.Encode()
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestAPIGetTrackedTimes(t *testing.T) {
|
||||||
assert.NoError(t, issue2.LoadRepo(db.DefaultContext))
|
assert.NoError(t, issue2.LoadRepo(db.DefaultContext))
|
||||||
|
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/times?token=%s", user2.Name, issue2.Repo.Name, issue2.Index, token)
|
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)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -71,7 +71,7 @@ func TestAPIDeleteTrackedTime(t *testing.T) {
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
// Deletion not allowed
|
// 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)
|
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)
|
||||||
|
@ -106,7 +106,7 @@ func TestAPIAddTrackedTimes(t *testing.T) {
|
||||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
session := loginUser(t, admin.Name)
|
session := loginUser(t, admin.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/times?token=%s", user2.Name, issue2.Repo.Name, issue2.Index, token)
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/times?token=%s", user2.Name, issue2.Repo.Name, issue2.Index, token)
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", repoOwner.Name, repo.Name, token)
|
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", repoOwner.Name, repo.Name, token)
|
||||||
rawKeyBody := api.CreateKeyOption{
|
rawKeyBody := api.CreateKeyOption{
|
||||||
Title: "read-only",
|
Title: "read-only",
|
||||||
|
@ -80,7 +80,7 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", repoOwner.Name, repo.Name, token)
|
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", repoOwner.Name, repo.Name, token)
|
||||||
rawKeyBody := api.CreateKeyOption{
|
rawKeyBody := api.CreateKeyOption{
|
||||||
Title: "read-write",
|
Title: "read-write",
|
||||||
|
@ -104,7 +104,7 @@ func TestCreateUserKey(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := url.QueryEscape(getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminPublicKey))
|
token := url.QueryEscape(getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser))
|
||||||
keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)
|
keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)
|
||||||
keyType := "ssh-rsa"
|
keyType := "ssh-rsa"
|
||||||
keyContent := "AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM="
|
keyContent := "AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cn+iXnA4KvcQYSV88vGn0Yi91vG47t1P7okprVmhNTkipNRIHWr6WdCO4VDr/cvsRkuVJAsLO2enwjGWWueOO6BodiBgyAOZ/5t5nJNMCNuLGT5UIo/RI1b0WRQwxEZTRjt6mFNw6lH14wRd8ulsr9toSWBPMOGWoYs1PDeDL0JuTjL+tr1SZi/EyxCngpYszKdXllJEHyI79KQgeD0Vt3pTrkbNVTOEcCNqZePSVmUH8X8Vhugz3bnE0/iE9Pb5fkWO9c4AnM1FgI/8Bvp27Fw2ShryIXuR6kKvUqhVMTuOSDHwu6A8jLE5Owt3GAYugDpDYuwTVNGrHLXKpPzrGGPE/jPmaLCMZcsdkec95dYeU3zKODEm8UQZFhmJmDeWVJ36nGrGZHL4J5aTTaeFUJmmXDaJYiJ+K2/ioKgXqnXvltu0A9R8/LGy4nrTJRr4JMLuJFoUXvGm1gXQ70w2LSpk6yl71RNC0hCtsBe8BP8IhYCM0EP5jh7eCMQZNvM="
|
||||||
|
@ -168,7 +168,7 @@ func TestCreateUserKey(t *testing.T) {
|
||||||
|
|
||||||
// Now login as user 2
|
// Now login as user 2
|
||||||
session2 := loginUser(t, "user2")
|
session2 := loginUser(t, "user2")
|
||||||
token2 := url.QueryEscape(getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeAdminPublicKey))
|
token2 := url.QueryEscape(getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeWriteUser))
|
||||||
|
|
||||||
// Should find key even though not ours, but we shouldn't know whose it is
|
// 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)
|
fingerprintURL = fmt.Sprintf("/api/v1/user/keys?token=%s&fingerprint=%s", token2, newPublicKey.Fingerprint)
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestAPINotification(t *testing.T) {
|
||||||
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
||||||
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeNotification)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteNotification, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// -- GET /notifications --
|
// -- GET /notifications --
|
||||||
// test filter
|
// test filter
|
||||||
|
@ -146,7 +146,7 @@ func TestAPINotificationPUT(t *testing.T) {
|
||||||
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
||||||
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeNotification)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteNotification)
|
||||||
|
|
||||||
// Check notifications are as expected
|
// Check notifications are as expected
|
||||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?all=true&token=%s", token))
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?all=true&token=%s", token))
|
||||||
|
|
|
@ -55,7 +55,7 @@ func testAPICreateOAuth2Application(t *testing.T) {
|
||||||
func testAPIListOAuth2Applications(t *testing.T) {
|
func testAPIListOAuth2Applications(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadApplication)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
existApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
existApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
||||||
UID: user.ID,
|
UID: user.ID,
|
||||||
|
@ -86,7 +86,7 @@ func testAPIListOAuth2Applications(t *testing.T) {
|
||||||
func testAPIDeleteOAuth2Application(t *testing.T) {
|
func testAPIDeleteOAuth2Application(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteApplication)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
oldApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
oldApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
||||||
UID: user.ID,
|
UID: user.ID,
|
||||||
|
@ -107,7 +107,7 @@ func testAPIDeleteOAuth2Application(t *testing.T) {
|
||||||
func testAPIGetOAuth2Application(t *testing.T) {
|
func testAPIGetOAuth2Application(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadApplication)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
existApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
existApp := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{
|
||||||
UID: user.ID,
|
UID: user.ID,
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
|
|
||||||
func TestAPIOrgCreate(t *testing.T) {
|
func TestAPIOrgCreate(t *testing.T) {
|
||||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrg)
|
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
|
||||||
|
|
||||||
org := api.CreateOrgOption{
|
org := api.CreateOrgOption{
|
||||||
UserName: "user1_org",
|
UserName: "user1_org",
|
||||||
|
@ -100,7 +100,7 @@ func TestAPIOrgEdit(t *testing.T) {
|
||||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
|
||||||
org := api.EditOrgOption{
|
org := api.EditOrgOption{
|
||||||
FullName: "User3 organization new full name",
|
FullName: "User3 organization new full name",
|
||||||
Description: "A new description",
|
Description: "A new description",
|
||||||
|
@ -127,7 +127,7 @@ func TestAPIOrgEditBadVisibility(t *testing.T) {
|
||||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
|
||||||
org := api.EditOrgOption{
|
org := api.EditOrgOption{
|
||||||
FullName: "User3 organization new full name",
|
FullName: "User3 organization new full name",
|
||||||
Description: "A new description",
|
Description: "A new description",
|
||||||
|
@ -162,7 +162,7 @@ func TestAPIOrgDeny(t *testing.T) {
|
||||||
func TestAPIGetAll(t *testing.T) {
|
func TestAPIGetAll(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeReadOrg)
|
token := getUserToken(t, "user1", auth_model.AccessTokenScopeReadOrganization)
|
||||||
|
|
||||||
// accessing with a token will return all orgs
|
// accessing with a token will return all orgs
|
||||||
req := NewRequestf(t, "GET", "/api/v1/orgs?token=%s", token)
|
req := NewRequestf(t, "GET", "/api/v1/orgs?token=%s", token)
|
||||||
|
@ -186,7 +186,7 @@ func TestAPIGetAll(t *testing.T) {
|
||||||
|
|
||||||
func TestAPIOrgSearchEmptyTeam(t *testing.T) {
|
func TestAPIOrgSearchEmptyTeam(t *testing.T) {
|
||||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
token := getUserToken(t, "user1", auth_model.AccessTokenScopeAdminOrg)
|
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
|
||||||
orgName := "org_with_empty_team"
|
orgName := "org_with_empty_team"
|
||||||
|
|
||||||
// create org
|
// create org
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestPackageNpm(t *testing.T) {
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
token := fmt.Sprintf("Bearer %s", getTokenForLoggedInUser(t, loginUser(t, user.Name), auth_model.AccessTokenScopePackage))
|
token := fmt.Sprintf("Bearer %s", getTokenForLoggedInUser(t, loginUser(t, user.Name), auth_model.AccessTokenScopeWritePackage))
|
||||||
|
|
||||||
packageName := "@scope/test-package"
|
packageName := "@scope/test-package"
|
||||||
packageVersion := "1.0.1-pre"
|
packageVersion := "1.0.1-pre"
|
||||||
|
|
|
@ -75,7 +75,7 @@ func TestPackageNuGet(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
token := getUserToken(t, user.Name, auth_model.AccessTokenScopePackage)
|
token := getUserToken(t, user.Name, auth_model.AccessTokenScopeWritePackage)
|
||||||
|
|
||||||
packageName := "test.package"
|
packageName := "test.package"
|
||||||
packageVersion := "1.0.3"
|
packageVersion := "1.0.3"
|
||||||
|
|
|
@ -31,7 +31,7 @@ func TestPackagePub(t *testing.T) {
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
token := "Bearer " + getUserToken(t, user.Name, auth_model.AccessTokenScopePackage)
|
token := "Bearer " + getUserToken(t, user.Name, auth_model.AccessTokenScopeWritePackage)
|
||||||
|
|
||||||
packageName := "test_package"
|
packageName := "test_package"
|
||||||
packageVersion := "1.0.1"
|
packageVersion := "1.0.1"
|
||||||
|
|
|
@ -34,7 +34,7 @@ func TestPackageAPI(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
tokenReadPackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadPackage)
|
tokenReadPackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadPackage)
|
||||||
tokenDeletePackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeDeletePackage)
|
tokenDeletePackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWritePackage)
|
||||||
|
|
||||||
packageName := "test-package"
|
packageName := "test-package"
|
||||||
packageVersion := "1.0.3"
|
packageVersion := "1.0.3"
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestPackageVagrant(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
token := "Bearer " + getUserToken(t, user.Name, auth_model.AccessTokenScopePackage)
|
token := "Bearer " + getUserToken(t, user.Name, auth_model.AccessTokenScopeWritePackage)
|
||||||
|
|
||||||
packageName := "test_package"
|
packageName := "test_package"
|
||||||
packageVersion := "1.0.1"
|
packageVersion := "1.0.1"
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestAPIPullReview(t *testing.T) {
|
||||||
|
|
||||||
// test ListPullReviews
|
// test ListPullReviews
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/%s/pulls/%d/reviews?token=%s", repo.OwnerName, repo.Name, pullIssue.Index, token)
|
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)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ func TestAPIPullReviewRequest(t *testing.T) {
|
||||||
|
|
||||||
// Test add Review Request
|
// Test add Review Request
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
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{
|
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"},
|
Reviewers: []string{"user4@example.com", "user8"},
|
||||||
})
|
})
|
||||||
|
@ -251,7 +251,7 @@ func TestAPIPullReviewRequest(t *testing.T) {
|
||||||
|
|
||||||
// Test Remove Review Request
|
// Test Remove Review Request
|
||||||
session2 := loginUser(t, "user4")
|
session2 := loginUser(t, "user4")
|
||||||
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeRepo)
|
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
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{
|
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"},
|
Reviewers: []string{"user4"},
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestAPIViewPulls(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
ctx := NewAPITestContext(t, "user2", repo.Name, auth_model.AccessTokenScopeRepo)
|
ctx := NewAPITestContext(t, "user2", repo.Name, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/pulls?state=all&token="+ctx.Token, owner.Name, repo.Name)
|
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)
|
resp := ctx.Session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -75,7 +75,7 @@ func TestAPIMergePullWIP(t *testing.T) {
|
||||||
assert.Contains(t, pr.Issue.Title, setting.Repository.PullRequest.WorkInProgressPrefixes[0])
|
assert.Contains(t, pr.Issue.Title, setting.Repository.PullRequest.WorkInProgressPrefixes[0])
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
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{
|
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,
|
MergeMessageField: pr.Issue.Title,
|
||||||
Do: string(repo_model.MergeStyleMerge),
|
Do: string(repo_model.MergeStyleMerge),
|
||||||
|
@ -94,7 +94,7 @@ func TestAPICreatePullSuccess(t *testing.T) {
|
||||||
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner11.Name)
|
session := loginUser(t, owner11.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
|
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),
|
Head: fmt.Sprintf("%s:master", owner11.Name),
|
||||||
Base: "master",
|
Base: "master",
|
||||||
|
@ -114,7 +114,7 @@ func TestAPICreatePullWithFieldsSuccess(t *testing.T) {
|
||||||
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner11.Name)
|
session := loginUser(t, owner11.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
opts := &api.CreatePullRequestOption{
|
opts := &api.CreatePullRequestOption{
|
||||||
Head: fmt.Sprintf("%s:master", owner11.Name),
|
Head: fmt.Sprintf("%s:master", owner11.Name),
|
||||||
|
@ -151,7 +151,7 @@ func TestAPICreatePullWithFieldsFailure(t *testing.T) {
|
||||||
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
owner11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo11.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner11.Name)
|
session := loginUser(t, owner11.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
opts := &api.CreatePullRequestOption{
|
opts := &api.CreatePullRequestOption{
|
||||||
Head: fmt.Sprintf("%s:master", owner11.Name),
|
Head: fmt.Sprintf("%s:master", owner11.Name),
|
||||||
|
@ -181,7 +181,7 @@ func TestAPIEditPull(t *testing.T) {
|
||||||
owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
|
owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner10.Name)
|
session := loginUser(t, owner10.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
|
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
|
||||||
Head: "develop",
|
Head: "develop",
|
||||||
Base: "master",
|
Base: "master",
|
||||||
|
|
|
@ -25,7 +25,7 @@ func TestAPIListReleases(t *testing.T) {
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeRepo)
|
token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/releases", user2.Name, repo.Name))
|
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/releases", user2.Name, repo.Name))
|
||||||
link.RawQuery = url.Values{"token": {token}}.Encode()
|
link.RawQuery = url.Values{"token": {token}}.Encode()
|
||||||
|
@ -101,7 +101,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
session := loginUser(t, owner.LowerName)
|
session := loginUser(t, owner.LowerName)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath())
|
gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -153,7 +153,7 @@ func TestAPICreateReleaseToDefaultBranch(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
session := loginUser(t, owner.LowerName)
|
session := loginUser(t, owner.LowerName)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", "", "v0.0.1", "test")
|
createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", "", "v0.0.1", "test")
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
session := loginUser(t, owner.LowerName)
|
session := loginUser(t, owner.LowerName)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath())
|
gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -232,7 +232,7 @@ func TestAPIDeleteReleaseByTagName(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
session := loginUser(t, owner.LowerName)
|
session := loginUser(t, owner.LowerName)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test")
|
createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test")
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ func TestAPIDownloadArchive(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
session := loginUser(t, user2.LowerName)
|
session := loginUser(t, user2.LowerName)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.zip", user2.Name, repo.Name))
|
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.zip", user2.Name, repo.Name))
|
||||||
link.RawQuery = url.Values{"token": {token}}.Encode()
|
link.RawQuery = url.Values{"token": {token}}.Encode()
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) {
|
||||||
user10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 10})
|
user10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 10})
|
||||||
user11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 11})
|
user11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 11})
|
||||||
|
|
||||||
testCtx := NewAPITestContext(t, repo2Owner.Name, repo2.Name, auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, repo2Owner.Name, repo2.Name, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
t.Run("RepoOwnerShouldBeOwner", func(t *testing.T) {
|
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)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, repo2Owner.Name, testCtx.Token)
|
||||||
|
@ -85,7 +85,7 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) {
|
||||||
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
|
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
|
||||||
|
|
||||||
_session := loginUser(t, user5.Name)
|
_session := loginUser(t, user5.Name)
|
||||||
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeRepo)
|
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user5.Name, _testCtx.Token)
|
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)
|
resp := _session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -100,7 +100,7 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) {
|
||||||
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
|
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
|
||||||
|
|
||||||
_session := loginUser(t, user5.Name)
|
_session := loginUser(t, user5.Name)
|
||||||
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeRepo)
|
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user5.Name, _testCtx.Token)
|
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)
|
resp := _session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -116,7 +116,7 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) {
|
||||||
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user11.Name, perm.AccessModeRead))
|
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user11.Name, perm.AccessModeRead))
|
||||||
|
|
||||||
_session := loginUser(t, user10.Name)
|
_session := loginUser(t, user10.Name)
|
||||||
_testCtx := NewAPITestContext(t, user10.Name, repo2.Name, auth_model.AccessTokenScopeRepo)
|
_testCtx := NewAPITestContext(t, user10.Name, repo2.Name, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user11.Name, _testCtx.Token)
|
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)
|
resp := _session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
|
@ -147,10 +147,10 @@ func TestAPIRepoEdit(t *testing.T) {
|
||||||
|
|
||||||
// Get user2's token
|
// Get user2's token
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
// Get user4's token
|
// Get user4's token
|
||||||
session = loginUser(t, user4.Name)
|
session = loginUser(t, user4.Name)
|
||||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// Test editing a repo1 which user2 owns, changing name and many properties
|
// Test editing a repo1 which user2 owns, changing name and many properties
|
||||||
origRepoEditOption := getRepoEditOptionFromRepo(repo1)
|
origRepoEditOption := getRepoEditOptionFromRepo(repo1)
|
||||||
|
|
|
@ -151,10 +151,10 @@ func TestAPICreateFile(t *testing.T) {
|
||||||
|
|
||||||
// Get user2's token
|
// Get user2's token
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
// Get user4's token
|
// Get user4's token
|
||||||
session = loginUser(t, user4.Name)
|
session = loginUser(t, user4.Name)
|
||||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
// Test creating a file in repo1 which user2 owns, try both with branch and empty branch
|
// Test creating a file in repo1 which user2 owns, try both with branch and empty branch
|
||||||
for _, branch := range [...]string{
|
for _, branch := range [...]string{
|
||||||
|
@ -280,7 +280,7 @@ func TestAPICreateFile(t *testing.T) {
|
||||||
MakeRequest(t, req, http.StatusForbidden)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
|
||||||
// Test creating a file in an empty repository
|
// Test creating a file in an empty repository
|
||||||
doAPICreateRepository(NewAPITestContext(t, "user2", "empty-repo", auth_model.AccessTokenScopeRepo), true)(t)
|
doAPICreateRepository(NewAPITestContext(t, "user2", "empty-repo", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser), true)(t)
|
||||||
createFileOptions = getCreateFileOptions()
|
createFileOptions = getCreateFileOptions()
|
||||||
fileID++
|
fileID++
|
||||||
treePath = fmt.Sprintf("new/file%d.txt", fileID)
|
treePath = fmt.Sprintf("new/file%d.txt", fileID)
|
||||||
|
|
|
@ -49,10 +49,10 @@ func TestAPIDeleteFile(t *testing.T) {
|
||||||
|
|
||||||
// Get user2's token
|
// Get user2's token
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
// Get user4's token
|
// Get user4's token
|
||||||
session = loginUser(t, user4.Name)
|
session = loginUser(t, user4.Name)
|
||||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// Test deleting a file in repo1 which user2 owns, try both with branch and empty branch
|
// Test deleting a file in repo1 which user2 owns, try both with branch and empty branch
|
||||||
for _, branch := range [...]string{
|
for _, branch := range [...]string{
|
||||||
|
|
|
@ -25,7 +25,7 @@ func TestAPIGetRawFileOrLFS(t *testing.T) {
|
||||||
|
|
||||||
// Test with LFS
|
// Test with LFS
|
||||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||||
httpContext := NewAPITestContext(t, "user2", "repo-lfs-test", auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeDeleteRepo)
|
httpContext := NewAPITestContext(t, "user2", "repo-lfs-test", auth_model.AccessTokenScopeWriteRepository)
|
||||||
doAPICreateRepository(httpContext, false, func(t *testing.T, repository api.Repository) {
|
doAPICreateRepository(httpContext, false, func(t *testing.T, repository api.Repository) {
|
||||||
u.Path = httpContext.GitPath()
|
u.Path = httpContext.GitPath()
|
||||||
dstPath := t.TempDir()
|
dstPath := t.TempDir()
|
||||||
|
|
|
@ -117,10 +117,10 @@ func TestAPIUpdateFile(t *testing.T) {
|
||||||
|
|
||||||
// Get user2's token
|
// Get user2's token
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
// Get user4's token
|
// Get user4's token
|
||||||
session = loginUser(t, user4.Name)
|
session = loginUser(t, user4.Name)
|
||||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// Test updating a file in repo1 which user2 owns, try both with branch and empty branch
|
// Test updating a file in repo1 which user2 owns, try both with branch and empty branch
|
||||||
for _, branch := range [...]string{
|
for _, branch := range [...]string{
|
||||||
|
|
|
@ -72,10 +72,10 @@ func TestAPIChangeFiles(t *testing.T) {
|
||||||
|
|
||||||
// Get user2's token
|
// Get user2's token
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
// Get user4's token
|
// Get user4's token
|
||||||
session = loginUser(t, user4.Name)
|
session = loginUser(t, user4.Name)
|
||||||
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// Test changing files in repo1 which user2 owns, try both with branch and empty branch
|
// Test changing files in repo1 which user2 owns, try both with branch and empty branch
|
||||||
for _, branch := range [...]string{
|
for _, branch := range [...]string{
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -64,10 +65,10 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
|
||||||
|
|
||||||
// Get user2's token
|
// Get user2's token
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token2 := getTokenForLoggedInUser(t, session)
|
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
// Get user4's token
|
// Get user4's token
|
||||||
session = loginUser(t, user4.Name)
|
session = loginUser(t, user4.Name)
|
||||||
token4 := getTokenForLoggedInUser(t, session)
|
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Make a new branch in repo1
|
// Make a new branch in repo1
|
||||||
newBranch := "test_branch"
|
newBranch := "test_branch"
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -66,10 +67,10 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
|
||||||
|
|
||||||
// Get user2's token
|
// Get user2's token
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token2 := getTokenForLoggedInUser(t, session)
|
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
// Get user4's token
|
// Get user4's token
|
||||||
session = loginUser(t, user4.Name)
|
session = loginUser(t, user4.Name)
|
||||||
token4 := getTokenForLoggedInUser(t, session)
|
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Make a new branch in repo1
|
// Make a new branch in repo1
|
||||||
newBranch := "test_branch"
|
newBranch := "test_branch"
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -31,7 +32,7 @@ func TestAPIReposGitBlobs(t *testing.T) {
|
||||||
|
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Test a public repo that anyone can GET the blob of
|
// Test a public repo that anyone can GET the blob of
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/blobs/%s", user2.Name, repo1.Name, repo1ReadmeSHA)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/blobs/%s", user2.Name, repo1.Name, repo1ReadmeSHA)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -28,7 +29,7 @@ func TestAPIReposGitCommits(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// check invalid requests
|
// check invalid requests
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/git/commits/12345?token="+token, user.Name)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/git/commits/12345?token="+token, user.Name)
|
||||||
|
@ -56,7 +57,7 @@ func TestAPIReposGitCommitList(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Test getting commits (Page 1)
|
// Test getting commits (Page 1)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo20/commits?token="+token+"¬=master&sha=remove-files-a", user.Name)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo20/commits?token="+token+"¬=master&sha=remove-files-a", user.Name)
|
||||||
|
@ -79,7 +80,7 @@ func TestAPIReposGitCommitListNotMaster(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Test getting commits (Page 1)
|
// Test getting commits (Page 1)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?token="+token, user.Name)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?token="+token, user.Name)
|
||||||
|
@ -104,7 +105,7 @@ func TestAPIReposGitCommitListPage2Empty(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Test getting commits (Page=2)
|
// Test getting commits (Page=2)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?token="+token+"&page=2", user.Name)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?token="+token+"&page=2", user.Name)
|
||||||
|
@ -121,7 +122,7 @@ func TestAPIReposGitCommitListDifferentBranch(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Test getting commits (Page=1, Branch=good-sign)
|
// Test getting commits (Page=1, Branch=good-sign)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?token="+token+"&sha=good-sign", user.Name)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?token="+token+"&sha=good-sign", user.Name)
|
||||||
|
@ -140,7 +141,7 @@ func TestAPIReposGitCommitListWithoutSelectFields(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Test getting commits without files, verification, and stats
|
// Test getting commits without files, verification, and stats
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?token="+token+"&sha=good-sign&stat=false&files=false&verification=false", user.Name)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?token="+token+"&sha=good-sign&stat=false&files=false&verification=false", user.Name)
|
||||||
|
@ -161,7 +162,7 @@ func TestDownloadCommitDiffOrPatch(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Test getting diff
|
// Test getting diff
|
||||||
reqDiff := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/git/commits/f27c2b2b03dcab38beaf89b0ab4ff61f6de63441.diff?token="+token, user.Name)
|
reqDiff := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/git/commits/f27c2b2b03dcab38beaf89b0ab4ff61f6de63441.diff?token="+token, user.Name)
|
||||||
|
@ -183,7 +184,7 @@ func TestGetFileHistory(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?path=readme.md&token="+token+"&sha=good-sign", user.Name)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/commits?path=readme.md&token="+token+"&sha=good-sign", user.Name)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -203,7 +204,7 @@ func TestGetFileHistoryNotOnMaster(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo20/commits?path=test.csv&token="+token+"&sha=add-csv¬=master", user.Name)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo20/commits?path=test.csv&token="+token+"&sha=add-csv¬=master", user.Name)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
|
@ -31,7 +31,7 @@ func TestAPIListGitHooks(t *testing.T) {
|
||||||
|
|
||||||
// user1 is an admin user
|
// user1 is an admin user
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -57,7 +57,7 @@ func TestAPIListGitHooksNoHooks(t *testing.T) {
|
||||||
|
|
||||||
// user1 is an admin user
|
// user1 is an admin user
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -77,7 +77,7 @@ func TestAPIListGitHooksNoAccess(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
MakeRequest(t, req, http.StatusForbidden)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
@ -91,7 +91,7 @@ func TestAPIGetGitHook(t *testing.T) {
|
||||||
|
|
||||||
// user1 is an admin user
|
// user1 is an admin user
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -108,7 +108,7 @@ func TestAPIGetGitHookNoAccess(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
MakeRequest(t, req, http.StatusForbidden)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
@ -122,7 +122,7 @@ func TestAPIEditGitHook(t *testing.T) {
|
||||||
|
|
||||||
// user1 is an admin user
|
// user1 is an admin user
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
|
@ -151,7 +151,7 @@ func TestAPIEditGitHookNoAccess(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
req := NewRequestWithJSON(t, "PATCH", urlStr, &api.EditGitHookOption{
|
req := NewRequestWithJSON(t, "PATCH", urlStr, &api.EditGitHookOption{
|
||||||
|
@ -168,7 +168,7 @@ func TestAPIDeleteGitHook(t *testing.T) {
|
||||||
|
|
||||||
// user1 is an admin user
|
// user1 is an admin user
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
|
@ -190,7 +190,7 @@ func TestAPIDeleteGitHookNoAccess(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/hooks/git/pre-receive?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
MakeRequest(t, req, http.StatusForbidden)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -20,7 +21,7 @@ func TestAPIReposGitNotes(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// check invalid requests
|
// check invalid requests
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/git/notes/12345?token=%s", user.Name, token)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/git/notes/12345?token=%s", user.Name, token)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
@ -17,7 +18,7 @@ func TestAPIReposGitRefs(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
for _, ref := range [...]string{
|
for _, ref := range [...]string{
|
||||||
"refs/heads/master", // Branch
|
"refs/heads/master", // Branch
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestAPIGitTags(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Set up git config for the tagger
|
// Set up git config for the tagger
|
||||||
_ = git.NewCommand(git.DefaultContext, "config", "user.name").AddDynamicArguments(user.Name).Run(&git.RunOpts{Dir: repo.RepoPath()})
|
_ = git.NewCommand(git.DefaultContext, "config", "user.name").AddDynamicArguments(user.Name).Run(&git.RunOpts{Dir: repo.RepoPath()})
|
||||||
|
@ -70,7 +70,7 @@ func TestAPIDeleteTagByName(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
session := loginUser(t, owner.LowerName)
|
session := loginUser(t, owner.LowerName)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/tags/delete-tag?token=%s",
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/tags/delete-tag?token=%s",
|
||||||
owner.Name, repo.Name, token)
|
owner.Name, repo.Name, token)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -28,7 +29,7 @@ func TestAPIReposGitTrees(t *testing.T) {
|
||||||
|
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
// Test a public repo that anyone can GET the tree of
|
// Test a public repo that anyone can GET the tree of
|
||||||
for _, ref := range [...]string{
|
for _, ref := range [...]string{
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestAPICreateHook(t *testing.T) {
|
||||||
|
|
||||||
// user1 is an admin user
|
// user1 is an admin user
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepoHook)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
completeURL := func(lastSegment string) string {
|
completeURL := func(lastSegment string) string {
|
||||||
return fmt.Sprintf("/api/v1/repos/%s/%s/%s?token=%s", owner.Name, repo.Name, lastSegment, token)
|
return fmt.Sprintf("/api/v1/repos/%s/%s/%s?token=%s", owner.Name, repo.Name, lastSegment, token)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ func TestAPIRepoLFSMigrateLocal(t *testing.T) {
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+token, &api.MigrateRepoOptions{
|
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+token, &api.MigrateRepoOptions{
|
||||||
CloneAddr: path.Join(setting.RepoRootPath, "migration/lfs-test.git"),
|
CloneAddr: path.Join(setting.RepoRootPath, "migration/lfs-test.git"),
|
||||||
|
|
|
@ -60,7 +60,7 @@ func TestAPILFSMediaType(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createLFSTestRepository(t *testing.T, name string) *repo_model.Repository {
|
func createLFSTestRepository(t *testing.T, name string) *repo_model.Repository {
|
||||||
ctx := NewAPITestContext(t, "user2", "lfs-"+name+"-repo", auth_model.AccessTokenScopeRepo)
|
ctx := NewAPITestContext(t, "user2", "lfs-"+name+"-repo", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateRepo", doAPICreateRepository(ctx, false))
|
t.Run("CreateRepo", doAPICreateRepository(ctx, false))
|
||||||
|
|
||||||
repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "lfs-"+name+"-repo")
|
repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "lfs-"+name+"-repo")
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestAPIReposRaw(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
|
|
||||||
for _, ref := range [...]string{
|
for _, ref := range [...]string{
|
||||||
"master", // Branch
|
"master", // Branch
|
||||||
|
|
|
@ -23,7 +23,7 @@ func TestAPIRepoTags(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
// Login as User2.
|
// Login as User2.
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
repoName := "repo1"
|
repoName := "repo1"
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestAPIRepoTeams(t *testing.T) {
|
||||||
// user4
|
// user4
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// ListTeams
|
// ListTeams
|
||||||
url := fmt.Sprintf("/api/v1/repos/%s/teams?token=%s", publicOrgRepo.FullName(), token)
|
url := fmt.Sprintf("/api/v1/repos/%s/teams?token=%s", publicOrgRepo.FullName(), token)
|
||||||
|
@ -68,7 +68,7 @@ func TestAPIRepoTeams(t *testing.T) {
|
||||||
// AddTeam with user2
|
// AddTeam with user2
|
||||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
session = loginUser(t, user.Name)
|
session = loginUser(t, user.Name)
|
||||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
url = fmt.Sprintf("/api/v1/repos/%s/teams/%s?token=%s", publicOrgRepo.FullName(), "team1", token)
|
url = fmt.Sprintf("/api/v1/repos/%s/teams/%s?token=%s", publicOrgRepo.FullName(), "team1", token)
|
||||||
req = NewRequest(t, "PUT", url)
|
req = NewRequest(t, "PUT", url)
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
|
@ -189,7 +189,7 @@ func TestAPISearchRepo(t *testing.T) {
|
||||||
if userToLogin != nil && userToLogin.ID > 0 {
|
if userToLogin != nil && userToLogin.ID > 0 {
|
||||||
testName = fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
testName = fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
||||||
session := loginUser(t, userToLogin.Name)
|
session := loginUser(t, userToLogin.Name)
|
||||||
token = getTokenForLoggedInUser(t, session)
|
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
userID = userToLogin.ID
|
userID = userToLogin.ID
|
||||||
} else {
|
} else {
|
||||||
testName = "AnonymousUser"
|
testName = "AnonymousUser"
|
||||||
|
@ -295,7 +295,7 @@ func TestAPIOrgRepos(t *testing.T) {
|
||||||
for userToLogin, expected := range expectedResults {
|
for userToLogin, expected := range expectedResults {
|
||||||
testName := fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
testName := fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
||||||
session := loginUser(t, userToLogin.Name)
|
session := loginUser(t, userToLogin.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrganization)
|
||||||
|
|
||||||
t.Run(testName, func(t *testing.T) {
|
t.Run(testName, func(t *testing.T) {
|
||||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
|
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
|
||||||
|
@ -317,7 +317,7 @@ func TestAPIGetRepoByIDUnauthorized(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repositories/2?token="+token)
|
req := NewRequestf(t, "GET", "/api/v1/repositories/2?token="+token)
|
||||||
MakeRequest(t, req, http.StatusNotFound)
|
MakeRequest(t, req, http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,7 @@ func TestAPIRepoMigrate(t *testing.T) {
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+token, &api.MigrateRepoOptions{
|
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+token, &api.MigrateRepoOptions{
|
||||||
CloneAddr: testCase.cloneURL,
|
CloneAddr: testCase.cloneURL,
|
||||||
RepoOwnerID: testCase.userID,
|
RepoOwnerID: testCase.userID,
|
||||||
|
@ -371,7 +371,7 @@ func TestAPIRepoMigrateConflict(t *testing.T) {
|
||||||
|
|
||||||
func testAPIRepoMigrateConflict(t *testing.T, u *url.URL) {
|
func testAPIRepoMigrateConflict(t *testing.T, u *url.URL) {
|
||||||
username := "user2"
|
username := "user2"
|
||||||
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeRepo)
|
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
u.Path = baseAPITestContext.GitPath()
|
u.Path = baseAPITestContext.GitPath()
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ func TestAPIMirrorSyncNonMirrorRepo(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
var repo api.Repository
|
var repo api.Repository
|
||||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1")
|
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1")
|
||||||
|
@ -438,7 +438,7 @@ func TestAPIOrgRepoCreate(t *testing.T) {
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos?token="+token, testCase.orgName), &api.CreateRepoOption{
|
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos?token="+token, testCase.orgName), &api.CreateRepoOption{
|
||||||
Name: testCase.repoName,
|
Name: testCase.repoName,
|
||||||
})
|
})
|
||||||
|
@ -452,7 +452,7 @@ func TestAPIRepoCreateConflict(t *testing.T) {
|
||||||
|
|
||||||
func testAPIRepoCreateConflict(t *testing.T, u *url.URL) {
|
func testAPIRepoCreateConflict(t *testing.T, u *url.URL) {
|
||||||
username := "user2"
|
username := "user2"
|
||||||
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeRepo)
|
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
u.Path = baseAPITestContext.GitPath()
|
u.Path = baseAPITestContext.GitPath()
|
||||||
|
|
||||||
|
@ -502,7 +502,7 @@ func TestAPIRepoTransfer(t *testing.T) {
|
||||||
// create repo to move
|
// create repo to move
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
repoName := "moveME"
|
repoName := "moveME"
|
||||||
apiRepo := new(api.Repository)
|
apiRepo := new(api.Repository)
|
||||||
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/repos?token=%s", token), &api.CreateRepoOption{
|
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/repos?token=%s", token), &api.CreateRepoOption{
|
||||||
|
@ -520,7 +520,7 @@ func TestAPIRepoTransfer(t *testing.T) {
|
||||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID})
|
||||||
session = loginUser(t, user.Name)
|
session = loginUser(t, user.Name)
|
||||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer?token=%s", repo.OwnerName, repo.Name, token), &api.TransferRepoOption{
|
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer?token=%s", repo.OwnerName, repo.Name, token), &api.TransferRepoOption{
|
||||||
NewOwner: testCase.newOwner,
|
NewOwner: testCase.newOwner,
|
||||||
TeamIDs: testCase.teams,
|
TeamIDs: testCase.teams,
|
||||||
|
@ -537,7 +537,7 @@ func transfer(t *testing.T) *repo_model.Repository {
|
||||||
// create repo to move
|
// create repo to move
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
repoName := "moveME"
|
repoName := "moveME"
|
||||||
apiRepo := new(api.Repository)
|
apiRepo := new(api.Repository)
|
||||||
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/repos?token=%s", token), &api.CreateRepoOption{
|
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/repos?token=%s", token), &api.CreateRepoOption{
|
||||||
|
@ -567,7 +567,7 @@ func TestAPIAcceptTransfer(t *testing.T) {
|
||||||
|
|
||||||
// try to accept with not authorized user
|
// try to accept with not authorized user
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
req := NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token))
|
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)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
|
||||||
|
@ -577,7 +577,7 @@ func TestAPIAcceptTransfer(t *testing.T) {
|
||||||
|
|
||||||
// accept transfer
|
// accept transfer
|
||||||
session = loginUser(t, "user4")
|
session = loginUser(t, "user4")
|
||||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/accept?token=%s", repo.OwnerName, repo.Name, token))
|
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)
|
resp := MakeRequest(t, req, http.StatusAccepted)
|
||||||
|
@ -593,7 +593,7 @@ func TestAPIRejectTransfer(t *testing.T) {
|
||||||
|
|
||||||
// try to reject with not authorized user
|
// try to reject with not authorized user
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token))
|
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)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
|
||||||
|
@ -603,7 +603,7 @@ func TestAPIRejectTransfer(t *testing.T) {
|
||||||
|
|
||||||
// reject transfer
|
// reject transfer
|
||||||
session = loginUser(t, "user4")
|
session = loginUser(t, "user4")
|
||||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token))
|
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)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -617,7 +617,7 @@ func TestAPIGenerateRepo(t *testing.T) {
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
templateRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 44})
|
templateRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 44})
|
||||||
|
|
||||||
|
@ -653,7 +653,7 @@ func TestAPIRepoGetReviewers(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
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)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/reviewers?token=%s", user.Name, repo.Name, token)
|
||||||
|
@ -667,7 +667,7 @@ func TestAPIRepoGetAssignees(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
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)
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/assignees?token=%s", user.Name, repo.Name, token)
|
||||||
|
|
|
@ -60,7 +60,7 @@ func TestAPIRepoTopic(t *testing.T) {
|
||||||
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
||||||
|
|
||||||
// Get user2's token
|
// Get user2's token
|
||||||
token2 := getUserToken(t, user2.Name, auth_model.AccessTokenScopeRepo)
|
token2 := getUserToken(t, user2.Name, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// Test read topics using login
|
// Test read topics using login
|
||||||
url := fmt.Sprintf("/api/v1/repos/%s/%s/topics", user2.Name, repo2.Name)
|
url := fmt.Sprintf("/api/v1/repos/%s/%s/topics", user2.Name, repo2.Name)
|
||||||
|
@ -140,7 +140,7 @@ func TestAPIRepoTopic(t *testing.T) {
|
||||||
MakeRequest(t, req, http.StatusNotFound)
|
MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
|
||||||
// Get user4's token
|
// Get user4's token
|
||||||
token4 := getUserToken(t, user4.Name, auth_model.AccessTokenScopeRepo)
|
token4 := getUserToken(t, user4.Name, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// Test read topics with write access
|
// Test read topics with write access
|
||||||
url = fmt.Sprintf("/api/v1/repos/%s/%s/topics?token=%s", user3.Name, repo3.Name, token4)
|
url = fmt.Sprintf("/api/v1/repos/%s/%s/topics?token=%s", user3.Name, repo3.Name, token4)
|
||||||
|
|
|
@ -33,7 +33,7 @@ func TestAPITeam(t *testing.T) {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser.UID})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser.UID})
|
||||||
|
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrganization)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
|
req := NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ func TestAPITeam(t *testing.T) {
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser2.UID})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser2.UID})
|
||||||
|
|
||||||
session = loginUser(t, user2.Name)
|
session = loginUser(t, user2.Name)
|
||||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrganization)
|
||||||
req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
|
req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
|
||||||
_ = MakeRequest(t, req, http.StatusForbidden)
|
_ = MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ func TestAPITeam(t *testing.T) {
|
||||||
// Get an admin user able to create, update and delete teams.
|
// Get an admin user able to create, update and delete teams.
|
||||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
session = loginUser(t, user.Name)
|
session = loginUser(t, user.Name)
|
||||||
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAdminOrg)
|
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
|
||||||
|
|
||||||
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 6})
|
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 6})
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ func TestAPITeamSearch(t *testing.T) {
|
||||||
|
|
||||||
var results TeamSearchResults
|
var results TeamSearchResults
|
||||||
|
|
||||||
token := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadOrg)
|
token := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadOrganization)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s&token=%s", org.Name, "_team", token)
|
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s&token=%s", org.Name, "_team", token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
DecodeJSON(t, resp, &results)
|
DecodeJSON(t, resp, &results)
|
||||||
|
@ -272,7 +272,7 @@ func TestAPITeamSearch(t *testing.T) {
|
||||||
|
|
||||||
// no access if not organization member
|
// no access if not organization member
|
||||||
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||||
token5 := getUserToken(t, user5.Name, auth_model.AccessTokenScopeReadOrg)
|
token5 := getUserToken(t, user5.Name, auth_model.AccessTokenScopeReadOrganization)
|
||||||
|
|
||||||
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s&token=%s", org.Name, "team", token5)
|
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s&token=%s", org.Name, "team", token5)
|
||||||
MakeRequest(t, req, http.StatusForbidden)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
@ -287,7 +287,7 @@ func TestAPIGetTeamRepo(t *testing.T) {
|
||||||
|
|
||||||
var results api.Repository
|
var results api.Repository
|
||||||
|
|
||||||
token := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadOrg)
|
token := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadOrganization)
|
||||||
req := NewRequestf(t, "GET", "/api/v1/teams/%d/repos/%s/?token=%s", team.ID, teamRepo.FullName(), token)
|
req := NewRequestf(t, "GET", "/api/v1/teams/%d/repos/%s/?token=%s", team.ID, teamRepo.FullName(), token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
DecodeJSON(t, resp, &results)
|
DecodeJSON(t, resp, &results)
|
||||||
|
@ -295,7 +295,7 @@ func TestAPIGetTeamRepo(t *testing.T) {
|
||||||
|
|
||||||
// no access if not organization member
|
// no access if not organization member
|
||||||
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||||
token5 := getUserToken(t, user5.Name, auth_model.AccessTokenScopeReadOrg)
|
token5 := getUserToken(t, user5.Name, auth_model.AccessTokenScopeReadOrganization)
|
||||||
|
|
||||||
req = NewRequestf(t, "GET", "/api/v1/teams/%d/repos/%s/?token=%s", team.ID, teamRepo.FullName(), token5)
|
req = NewRequestf(t, "GET", "/api/v1/teams/%d/repos/%s/?token=%s", team.ID, teamRepo.FullName(), token5)
|
||||||
MakeRequest(t, req, http.StatusNotFound)
|
MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
|
|
@ -24,7 +24,7 @@ func TestAPITeamUser(t *testing.T) {
|
||||||
|
|
||||||
normalUsername := "user2"
|
normalUsername := "user2"
|
||||||
session := loginUser(t, normalUsername)
|
session := loginUser(t, normalUsername)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrganization)
|
||||||
req := NewRequest(t, "GET", "/api/v1/teams/1/members/user1?token="+token)
|
req := NewRequest(t, "GET", "/api/v1/teams/1/members/user1?token="+token)
|
||||||
MakeRequest(t, req, http.StatusNotFound)
|
MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,18 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAPICreateAndDeleteToken tests that token that was just created can be deleted
|
// TestAPICreateAndDeleteToken tests that token that was just created can be deleted
|
||||||
|
@ -19,9 +23,518 @@ func TestAPICreateAndDeleteToken(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
req := NewRequestWithJSON(t, "POST", "/api/v1/users/user1/tokens", map[string]string{
|
newAccessToken := createAPIAccessTokenWithoutCleanUp(t, "test-key-1", user, nil)
|
||||||
"name": "test-key-1",
|
deleteAPIAccessToken(t, newAccessToken, user)
|
||||||
|
|
||||||
|
newAccessToken = createAPIAccessTokenWithoutCleanUp(t, "test-key-2", user, nil)
|
||||||
|
deleteAPIAccessToken(t, newAccessToken, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAPIDeleteMissingToken ensures that error is thrown when token not found
|
||||||
|
func TestAPIDeleteMissingToken(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
|
req := NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", unittest.NonexistentID)
|
||||||
|
req = AddBasicAuthHeader(req, user.Name)
|
||||||
|
MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
type permission struct {
|
||||||
|
category auth_model.AccessTokenScopeCategory
|
||||||
|
level auth_model.AccessTokenScopeLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
type requiredScopeTestCase struct {
|
||||||
|
url string
|
||||||
|
method string
|
||||||
|
requiredPermissions []permission
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *requiredScopeTestCase) Name() string {
|
||||||
|
return fmt.Sprintf("%v %v", c.method, c.url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAPIDeniesPermissionBasedOnTokenScope tests that API routes forbid access
|
||||||
|
// when the correct token scope is not included.
|
||||||
|
func TestAPIDeniesPermissionBasedOnTokenScope(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
// We'll assert that each endpoint, when fetched with a token with all
|
||||||
|
// scopes *except* the ones specified, a forbidden status code is returned.
|
||||||
|
//
|
||||||
|
// This is to protect against endpoints having their access check copied
|
||||||
|
// from other endpoints and not updated.
|
||||||
|
//
|
||||||
|
// Test cases are in alphabetical order by URL.
|
||||||
|
//
|
||||||
|
// Note: query parameters are not currently supported since the token is
|
||||||
|
// appended with `?=token=<token>`.
|
||||||
|
testCases := []requiredScopeTestCase{
|
||||||
|
{
|
||||||
|
"/api/v1/admin/emails",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryAdmin,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/admin/users",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryAdmin,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/admin/users",
|
||||||
|
"POST",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryAdmin,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/admin/users/user2",
|
||||||
|
"PATCH",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryAdmin,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/admin/users/user2/orgs",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryAdmin,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/admin/users/user2/orgs",
|
||||||
|
"POST",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryAdmin,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/admin/orgs",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryAdmin,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/markdown",
|
||||||
|
"POST",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryMisc,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/markdown/raw",
|
||||||
|
"POST",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryMisc,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/notifications",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryNotification,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/notifications",
|
||||||
|
"PUT",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryNotification,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/org/org1/repos",
|
||||||
|
"POST",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryOrganization,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/packages/user1/type/name/1",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryPackage,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/packages/user1/type/name/1",
|
||||||
|
"DELETE",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryPackage,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1",
|
||||||
|
"PATCH",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1",
|
||||||
|
"DELETE",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1/branches",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1/archive/foo",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1/issues",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryIssue,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1/media/foo",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1/raw/foo",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1/teams",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1/teams/team1",
|
||||||
|
"PUT",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user1/repo1/transfer",
|
||||||
|
"POST",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Private repo
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user2/repo2",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Private repo
|
||||||
|
{
|
||||||
|
"/api/v1/repos/user2/repo2",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryRepository,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/settings/api",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryMisc,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/user",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/user/emails",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/user/emails",
|
||||||
|
"POST",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/user/emails",
|
||||||
|
"DELETE",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/user/applications/oauth2",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/user/applications/oauth2",
|
||||||
|
"POST",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Write,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/api/v1/users/search",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Private user
|
||||||
|
{
|
||||||
|
"/api/v1/users/user31",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Private user
|
||||||
|
{
|
||||||
|
"/api/v1/users/user31/gpg_keys",
|
||||||
|
"GET",
|
||||||
|
[]permission{
|
||||||
|
{
|
||||||
|
auth_model.AccessTokenScopeCategoryUser,
|
||||||
|
auth_model.Read,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// User needs to be admin so that we can verify that tokens without admin
|
||||||
|
// scopes correctly deny access.
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
assert.True(t, user.IsAdmin, "User needs to be admin")
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
runTestCase(t, &testCase, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// runTestCase Helper function to run a single test case.
|
||||||
|
func runTestCase(t *testing.T, testCase *requiredScopeTestCase, user *user_model.User) {
|
||||||
|
t.Run(testCase.Name(), func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
// Create a token with all scopes NOT required by the endpoint.
|
||||||
|
var unauthorizedScopes []auth_model.AccessTokenScope
|
||||||
|
for _, category := range auth_model.AllAccessTokenScopeCategories {
|
||||||
|
// For permissions, Write > Read > NoAccess. So we need to
|
||||||
|
// find the minimum required, and only grant permission up to but
|
||||||
|
// not including the minimum required.
|
||||||
|
minRequiredLevel := auth_model.Write
|
||||||
|
categoryIsRequired := false
|
||||||
|
for _, requiredPermission := range testCase.requiredPermissions {
|
||||||
|
if requiredPermission.category != category {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
categoryIsRequired = true
|
||||||
|
if requiredPermission.level < minRequiredLevel {
|
||||||
|
minRequiredLevel = requiredPermission.level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unauthorizedLevel := auth_model.Write
|
||||||
|
if categoryIsRequired {
|
||||||
|
if minRequiredLevel == auth_model.Read {
|
||||||
|
unauthorizedLevel = auth_model.NoAccess
|
||||||
|
} else if minRequiredLevel == auth_model.Write {
|
||||||
|
unauthorizedLevel = auth_model.Read
|
||||||
|
} else {
|
||||||
|
assert.Failf(t, "Invalid test case", "Unknown access token scope level: %v", minRequiredLevel)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if unauthorizedLevel == auth_model.NoAccess {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cateogoryUnauthorizedScopes := auth_model.GetRequiredScopes(
|
||||||
|
unauthorizedLevel,
|
||||||
|
category)
|
||||||
|
unauthorizedScopes = append(unauthorizedScopes, cateogoryUnauthorizedScopes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
accessToken := createAPIAccessTokenWithoutCleanUp(t, "test-token", user, &unauthorizedScopes)
|
||||||
|
defer deleteAPIAccessToken(t, accessToken, user)
|
||||||
|
|
||||||
|
// Add API access token to the URL.
|
||||||
|
url := fmt.Sprintf("%s?token=%s", testCase.url, accessToken.Token)
|
||||||
|
|
||||||
|
// Request the endpoint. Verify that permission is denied.
|
||||||
|
req := NewRequestf(t, testCase.method, url)
|
||||||
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// createAPIAccessTokenWithoutCleanUp Create an API access token and assert that
|
||||||
|
// creation succeeded. The caller is responsible for deleting the token.
|
||||||
|
func createAPIAccessTokenWithoutCleanUp(t *testing.T, tokenName string, user *user_model.User, scopes *[]auth_model.AccessTokenScope) api.AccessToken {
|
||||||
|
payload := map[string]interface{}{
|
||||||
|
"name": tokenName,
|
||||||
|
}
|
||||||
|
if scopes != nil {
|
||||||
|
for _, scope := range *scopes {
|
||||||
|
scopes, scopesExists := payload["scopes"].([]string)
|
||||||
|
if !scopesExists {
|
||||||
|
scopes = make([]string, 0)
|
||||||
|
}
|
||||||
|
scopes = append(scopes, string(scope))
|
||||||
|
payload["scopes"] = scopes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Debug("Requesting creation of token with scopes: %v", scopes)
|
||||||
|
req := NewRequestWithJSON(t, "POST", "/api/v1/users/user1/tokens", payload)
|
||||||
|
|
||||||
req = AddBasicAuthHeader(req, user.Name)
|
req = AddBasicAuthHeader(req, user.Name)
|
||||||
resp := MakeRequest(t, req, http.StatusCreated)
|
resp := MakeRequest(t, req, http.StatusCreated)
|
||||||
|
|
||||||
|
@ -34,32 +547,15 @@ func TestAPICreateAndDeleteToken(t *testing.T) {
|
||||||
UID: user.ID,
|
UID: user.ID,
|
||||||
})
|
})
|
||||||
|
|
||||||
req = NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", newAccessToken.ID)
|
return newAccessToken
|
||||||
|
}
|
||||||
|
|
||||||
|
// createAPIAccessTokenWithoutCleanUp Delete an API access token and assert that
|
||||||
|
// deletion succeeded.
|
||||||
|
func deleteAPIAccessToken(t *testing.T, accessToken api.AccessToken, user *user_model.User) {
|
||||||
|
req := NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", accessToken.ID)
|
||||||
req = AddBasicAuthHeader(req, user.Name)
|
req = AddBasicAuthHeader(req, user.Name)
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
unittest.AssertNotExistsBean(t, &auth_model.AccessToken{ID: newAccessToken.ID})
|
unittest.AssertNotExistsBean(t, &auth_model.AccessToken{ID: accessToken.ID})
|
||||||
|
|
||||||
req = NewRequestWithJSON(t, "POST", "/api/v1/users/user1/tokens", map[string]string{
|
|
||||||
"name": "test-key-2",
|
|
||||||
})
|
|
||||||
req = AddBasicAuthHeader(req, user.Name)
|
|
||||||
resp = MakeRequest(t, req, http.StatusCreated)
|
|
||||||
DecodeJSON(t, resp, &newAccessToken)
|
|
||||||
|
|
||||||
req = NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%s", newAccessToken.Name)
|
|
||||||
req = AddBasicAuthHeader(req, user.Name)
|
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
|
||||||
|
|
||||||
unittest.AssertNotExistsBean(t, &auth_model.AccessToken{ID: newAccessToken.ID})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestAPIDeleteMissingToken ensures that error is thrown when token not found
|
|
||||||
func TestAPIDeleteMissingToken(t *testing.T) {
|
|
||||||
defer tests.PrepareTestEnv(t)()
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
||||||
|
|
||||||
req := NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", unittest.NonexistentID)
|
|
||||||
req = AddBasicAuthHeader(req, user.Name)
|
|
||||||
MakeRequest(t, req, http.StatusNotFound)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func TestAPIAddEmail(t *testing.T) {
|
||||||
|
|
||||||
normalUsername := "user2"
|
normalUsername := "user2"
|
||||||
session := loginUser(t, normalUsername)
|
session := loginUser(t, normalUsername)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeUser)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
opts := api.CreateEmailOption{
|
opts := api.CreateEmailOption{
|
||||||
Emails: []string{"user101@example.com"},
|
Emails: []string{"user101@example.com"},
|
||||||
|
@ -83,7 +83,7 @@ func TestAPIDeleteEmail(t *testing.T) {
|
||||||
|
|
||||||
normalUsername := "user2"
|
normalUsername := "user2"
|
||||||
session := loginUser(t, normalUsername)
|
session := loginUser(t, normalUsername)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeUser)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
opts := api.DeleteEmailOption{
|
opts := api.DeleteEmailOption{
|
||||||
Emails: []string{"user2-3@example.com"},
|
Emails: []string{"user2-3@example.com"},
|
||||||
|
|
|
@ -22,10 +22,10 @@ func TestAPIFollow(t *testing.T) {
|
||||||
user2 := "user1"
|
user2 := "user1"
|
||||||
|
|
||||||
session1 := loginUser(t, user1)
|
session1 := loginUser(t, user1)
|
||||||
token1 := getTokenForLoggedInUser(t, session1)
|
token1 := getTokenForLoggedInUser(t, session1, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
session2 := loginUser(t, user2)
|
session2 := loginUser(t, user2)
|
||||||
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeUserFollow)
|
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
t.Run("Follow", func(t *testing.T) {
|
t.Run("Follow", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
activities_model "code.gitea.io/gitea/models/activities"
|
activities_model "code.gitea.io/gitea/models/activities"
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ func TestUserHeatmap(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
normalUsername := "user2"
|
normalUsername := "user2"
|
||||||
token := getUserToken(t, adminUsername)
|
token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
fakeNow := time.Date(2011, 10, 20, 0, 0, 0, 0, time.Local)
|
fakeNow := time.Date(2011, 10, 20, 0, 0, 0, 0, time.Local)
|
||||||
timeutil.Set(fakeNow)
|
timeutil.Set(fakeNow)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ func TestAPIUserInfo(t *testing.T) {
|
||||||
user2 := "user31"
|
user2 := "user31"
|
||||||
|
|
||||||
session := loginUser(t, user)
|
session := loginUser(t, user)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
t.Run("GetInfo", func(t *testing.T) {
|
t.Run("GetInfo", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
|
@ -33,7 +33,7 @@ func sampleTest(t *testing.T, auoptc apiUserOrgPermTestCase) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, auoptc.LoginUser)
|
session := loginUser(t, auoptc.LoginUser)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrganization, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/%s/orgs/%s/permissions?token=%s", auoptc.User, auoptc.Organization, token))
|
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)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -126,7 +126,7 @@ func TestUnknowUser(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser, auth_model.AccessTokenScopeReadOrganization)
|
||||||
|
|
||||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/unknow/orgs/org25/permissions?token=%s", token))
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/unknow/orgs/org25/permissions?token=%s", token))
|
||||||
resp := MakeRequest(t, req, http.StatusNotFound)
|
resp := MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
@ -140,7 +140,7 @@ func TestUnknowOrganization(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrg)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser, auth_model.AccessTokenScopeReadOrganization)
|
||||||
|
|
||||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/user1/orgs/unknow/permissions?token=%s", token))
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/users/user1/orgs/unknow/permissions?token=%s", token))
|
||||||
resp := MakeRequest(t, req, http.StatusNotFound)
|
resp := MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
|
|
@ -70,7 +70,7 @@ func TestUserOrgs(t *testing.T) {
|
||||||
func getUserOrgs(t *testing.T, userDoer, userCheck string) (orgs []*api.Organization) {
|
func getUserOrgs(t *testing.T, userDoer, userCheck string) (orgs []*api.Organization) {
|
||||||
token := ""
|
token := ""
|
||||||
if len(userDoer) != 0 {
|
if len(userDoer) != 0 {
|
||||||
token = getUserToken(t, userDoer, auth_model.AccessTokenScopeReadOrg)
|
token = getUserToken(t, userDoer, auth_model.AccessTokenScopeReadOrganization, auth_model.AccessTokenScopeReadUser)
|
||||||
}
|
}
|
||||||
urlStr := fmt.Sprintf("/api/v1/users/%s/orgs?token=%s", userCheck, token)
|
urlStr := fmt.Sprintf("/api/v1/users/%s/orgs?token=%s", userCheck, token)
|
||||||
req := NewRequest(t, "GET", urlStr)
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
@ -92,7 +92,7 @@ func TestMyOrgs(t *testing.T) {
|
||||||
MakeRequest(t, req, http.StatusUnauthorized)
|
MakeRequest(t, req, http.StatusUnauthorized)
|
||||||
|
|
||||||
normalUsername := "user2"
|
normalUsername := "user2"
|
||||||
token := getUserToken(t, normalUsername, auth_model.AccessTokenScopeReadOrg)
|
token := getUserToken(t, normalUsername, auth_model.AccessTokenScopeReadOrganization, auth_model.AccessTokenScopeReadUser)
|
||||||
req = NewRequest(t, "GET", "/api/v1/user/orgs?token="+token)
|
req = NewRequest(t, "GET", "/api/v1/user/orgs?token="+token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
var orgs []*api.Organization
|
var orgs []*api.Organization
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -26,7 +27,7 @@ func TestAPIUserSearchLoggedIn(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
session := loginUser(t, adminUsername)
|
session := loginUser(t, adminUsername)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||||
query := "user2"
|
query := "user2"
|
||||||
req := NewRequestf(t, "GET", "/api/v1/users/search?token=%s&q=%s", token, query)
|
req := NewRequestf(t, "GET", "/api/v1/users/search?token=%s&q=%s", token, query)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -65,7 +66,7 @@ func TestAPIUserSearchAdminLoggedInUserHidden(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
adminUsername := "user1"
|
adminUsername := "user1"
|
||||||
session := loginUser(t, adminUsername)
|
session := loginUser(t, adminUsername)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||||
query := "user31"
|
query := "user31"
|
||||||
req := NewRequestf(t, "GET", "/api/v1/users/search?token=%s&q=%s", token, query)
|
req := NewRequestf(t, "GET", "/api/v1/users/search?token=%s&q=%s", token, query)
|
||||||
req.SetBasicAuth(token, "x-oauth-basic")
|
req.SetBasicAuth(token, "x-oauth-basic")
|
||||||
|
|
|
@ -22,13 +22,13 @@ func TestAPIStar(t *testing.T) {
|
||||||
repo := "user2/repo1"
|
repo := "user2/repo1"
|
||||||
|
|
||||||
session := loginUser(t, user)
|
session := loginUser(t, user)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||||
tokenWithRepoScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
tokenWithUserScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
t.Run("Star", func(t *testing.T) {
|
t.Run("Star", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithRepoScope))
|
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithUserScope))
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ func TestAPIStar(t *testing.T) {
|
||||||
t.Run("GetMyStarredRepos", func(t *testing.T) {
|
t.Run("GetMyStarredRepos", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred?token=%s", tokenWithRepoScope))
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred?token=%s", tokenWithUserScope))
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
assert.Equal(t, "1", resp.Header().Get("X-Total-Count"))
|
assert.Equal(t, "1", resp.Header().Get("X-Total-Count"))
|
||||||
|
@ -63,17 +63,17 @@ func TestAPIStar(t *testing.T) {
|
||||||
t.Run("IsStarring", func(t *testing.T) {
|
t.Run("IsStarring", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithRepoScope))
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithUserScope))
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo+"notexisting", tokenWithRepoScope))
|
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo+"notexisting", tokenWithUserScope))
|
||||||
MakeRequest(t, req, http.StatusNotFound)
|
MakeRequest(t, req, http.StatusNotFound)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Unstar", func(t *testing.T) {
|
t.Run("Unstar", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithRepoScope))
|
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/user/starred/%s?token=%s", repo, tokenWithUserScope))
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ func TestAPIWatch(t *testing.T) {
|
||||||
repo := "user2/repo1"
|
repo := "user2/repo1"
|
||||||
|
|
||||||
session := loginUser(t, user)
|
session := loginUser(t, user)
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||||
tokenWithRepoScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
tokenWithRepoScope := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
t.Run("Watch", func(t *testing.T) {
|
t.Run("Watch", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
|
@ -180,7 +180,7 @@ func TestAPINewWikiPage(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
username := "user2"
|
username := "user2"
|
||||||
session := loginUser(t, username)
|
session := loginUser(t, username)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new?token=%s", username, "repo1", token)
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new?token=%s", username, "repo1", token)
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ func TestAPIEditWikiPage(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
username := "user2"
|
username := "user2"
|
||||||
session := loginUser(t, username)
|
session := loginUser(t, username)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/Page-With-Spaced-Name?token=%s", username, "repo1", token)
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/Page-With-Spaced-Name?token=%s", username, "repo1", token)
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ func TestDumpRestore(t *testing.T) {
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame})
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
session := loginUser(t, repoOwner.Name)
|
session := loginUser(t, repoOwner.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadMisc)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Phase 1: dump repo1 from the Gitea instance to the filesystem
|
// Phase 1: dump repo1 from the Gitea instance to the filesystem
|
||||||
|
|
|
@ -117,7 +117,7 @@ func TestEmptyRepoAddFileByAPI(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
session := loginUser(t, "user30")
|
session := loginUser(t, "user30")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
url := fmt.Sprintf("/api/v1/repos/user30/empty/contents/new-file.txt?token=%s", token)
|
url := fmt.Sprintf("/api/v1/repos/user30/empty/contents/new-file.txt?token=%s", token)
|
||||||
req := NewRequestWithJSON(t, "POST", url, &api.CreateFileOptions{
|
req := NewRequestWithJSON(t, "POST", url, &api.CreateFileOptions{
|
||||||
|
|
|
@ -60,7 +60,7 @@ func TestEventSourceManagerRun(t *testing.T) {
|
||||||
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
|
||||||
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
|
||||||
session := loginUser(t, user2.Name)
|
session := loginUser(t, user2.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeNotification)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteNotification, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
var apiNL []api.NotificationThread
|
var apiNL []api.NotificationThread
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,11 @@ func TestGit(t *testing.T) {
|
||||||
|
|
||||||
func testGit(t *testing.T, u *url.URL) {
|
func testGit(t *testing.T, u *url.URL) {
|
||||||
username := "user2"
|
username := "user2"
|
||||||
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeWritePublicKey, auth_model.AccessTokenScopeDeleteRepo)
|
baseAPITestContext := NewAPITestContext(t, username, "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
u.Path = baseAPITestContext.GitPath()
|
u.Path = baseAPITestContext.GitPath()
|
||||||
|
|
||||||
forkedUserCtx := NewAPITestContext(t, "user4", "repo1", auth_model.AccessTokenScopeRepo)
|
forkedUserCtx := NewAPITestContext(t, "user4", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
t.Run("HTTP", func(t *testing.T) {
|
t.Run("HTTP", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
@ -359,7 +359,7 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
|
||||||
t.Run("CreateBranchProtected", doGitCreateBranch(dstPath, "protected"))
|
t.Run("CreateBranchProtected", doGitCreateBranch(dstPath, "protected"))
|
||||||
t.Run("PushProtectedBranch", doGitPushTestRepository(dstPath, "origin", "protected"))
|
t.Run("PushProtectedBranch", doGitPushTestRepository(dstPath, "origin", "protected"))
|
||||||
|
|
||||||
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame, auth_model.AccessTokenScopeRepo)
|
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame, auth_model.AccessTokenScopeWriteRepository)
|
||||||
t.Run("ProtectProtectedBranchNoWhitelist", doProtectBranch(ctx, "protected", "", ""))
|
t.Run("ProtectProtectedBranchNoWhitelist", doProtectBranch(ctx, "protected", "", ""))
|
||||||
t.Run("GenerateCommit", func(t *testing.T) {
|
t.Run("GenerateCommit", func(t *testing.T) {
|
||||||
_, err := generateCommitWithNewData(littleSize, dstPath, "user2@example.com", "User Two", "branch-data-file-")
|
_, err := generateCommitWithNewData(littleSize, dstPath, "user2@example.com", "User Two", "branch-data-file-")
|
||||||
|
@ -603,7 +603,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
|
||||||
return func(t *testing.T) {
|
return func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame, auth_model.AccessTokenScopeRepo)
|
ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
t.Run("CheckoutProtected", doGitCheckoutBranch(dstPath, "protected"))
|
t.Run("CheckoutProtected", doGitCheckoutBranch(dstPath, "protected"))
|
||||||
t.Run("PullProtected", doGitPull(dstPath, "origin", "protected"))
|
t.Run("PullProtected", doGitPull(dstPath, "origin", "protected"))
|
||||||
|
|
|
@ -70,7 +70,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("Unsigned-Initial", func(t *testing.T) {
|
t.Run("Unsigned-Initial", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||||
t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
|
t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
|
||||||
assert.NotNil(t, branch.Commit)
|
assert.NotNil(t, branch.Commit)
|
||||||
|
@ -94,7 +94,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) {
|
t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
|
t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
|
||||||
t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
|
t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
|
||||||
assert.False(t, response.Verification.Verified)
|
assert.False(t, response.Verification.Verified)
|
||||||
|
@ -111,7 +111,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("Unsigned-Initial-CRUD-Never", func(t *testing.T) {
|
t.Run("Unsigned-Initial-CRUD-Never", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateCRUDFile-Never", crudActionCreateFile(
|
t.Run("CreateCRUDFile-Never", crudActionCreateFile(
|
||||||
t, testCtx, user, "parentsigned", "parentsigned-never", "unsigned-never2.txt", func(t *testing.T, response api.FileResponse) {
|
t, testCtx, user, "parentsigned", "parentsigned-never", "unsigned-never2.txt", func(t *testing.T, response api.FileResponse) {
|
||||||
assert.False(t, response.Verification.Verified)
|
assert.False(t, response.Verification.Verified)
|
||||||
|
@ -124,7 +124,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("Unsigned-Initial-CRUD-Always", func(t *testing.T) {
|
t.Run("Unsigned-Initial-CRUD-Always", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
|
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
|
||||||
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
|
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
|
||||||
assert.NotNil(t, response.Verification)
|
assert.NotNil(t, response.Verification)
|
||||||
|
@ -161,7 +161,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) {
|
t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateCRUDFile-Always-ParentSigned", crudActionCreateFile(
|
t.Run("CreateCRUDFile-Always-ParentSigned", crudActionCreateFile(
|
||||||
t, testCtx, user, "always", "always-parentsigned", "signed-always-parentsigned.txt", func(t *testing.T, response api.FileResponse) {
|
t, testCtx, user, "always", "always-parentsigned", "signed-always-parentsigned.txt", func(t *testing.T, response api.FileResponse) {
|
||||||
assert.NotNil(t, response.Verification)
|
assert.NotNil(t, response.Verification)
|
||||||
|
@ -184,7 +184,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("AlwaysSign-Initial", func(t *testing.T) {
|
t.Run("AlwaysSign-Initial", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-always", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-always", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||||
t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
|
t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
|
||||||
assert.NotNil(t, branch.Commit)
|
assert.NotNil(t, branch.Commit)
|
||||||
|
@ -212,7 +212,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("AlwaysSign-Initial-CRUD-Never", func(t *testing.T) {
|
t.Run("AlwaysSign-Initial-CRUD-Never", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-always-never", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-always-never", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||||
t.Run("CreateCRUDFile-Never", crudActionCreateFile(
|
t.Run("CreateCRUDFile-Never", crudActionCreateFile(
|
||||||
t, testCtx, user, "master", "never", "unsigned-never.txt", func(t *testing.T, response api.FileResponse) {
|
t, testCtx, user, "master", "never", "unsigned-never.txt", func(t *testing.T, response api.FileResponse) {
|
||||||
|
@ -225,7 +225,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
u.Path = baseAPITestContext.GitPath()
|
u.Path = baseAPITestContext.GitPath()
|
||||||
t.Run("AlwaysSign-Initial-CRUD-ParentSigned-On-Always", func(t *testing.T) {
|
t.Run("AlwaysSign-Initial-CRUD-ParentSigned-On-Always", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-always-parent", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-always-parent", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||||
t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
|
t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
|
||||||
t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
|
t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
|
||||||
|
@ -244,7 +244,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("AlwaysSign-Initial-CRUD-Always", func(t *testing.T) {
|
t.Run("AlwaysSign-Initial-CRUD-Always", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-always-always", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-always-always", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
|
||||||
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
|
t.Run("CreateCRUDFile-Always", crudActionCreateFile(
|
||||||
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
|
t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
|
||||||
|
@ -264,7 +264,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("UnsignedMerging", func(t *testing.T) {
|
t.Run("UnsignedMerging", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
var err error
|
var err error
|
||||||
t.Run("CreatePullRequest", func(t *testing.T) {
|
t.Run("CreatePullRequest", func(t *testing.T) {
|
||||||
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "never2")(t)
|
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "never2")(t)
|
||||||
|
@ -285,7 +285,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("BaseSignedMerging", func(t *testing.T) {
|
t.Run("BaseSignedMerging", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
var err error
|
var err error
|
||||||
t.Run("CreatePullRequest", func(t *testing.T) {
|
t.Run("CreatePullRequest", func(t *testing.T) {
|
||||||
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "parentsigned2")(t)
|
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "parentsigned2")(t)
|
||||||
|
@ -306,7 +306,7 @@ func TestGPGGit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("CommitsSignedMerging", func(t *testing.T) {
|
t.Run("CommitsSignedMerging", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
var err error
|
var err error
|
||||||
t.Run("CreatePullRequest", func(t *testing.T) {
|
t.Run("CreatePullRequest", func(t *testing.T) {
|
||||||
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "always-parentsigned")(t)
|
pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "always-parentsigned")(t)
|
||||||
|
|
|
@ -41,13 +41,13 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string
|
||||||
return pointer.Oid
|
return pointer.Oid
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeAndGetLfsToken(t *testing.T, ts auth.AccessTokenScope, content *[]byte, extraHeader *http.Header, expectedStatus int) *httptest.ResponseRecorder {
|
func storeAndGetLfsToken(t *testing.T, content *[]byte, extraHeader *http.Header, expectedStatus int, ts ...auth.AccessTokenScope) *httptest.ResponseRecorder {
|
||||||
repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "repo1")
|
repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "repo1")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
oid := storeObjectInRepo(t, repo.ID, content)
|
oid := storeObjectInRepo(t, repo.ID, content)
|
||||||
defer git_model.RemoveLFSMetaObjectByOid(db.DefaultContext, repo.ID, oid)
|
defer git_model.RemoveLFSMetaObjectByOid(db.DefaultContext, repo.ID, oid)
|
||||||
|
|
||||||
token := getUserToken(t, "user2", ts)
|
token := getUserToken(t, "user2", ts...)
|
||||||
|
|
||||||
// Request OID
|
// Request OID
|
||||||
req := NewRequest(t, "GET", "/user2/repo1.git/info/lfs/objects/"+oid+"/test")
|
req := NewRequest(t, "GET", "/user2/repo1.git/info/lfs/objects/"+oid+"/test")
|
||||||
|
@ -119,7 +119,7 @@ func TestGetLFSSmallToken(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
content := []byte("A very small file\n")
|
content := []byte("A very small file\n")
|
||||||
|
|
||||||
resp := storeAndGetLfsToken(t, auth.AccessTokenScopePublicRepo, &content, nil, http.StatusOK)
|
resp := storeAndGetLfsToken(t, &content, nil, http.StatusOK, auth.AccessTokenScopePublicOnly, auth.AccessTokenScopeReadRepository)
|
||||||
checkResponseTestContentEncoding(t, &content, resp, false)
|
checkResponseTestContentEncoding(t, &content, resp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ func TestGetLFSSmallTokenFail(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
content := []byte("A very small file\n")
|
content := []byte("A very small file\n")
|
||||||
|
|
||||||
storeAndGetLfsToken(t, auth.AccessTokenScopeNotification, &content, nil, http.StatusForbidden)
|
storeAndGetLfsToken(t, &content, nil, http.StatusForbidden, auth.AccessTokenScopeReadNotification)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetLFSLarge(t *testing.T) {
|
func TestGetLFSLarge(t *testing.T) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ func TestMigrateGiteaForm(t *testing.T) {
|
||||||
repoName := "repo1"
|
repoName := "repo1"
|
||||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: ownerName})
|
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: ownerName})
|
||||||
session := loginUser(t, ownerName)
|
session := loginUser(t, ownerName)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadMisc)
|
||||||
|
|
||||||
// Step 0: verify the repo is available
|
// Step 0: verify the repo is available
|
||||||
req := NewRequestf(t, "GET", fmt.Sprintf("/%s/%s", ownerName, repoName))
|
req := NewRequestf(t, "GET", fmt.Sprintf("/%s/%s", ownerName, repoName))
|
||||||
|
|
|
@ -25,7 +25,7 @@ func testOrgCounts(t *testing.T, u *url.URL) {
|
||||||
orgOwner := "user2"
|
orgOwner := "user2"
|
||||||
orgName := "testOrg"
|
orgName := "testOrg"
|
||||||
orgCollaborator := "user4"
|
orgCollaborator := "user4"
|
||||||
ctx := NewAPITestContext(t, orgOwner, "repo1", auth_model.AccessTokenScopeAdminOrg)
|
ctx := NewAPITestContext(t, orgOwner, "repo1", auth_model.AccessTokenScopeWriteOrganization)
|
||||||
|
|
||||||
var ownerCountRepos map[string]int
|
var ownerCountRepos map[string]int
|
||||||
var collabCountRepos map[string]int
|
var collabCountRepos map[string]int
|
||||||
|
|
|
@ -159,7 +159,7 @@ func TestOrgRestrictedUser(t *testing.T) {
|
||||||
|
|
||||||
// Therefore create a read-only team
|
// Therefore create a read-only team
|
||||||
adminSession := loginUser(t, "user1")
|
adminSession := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, adminSession, auth_model.AccessTokenScopeAdminOrg)
|
token := getTokenForLoggedInUser(t, adminSession, auth_model.AccessTokenScopeWriteOrganization)
|
||||||
|
|
||||||
teamToCreate := &api.CreateTeamOption{
|
teamToCreate := &api.CreateTeamOption{
|
||||||
Name: "codereader",
|
Name: "codereader",
|
||||||
|
|
|
@ -34,7 +34,7 @@ func testPrivateActivityDoSomethingForActionEntries(t *testing.T) {
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID})
|
||||||
|
|
||||||
session := loginUser(t, privateActivityTestUser)
|
session := loginUser(t, privateActivityTestUser)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
|
||||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all&token=%s", owner.Name, repoBefore.Name, token)
|
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{
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{
|
||||||
Body: "test",
|
Body: "test",
|
||||||
|
@ -125,7 +125,7 @@ func testPrivateActivityHelperHasHeatmapContentFromPublic(t *testing.T) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPrivateActivityHelperHasHeatmapContentFromSession(t *testing.T, session *TestSession) bool {
|
func testPrivateActivityHelperHasHeatmapContentFromSession(t *testing.T, session *TestSession) bool {
|
||||||
token := getTokenForLoggedInUser(t, session)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/users/%s/heatmap?token=%s", privateActivityTestUser, token)
|
req := NewRequestf(t, "GET", "/api/v1/users/%s/heatmap?token=%s", privateActivityTestUser, token)
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
|
@ -218,7 +218,7 @@ func TestCantMergeConflict(t *testing.T) {
|
||||||
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "base", "README.md", "Hello, World (Edited Twice)\n")
|
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "base", "README.md", "Hello, World (Edited Twice)\n")
|
||||||
|
|
||||||
// Use API to create a conflicting pr
|
// Use API to create a conflicting pr
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", "user1", "repo1", token), &api.CreatePullRequestOption{
|
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", "user1", "repo1", token), &api.CreatePullRequestOption{
|
||||||
Head: "conflict",
|
Head: "conflict",
|
||||||
Base: "base",
|
Base: "base",
|
||||||
|
@ -326,7 +326,7 @@ func TestCantMergeUnrelated(t *testing.T) {
|
||||||
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "conflict", "README.md", "Hello, World (Edited Once)\n")
|
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "conflict", "README.md", "Hello, World (Edited Once)\n")
|
||||||
|
|
||||||
// Use API to create a conflicting pr
|
// Use API to create a conflicting pr
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", "user1", "repo1", token), &api.CreatePullRequestOption{
|
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", "user1", "repo1", token), &api.CreatePullRequestOption{
|
||||||
Head: "unrelated",
|
Head: "unrelated",
|
||||||
Base: "base",
|
Base: "base",
|
||||||
|
|
|
@ -64,7 +64,7 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
||||||
api.CommitStatusWarning: "gitea-exclamation",
|
api.CommitStatusWarning: "gitea-exclamation",
|
||||||
}
|
}
|
||||||
|
|
||||||
testCtx := NewAPITestContext(t, "user1", "repo1", auth_model.AccessTokenScopeRepo)
|
testCtx := NewAPITestContext(t, "user1", "repo1", auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
// Update commit status, and check if icon is updated as well
|
// Update commit status, and check if icon is updated as well
|
||||||
for _, status := range statusList {
|
for _, status := range statusList {
|
||||||
|
|
|
@ -39,7 +39,7 @@ func TestAPIPullUpdate(t *testing.T) {
|
||||||
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
|
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
|
||||||
|
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestf(t, "POST", "/api/v1/repos/%s/%s/pulls/%d/update?token="+token, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, pr.Issue.Index)
|
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)
|
session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ func TestAPIPullUpdateByRebase(t *testing.T) {
|
||||||
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
|
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
|
||||||
|
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
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)
|
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)
|
session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
|
|
||||||
// Call API to add status for commit
|
// Call API to add status for commit
|
||||||
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeRepo)
|
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
|
||||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
||||||
State: api.CommitStatusState(state),
|
State: api.CommitStatusState(state),
|
||||||
TargetURL: "http://test.ci/",
|
TargetURL: "http://test.ci/",
|
||||||
|
@ -157,7 +157,7 @@ func TestRepoCommitsStatusParallel(t *testing.T) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(parentT *testing.T, i int) {
|
go func(parentT *testing.T, i int) {
|
||||||
parentT.Run(fmt.Sprintf("ParallelCreateStatus_%d", i), func(t *testing.T) {
|
parentT.Run(fmt.Sprintf("ParallelCreateStatus_%d", i), func(t *testing.T) {
|
||||||
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeRepoStatus)
|
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
|
||||||
runBody := doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
runBody := doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
||||||
State: api.CommitStatusPending,
|
State: api.CommitStatusPending,
|
||||||
TargetURL: "http://test.ci/",
|
TargetURL: "http://test.ci/",
|
||||||
|
@ -188,7 +188,7 @@ func TestRepoCommitsStatusMultiple(t *testing.T) {
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
|
|
||||||
// Call API to add status for commit
|
// Call API to add status for commit
|
||||||
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeRepo)
|
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
|
||||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
||||||
State: api.CommitStatusSuccess,
|
State: api.CommitStatusSuccess,
|
||||||
TargetURL: "http://test.ci/",
|
TargetURL: "http://test.ci/",
|
||||||
|
|
|
@ -48,8 +48,8 @@ func TestPushDeployKeyOnEmptyRepo(t *testing.T) {
|
||||||
|
|
||||||
func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
|
func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
|
||||||
// OK login
|
// OK login
|
||||||
ctx := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeRepo)
|
ctx := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
ctxWithDeleteRepo := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeDeleteRepo)
|
ctxWithDeleteRepo := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
keyname := fmt.Sprintf("%s-push", ctx.Reponame)
|
keyname := fmt.Sprintf("%s-push", ctx.Reponame)
|
||||||
u.Path = ctx.GitPath()
|
u.Path = ctx.GitPath()
|
||||||
|
@ -92,8 +92,8 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
|
||||||
keyname := fmt.Sprintf("%s-push", reponame)
|
keyname := fmt.Sprintf("%s-push", reponame)
|
||||||
|
|
||||||
// OK login
|
// OK login
|
||||||
ctx := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeAdminPublicKey)
|
ctx := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
ctxWithDeleteRepo := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeAdminPublicKey, auth_model.AccessTokenScopeDeleteRepo)
|
ctxWithDeleteRepo := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
otherCtx := ctx
|
otherCtx := ctx
|
||||||
otherCtx.Reponame = "ssh-key-test-repo-2"
|
otherCtx.Reponame = "ssh-key-test-repo-2"
|
||||||
|
|
|
@ -166,7 +166,7 @@ Note: This user hasn't uploaded any GPG keys.
|
||||||
// Import key
|
// Import key
|
||||||
// User1 <user1@example.com>
|
// User1 <user1@example.com>
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteGPGKey)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
|
||||||
testCreateGPGKey(t, session.MakeRequest, token, http.StatusCreated, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
testCreateGPGKey(t, session.MakeRequest, token, http.StatusCreated, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
mQENBFyy/VUBCADJ7zbM20Z1RWmFoVgp5WkQfI2rU1Vj9cQHes9i42wVLLtcbPeo
|
mQENBFyy/VUBCADJ7zbM20Z1RWmFoVgp5WkQfI2rU1Vj9cQHes9i42wVLLtcbPeo
|
||||||
|
|
|
@ -64,6 +64,7 @@ Gitea's private styles use `g-` prefix.
|
||||||
.gt-break-all { word-break: break-all !important; }
|
.gt-break-all { word-break: break-all !important; }
|
||||||
.gt-content-center { align-content: center !important; }
|
.gt-content-center { align-content: center !important; }
|
||||||
.gt-cursor-default { cursor: default !important; }
|
.gt-cursor-default { cursor: default !important; }
|
||||||
|
.gt-cursor-pointer { cursor: pointer !important; }
|
||||||
.gt-invisible { visibility: hidden !important; }
|
.gt-invisible { visibility: hidden !important; }
|
||||||
.gt-items-start { align-items: flex-start !important; }
|
.gt-items-start { align-items: flex-start !important; }
|
||||||
.gt-pointer-events-none { pointer-events: none !important; }
|
.gt-pointer-events-none { pointer-events: none !important; }
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue