aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/auth/token_scope.go25
-rw-r--r--modules/structs/user_app.go14
-rw-r--r--options/locale/locale_en-US.ini1
-rw-r--r--routers/api/v1/user/app.go13
-rw-r--r--templates/swagger/v1_json.tmpl20
-rw-r--r--templates/user/settings/applications.tmpl9
6 files changed, 68 insertions, 14 deletions
diff --git a/models/auth/token_scope.go b/models/auth/token_scope.go
index c61c306496..38733a1c8f 100644
--- a/models/auth/token_scope.go
+++ b/models/auth/token_scope.go
@@ -168,10 +168,23 @@ var allAccessTokenScopeBits = map[AccessTokenScope]AccessTokenScopeBitmap{
// Parse parses the scope string into a bitmap, thus removing possible duplicates.
func (s AccessTokenScope) Parse() (AccessTokenScopeBitmap, error) {
- list := strings.Split(string(s), ",")
-
var bitmap AccessTokenScopeBitmap
- for _, v := range list {
+
+ // 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
@@ -187,9 +200,15 @@ func (s AccessTokenScope) Parse() (AccessTokenScopeBitmap, error) {
}
bitmap |= bits
}
+
return bitmap, nil
}
+// StringSlice returns the AccessTokenScope as a []string
+func (s AccessTokenScope) StringSlice() []string {
+ return strings.Split(string(s), ",")
+}
+
// Normalize returns a normalized scope string without any duplicates.
func (s AccessTokenScope) Normalize() (AccessTokenScope, error) {
bitmap, err := s.Parse()
diff --git a/modules/structs/user_app.go b/modules/structs/user_app.go
index 3a5ae34df1..7f78fbd495 100644
--- a/modules/structs/user_app.go
+++ b/modules/structs/user_app.go
@@ -11,10 +11,11 @@ import (
// AccessToken represents an API access token.
// swagger:response AccessToken
type AccessToken struct {
- ID int64 `json:"id"`
- Name string `json:"name"`
- Token string `json:"sha1"`
- TokenLastEight string `json:"token_last_eight"`
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ Token string `json:"sha1"`
+ TokenLastEight string `json:"token_last_eight"`
+ Scopes []string `json:"scopes"`
}
// AccessTokenList represents a list of API access token.
@@ -22,9 +23,10 @@ type AccessToken struct {
type AccessTokenList []*AccessToken
// CreateAccessTokenOption options when create access token
-// swagger:parameters userCreateToken
type CreateAccessTokenOption struct {
- Name string `json:"name" binding:"Required"`
+ // required: true
+ Name string `json:"name" binding:"Required"`
+ Scopes []string `json:"scopes"`
}
// CreateOAuth2ApplicationOptions holds options to create an oauth2 application
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 92ca5be8d3..df66ce2339 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -757,6 +757,7 @@ access_token_deletion_confirm_action = Delete
access_token_deletion_desc = Deleting a token will revoke access to your account for applications using it. This cannot be undone. Continue?
delete_token_success = The token has been deleted. Applications using it no longer have access to your account.
select_scopes = Select scopes
+scopes_list = Scopes:
manage_oauth2_applications = Manage OAuth2 Applications
edit_oauth2_application = Edit OAuth2 Application
diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go
index 7b2f0d8c30..f89d53945f 100644
--- a/routers/api/v1/user/app.go
+++ b/routers/api/v1/user/app.go
@@ -9,6 +9,7 @@ import (
"fmt"
"net/http"
"strconv"
+ "strings"
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/modules/context"
@@ -62,6 +63,7 @@ func ListAccessTokens(ctx *context.APIContext) {
ID: tokens[i].ID,
Name: tokens[i].Name,
TokenLastEight: tokens[i].TokenLastEight,
+ Scopes: tokens[i].Scope.StringSlice(),
}
}
@@ -82,9 +84,9 @@ func CreateAccessToken(ctx *context.APIContext) {
// - name: username
// in: path
// description: username of user
- // type: string
// required: true
- // - name: userCreateToken
+ // type: string
+ // - name: body
// in: body
// schema:
// "$ref": "#/definitions/CreateAccessTokenOption"
@@ -111,6 +113,13 @@ func CreateAccessToken(ctx *context.APIContext) {
return
}
+ scope, err := auth_model.AccessTokenScope(strings.Join(form.Scopes, ",")).Normalize()
+ if err != nil {
+ ctx.Error(http.StatusBadRequest, "AccessTokenScope.Normalize", fmt.Errorf("invalid access token scope provided: %w", err))
+ return
+ }
+ t.Scope = scope
+
if err := auth_model.NewAccessToken(t); err != nil {
ctx.Error(http.StatusInternalServerError, "NewAccessToken", err)
return
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 2a675766ab..de774deaed 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -14084,14 +14084,13 @@
"parameters": [
{
"type": "string",
- "x-go-name": "Name",
"description": "username of user",
"name": "username",
"in": "path",
"required": true
},
{
- "name": "userCreateToken",
+ "name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/CreateAccessTokenOption"
@@ -14194,6 +14193,13 @@
"type": "string",
"x-go-name": "Name"
},
+ "scopes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Scopes"
+ },
"sha1": {
"type": "string",
"x-go-name": "Token"
@@ -14925,10 +14931,20 @@
"CreateAccessTokenOption": {
"description": "CreateAccessTokenOption options when create access token",
"type": "object",
+ "required": [
+ "name"
+ ],
"properties": {
"name": {
"type": "string",
"x-go-name": "Name"
+ },
+ "scopes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Scopes"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
diff --git a/templates/user/settings/applications.tmpl b/templates/user/settings/applications.tmpl
index 439ed5e148..ef9ac9a977 100644
--- a/templates/user/settings/applications.tmpl
+++ b/templates/user/settings/applications.tmpl
@@ -21,7 +21,14 @@
</div>
<i class="icon tooltip{{if .HasRecentActivity}} green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.token_state_desc"}}"{{end}}>{{svg "fontawesome-send" 36}}</i>
<div class="content">
- <strong>{{.Name}}</strong>
+ <details><summary><strong>{{.Name}}</strong></summary>
+ <p class="gt-my-2">{{$.locale.Tr "settings.scopes_list"}}</p>
+ <ul class="gt-my-2">
+ {{range .Scope.StringSlice}}
+ <li>{{.}}</li>
+ {{end}}
+ </ul>
+ </details>
<div class="activity meta">
<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span> — {{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}><time data-format="short-date" datetime="{{.UpdatedUnix.FormatLong}}">{{.UpdatedUnix.FormatShort}}</time></span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
</div>