Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Get/Update for api/v1/user/applications/oauth2 #11008

Merged
merged 2 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 66 additions & 3 deletions integrations/api_oauth2_apps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ func TestOAuth2Application(t *testing.T) {
defer prepareTestEnv(t)()
testAPICreateOAuth2Application(t)
testAPIListOAuth2Applications(t)
testAPIGetOAuth2Application(t)
testAPIUpdateOAuth2Application(t)
testAPIDeleteOAuth2Application(t)
}

Expand Down Expand Up @@ -83,9 +85,6 @@ func testAPIDeleteOAuth2Application(t *testing.T) {
oldApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{
UID: user.ID,
Name: "test-app-1",
RedirectURIs: []string{
dmolik marked this conversation as resolved.
Show resolved Hide resolved
"http:https://www.google.com",
},
}).(*models.OAuth2Application)

urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d?token=%s", oldApp.ID, token)
Expand All @@ -94,3 +93,67 @@ func testAPIDeleteOAuth2Application(t *testing.T) {

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:https://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:https://www.google.com",
},
}).(*models.OAuth2Application)

appBody := api.CreateOAuth2ApplicationOptions{
Name: "test-app-1",
RedirectURIs: []string{
"http:https://www.google.com/",
"http:https://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})
}
5 changes: 4 additions & 1 deletion routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,10 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/oauth2").
Get(user.ListOauth2Applications).
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())

m.Group("/gpg_keys", func() {
Expand Down
86 changes: 86 additions & 0 deletions routers/api/v1/user/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,89 @@ func DeleteOauth2Application(ctx *context.APIContext) {

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))
dmolik marked this conversation as resolved.
Show resolved Hide resolved
}

// 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)
dmolik marked this conversation as resolved.
Show resolved Hide resolved
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))
}
58 changes: 58 additions & 0 deletions templates/swagger/v1_json.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8360,6 +8360,31 @@
}
},
"/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": {
"produces": [
"application/json"
Expand All @@ -8384,6 +8409,39 @@
"$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": {
Expand Down