mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-22 12:54:53 -05:00
Add Get/Update for api/v1/user/applications/oauth2 (#11008)
Add api methods for getting and updating user oauth2 applications. Signed-off-by: Dan Molik <dan@danmolik.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
4ec7a659ce
commit
743022116d
4 changed files with 214 additions and 4 deletions
|
@ -19,6 +19,8 @@ func TestOAuth2Application(t *testing.T) {
|
||||||
defer prepareTestEnv(t)()
|
defer prepareTestEnv(t)()
|
||||||
testAPICreateOAuth2Application(t)
|
testAPICreateOAuth2Application(t)
|
||||||
testAPIListOAuth2Applications(t)
|
testAPIListOAuth2Applications(t)
|
||||||
|
testAPIGetOAuth2Application(t)
|
||||||
|
testAPIUpdateOAuth2Application(t)
|
||||||
testAPIDeleteOAuth2Application(t)
|
testAPIDeleteOAuth2Application(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,9 +85,6 @@ func testAPIDeleteOAuth2Application(t *testing.T) {
|
||||||
oldApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{
|
oldApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{
|
||||||
UID: user.ID,
|
UID: user.ID,
|
||||||
Name: "test-app-1",
|
Name: "test-app-1",
|
||||||
RedirectURIs: []string{
|
|
||||||
"http://www.google.com",
|
|
||||||
},
|
|
||||||
}).(*models.OAuth2Application)
|
}).(*models.OAuth2Application)
|
||||||
|
|
||||||
urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d?token=%s", oldApp.ID, token)
|
urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d?token=%s", oldApp.ID, token)
|
||||||
|
@ -94,3 +93,67 @@ func testAPIDeleteOAuth2Application(t *testing.T) {
|
||||||
|
|
||||||
models.AssertNotExistsBean(t, &models.OAuth2Application{UID: oldApp.UID, Name: oldApp.Name})
|
models.AssertNotExistsBean(t, &models.OAuth2Application{UID: oldApp.UID, Name: oldApp.Name})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAPIGetOAuth2Application(t *testing.T) {
|
||||||
|
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||||
|
session := loginUser(t, user.Name)
|
||||||
|
token := getTokenForLoggedInUser(t, session)
|
||||||
|
|
||||||
|
existApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{
|
||||||
|
UID: user.ID,
|
||||||
|
Name: "test-app-1",
|
||||||
|
RedirectURIs: []string{
|
||||||
|
"http://www.google.com",
|
||||||
|
},
|
||||||
|
}).(*models.OAuth2Application)
|
||||||
|
|
||||||
|
urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d?token=%s", existApp.ID, token)
|
||||||
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
var app api.OAuth2Application
|
||||||
|
DecodeJSON(t, resp, &app)
|
||||||
|
expectedApp := app
|
||||||
|
|
||||||
|
assert.EqualValues(t, existApp.Name, expectedApp.Name)
|
||||||
|
assert.EqualValues(t, existApp.ClientID, expectedApp.ClientID)
|
||||||
|
assert.Len(t, expectedApp.ClientID, 36)
|
||||||
|
assert.Empty(t, expectedApp.ClientSecret)
|
||||||
|
assert.EqualValues(t, len(expectedApp.RedirectURIs), 1)
|
||||||
|
assert.EqualValues(t, existApp.RedirectURIs[0], expectedApp.RedirectURIs[0])
|
||||||
|
models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAPIUpdateOAuth2Application(t *testing.T) {
|
||||||
|
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||||
|
|
||||||
|
existApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{
|
||||||
|
UID: user.ID,
|
||||||
|
Name: "test-app-1",
|
||||||
|
RedirectURIs: []string{
|
||||||
|
"http://www.google.com",
|
||||||
|
},
|
||||||
|
}).(*models.OAuth2Application)
|
||||||
|
|
||||||
|
appBody := api.CreateOAuth2ApplicationOptions{
|
||||||
|
Name: "test-app-1",
|
||||||
|
RedirectURIs: []string{
|
||||||
|
"http://www.google.com/",
|
||||||
|
"http://www.github.com/",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d", existApp.ID)
|
||||||
|
req := NewRequestWithJSON(t, "PATCH", urlStr, &appBody)
|
||||||
|
req = AddBasicAuthHeader(req, user.Name)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
var app api.OAuth2Application
|
||||||
|
DecodeJSON(t, resp, &app)
|
||||||
|
expectedApp := app
|
||||||
|
|
||||||
|
assert.EqualValues(t, len(expectedApp.RedirectURIs), 2)
|
||||||
|
assert.EqualValues(t, expectedApp.RedirectURIs[0], appBody.RedirectURIs[0])
|
||||||
|
assert.EqualValues(t, expectedApp.RedirectURIs[1], appBody.RedirectURIs[1])
|
||||||
|
models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
|
||||||
|
}
|
||||||
|
|
|
@ -580,7 +580,10 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Combo("/oauth2").
|
m.Combo("/oauth2").
|
||||||
Get(user.ListOauth2Applications).
|
Get(user.ListOauth2Applications).
|
||||||
Post(bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application)
|
Post(bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application)
|
||||||
m.Delete("/oauth2/:id", user.DeleteOauth2Application)
|
m.Combo("/oauth2/:id").
|
||||||
|
Delete(user.DeleteOauth2Application).
|
||||||
|
Patch(bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application).
|
||||||
|
Get(user.GetOauth2Application)
|
||||||
}, reqToken())
|
}, reqToken())
|
||||||
|
|
||||||
m.Group("/gpg_keys", func() {
|
m.Group("/gpg_keys", func() {
|
||||||
|
|
|
@ -231,3 +231,89 @@ func DeleteOauth2Application(ctx *context.APIContext) {
|
||||||
|
|
||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOauth2Application get OAuth2 Application
|
||||||
|
func GetOauth2Application(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /user/applications/oauth2/{id} user userGetOAuth2Application
|
||||||
|
// ---
|
||||||
|
// summary: get an OAuth2 Application
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: id
|
||||||
|
// in: path
|
||||||
|
// description: Application ID to be found
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/OAuth2Application"
|
||||||
|
appID := ctx.ParamsInt64(":id")
|
||||||
|
app, err := models.GetOAuth2ApplicationByID(appID)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrOauthClientIDInvalid(err) || models.IsErrOAuthApplicationNotFound(err) {
|
||||||
|
ctx.NotFound()
|
||||||
|
} else {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetOauth2ApplicationByID", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
app.ClientSecret = ""
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, convert.ToOAuth2Application(app))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOauth2Application update OAuth2 Application
|
||||||
|
func UpdateOauth2Application(ctx *context.APIContext, data api.CreateOAuth2ApplicationOptions) {
|
||||||
|
// swagger:operation PATCH /user/applications/oauth2/{id} user userUpdateOAuth2Application
|
||||||
|
// ---
|
||||||
|
// summary: update an OAuth2 Application, this includes regenerating the client secret
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: id
|
||||||
|
// in: path
|
||||||
|
// description: application to be updated
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// - name: body
|
||||||
|
// in: body
|
||||||
|
// required: true
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/CreateOAuth2ApplicationOptions"
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/OAuth2Application"
|
||||||
|
appID := ctx.ParamsInt64(":id")
|
||||||
|
|
||||||
|
err := models.UpdateOAuth2Application(models.UpdateOAuth2ApplicationOptions{
|
||||||
|
Name: data.Name,
|
||||||
|
UserID: ctx.User.ID,
|
||||||
|
ID: appID,
|
||||||
|
RedirectURIs: data.RedirectURIs,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusBadRequest, "", "error updating oauth2 application")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
app, err := models.GetOAuth2ApplicationByID(appID)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrOauthClientIDInvalid(err) || models.IsErrOAuthApplicationNotFound(err) {
|
||||||
|
ctx.NotFound()
|
||||||
|
} else {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "UpdateOauth2ApplicationByID", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
secret, err := app.GenerateClientSecret()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusBadRequest, "", "error updating application secret")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
app.ClientSecret = secret
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, convert.ToOAuth2Application(app))
|
||||||
|
}
|
||||||
|
|
|
@ -8360,6 +8360,31 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/user/applications/oauth2/{id}": {
|
"/user/applications/oauth2/{id}": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "get an OAuth2 Application",
|
||||||
|
"operationId": "userGetOAuth2Application",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "Application ID to be found",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/OAuth2Application"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
|
@ -8384,6 +8409,39 @@
|
||||||
"$ref": "#/responses/empty"
|
"$ref": "#/responses/empty"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"patch": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "update an OAuth2 Application, this includes regenerating the client secret",
|
||||||
|
"operationId": "userUpdateOAuth2Application",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "application to be updated",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/CreateOAuth2ApplicationOptions"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/OAuth2Application"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/user/emails": {
|
"/user/emails": {
|
||||||
|
|
Loading…
Reference in a new issue