Add sudo functionality to the API (#4809)
This commit is contained in:
parent
e6a03813d4
commit
d293a2b9d6
|
@ -73,3 +73,7 @@ using BasicAuth, as follows:
|
||||||
$ curl --request GET --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
|
$ curl --request GET --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
|
||||||
[{"name":"test","sha1":"..."},{"name":"dev","sha1":"..."}]
|
[{"name":"test","sha1":"..."},{"name":"dev","sha1":"..."}]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Sudo
|
||||||
|
|
||||||
|
The API allows admin users to sudo API requests as another user. Simply add either a `sudo=` parameter or `Sudo:` request header with the username of the user to sudo.
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
api "code.gitea.io/sdk/gitea"
|
api "code.gitea.io/sdk/gitea"
|
||||||
)
|
)
|
||||||
|
@ -71,3 +73,30 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
|
||||||
adminUsername, newPublicKey.ID)
|
adminUsername, newPublicKey.ID)
|
||||||
session.MakeRequest(t, req, http.StatusForbidden)
|
session.MakeRequest(t, req, http.StatusForbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPISudoUser(t *testing.T) {
|
||||||
|
prepareTestEnv(t)
|
||||||
|
adminUsername := "user1"
|
||||||
|
normalUsername := "user2"
|
||||||
|
session := loginUser(t, adminUsername)
|
||||||
|
|
||||||
|
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s", normalUsername)
|
||||||
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
var user api.User
|
||||||
|
DecodeJSON(t, resp, &user)
|
||||||
|
|
||||||
|
assert.Equal(t, normalUsername, user.UserName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPISudoUserForbidden(t *testing.T) {
|
||||||
|
prepareTestEnv(t)
|
||||||
|
adminUsername := "user1"
|
||||||
|
normalUsername := "user2"
|
||||||
|
|
||||||
|
session := loginUser(t, normalUsername)
|
||||||
|
|
||||||
|
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s", adminUsername)
|
||||||
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
session.MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
// - Token :
|
// - Token :
|
||||||
// - AccessToken :
|
// - AccessToken :
|
||||||
// - AuthorizationHeaderToken :
|
// - AuthorizationHeaderToken :
|
||||||
|
// - SudoParam :
|
||||||
|
// - SudoHeader :
|
||||||
//
|
//
|
||||||
// SecurityDefinitions:
|
// SecurityDefinitions:
|
||||||
// BasicAuth:
|
// BasicAuth:
|
||||||
|
@ -40,6 +42,16 @@
|
||||||
// type: apiKey
|
// type: apiKey
|
||||||
// name: Authorization
|
// name: Authorization
|
||||||
// in: header
|
// in: header
|
||||||
|
// SudoParam:
|
||||||
|
// type: apiKey
|
||||||
|
// name: sudo
|
||||||
|
// in: query
|
||||||
|
// description: Sudo API request as the user provided as the key. Admin privileges are required.
|
||||||
|
// SudoHeader:
|
||||||
|
// type: apiKey
|
||||||
|
// name: Sudo
|
||||||
|
// in: header
|
||||||
|
// description: Sudo API request as the user provided as the key. Admin privileges are required.
|
||||||
//
|
//
|
||||||
// swagger:meta
|
// swagger:meta
|
||||||
package v1
|
package v1
|
||||||
|
@ -50,6 +62,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/auth"
|
"code.gitea.io/gitea/modules/auth"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/routers/api/v1/admin"
|
"code.gitea.io/gitea/routers/api/v1/admin"
|
||||||
"code.gitea.io/gitea/routers/api/v1/misc"
|
"code.gitea.io/gitea/routers/api/v1/misc"
|
||||||
|
@ -64,6 +77,36 @@ import (
|
||||||
"gopkg.in/macaron.v1"
|
"gopkg.in/macaron.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func sudo() macaron.Handler {
|
||||||
|
return func(ctx *context.APIContext) {
|
||||||
|
sudo := ctx.Query("sudo")
|
||||||
|
if len(sudo) <= 0 {
|
||||||
|
sudo = ctx.Req.Header.Get("Sudo")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sudo) > 0 {
|
||||||
|
if ctx.User.IsAdmin {
|
||||||
|
user, err := models.GetUserByName(sudo)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.Status(404)
|
||||||
|
} else {
|
||||||
|
ctx.Error(500, "GetUserByName", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Trace("Sudo from (%s) to: %s", ctx.User.Name, user.Name)
|
||||||
|
ctx.User = user
|
||||||
|
} else {
|
||||||
|
ctx.JSON(403, map[string]string{
|
||||||
|
"message": "Only administrators allowed to sudo.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func repoAssignment() macaron.Handler {
|
func repoAssignment() macaron.Handler {
|
||||||
return func(ctx *context.APIContext) {
|
return func(ctx *context.APIContext) {
|
||||||
userName := ctx.Params(":username")
|
userName := ctx.Params(":username")
|
||||||
|
@ -589,5 +632,5 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Group("/topics", func() {
|
m.Group("/topics", func() {
|
||||||
m.Get("/search", repo.TopicSearch)
|
m.Get("/search", repo.TopicSearch)
|
||||||
})
|
})
|
||||||
}, context.APIContexter())
|
}, context.APIContexter(), sudo())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8008,6 +8008,18 @@
|
||||||
"BasicAuth": {
|
"BasicAuth": {
|
||||||
"type": "basic"
|
"type": "basic"
|
||||||
},
|
},
|
||||||
|
"SudoHeader": {
|
||||||
|
"description": "Sudo API request as the user provided as the key. Admin privileges are required.",
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "Sudo",
|
||||||
|
"in": "header"
|
||||||
|
},
|
||||||
|
"SudoParam": {
|
||||||
|
"description": "Sudo API request as the user provided as the key. Admin privileges are required.",
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "sudo",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
"Token": {
|
"Token": {
|
||||||
"type": "apiKey",
|
"type": "apiKey",
|
||||||
"name": "token",
|
"name": "token",
|
||||||
|
@ -8026,6 +8038,12 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"AuthorizationHeaderToken": []
|
"AuthorizationHeaderToken": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SudoParam": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SudoHeader": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Reference in New Issue