Skip to content

Commit 7430221

Browse files
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 <[email protected]> Co-authored-by: techknowlogick <[email protected]>
1 parent 4ec7a65 commit 7430221

File tree

4 files changed

+214
-4
lines changed

4 files changed

+214
-4
lines changed

integrations/api_oauth2_apps_test.go

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ func TestOAuth2Application(t *testing.T) {
1919
defer prepareTestEnv(t)()
2020
testAPICreateOAuth2Application(t)
2121
testAPIListOAuth2Applications(t)
22+
testAPIGetOAuth2Application(t)
23+
testAPIUpdateOAuth2Application(t)
2224
testAPIDeleteOAuth2Application(t)
2325
}
2426

@@ -83,9 +85,6 @@ func testAPIDeleteOAuth2Application(t *testing.T) {
8385
oldApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{
8486
UID: user.ID,
8587
Name: "test-app-1",
86-
RedirectURIs: []string{
87-
"http://www.google.com",
88-
},
8988
}).(*models.OAuth2Application)
9089

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

9594
models.AssertNotExistsBean(t, &models.OAuth2Application{UID: oldApp.UID, Name: oldApp.Name})
9695
}
96+
97+
func testAPIGetOAuth2Application(t *testing.T) {
98+
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
99+
session := loginUser(t, user.Name)
100+
token := getTokenForLoggedInUser(t, session)
101+
102+
existApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{
103+
UID: user.ID,
104+
Name: "test-app-1",
105+
RedirectURIs: []string{
106+
"http://www.google.com",
107+
},
108+
}).(*models.OAuth2Application)
109+
110+
urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d?token=%s", existApp.ID, token)
111+
req := NewRequest(t, "GET", urlStr)
112+
resp := session.MakeRequest(t, req, http.StatusOK)
113+
114+
var app api.OAuth2Application
115+
DecodeJSON(t, resp, &app)
116+
expectedApp := app
117+
118+
assert.EqualValues(t, existApp.Name, expectedApp.Name)
119+
assert.EqualValues(t, existApp.ClientID, expectedApp.ClientID)
120+
assert.Len(t, expectedApp.ClientID, 36)
121+
assert.Empty(t, expectedApp.ClientSecret)
122+
assert.EqualValues(t, len(expectedApp.RedirectURIs), 1)
123+
assert.EqualValues(t, existApp.RedirectURIs[0], expectedApp.RedirectURIs[0])
124+
models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
125+
}
126+
127+
func testAPIUpdateOAuth2Application(t *testing.T) {
128+
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
129+
130+
existApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{
131+
UID: user.ID,
132+
Name: "test-app-1",
133+
RedirectURIs: []string{
134+
"http://www.google.com",
135+
},
136+
}).(*models.OAuth2Application)
137+
138+
appBody := api.CreateOAuth2ApplicationOptions{
139+
Name: "test-app-1",
140+
RedirectURIs: []string{
141+
"http://www.google.com/",
142+
"http://www.github.com/",
143+
},
144+
}
145+
146+
urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d", existApp.ID)
147+
req := NewRequestWithJSON(t, "PATCH", urlStr, &appBody)
148+
req = AddBasicAuthHeader(req, user.Name)
149+
resp := MakeRequest(t, req, http.StatusOK)
150+
151+
var app api.OAuth2Application
152+
DecodeJSON(t, resp, &app)
153+
expectedApp := app
154+
155+
assert.EqualValues(t, len(expectedApp.RedirectURIs), 2)
156+
assert.EqualValues(t, expectedApp.RedirectURIs[0], appBody.RedirectURIs[0])
157+
assert.EqualValues(t, expectedApp.RedirectURIs[1], appBody.RedirectURIs[1])
158+
models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name})
159+
}

routers/api/v1/api.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,10 @@ func RegisterRoutes(m *macaron.Macaron) {
580580
m.Combo("/oauth2").
581581
Get(user.ListOauth2Applications).
582582
Post(bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application)
583-
m.Delete("/oauth2/:id", user.DeleteOauth2Application)
583+
m.Combo("/oauth2/:id").
584+
Delete(user.DeleteOauth2Application).
585+
Patch(bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application).
586+
Get(user.GetOauth2Application)
584587
}, reqToken())
585588

586589
m.Group("/gpg_keys", func() {

routers/api/v1/user/app.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,89 @@ func DeleteOauth2Application(ctx *context.APIContext) {
231231

232232
ctx.Status(http.StatusNoContent)
233233
}
234+
235+
// GetOauth2Application get OAuth2 Application
236+
func GetOauth2Application(ctx *context.APIContext) {
237+
// swagger:operation GET /user/applications/oauth2/{id} user userGetOAuth2Application
238+
// ---
239+
// summary: get an OAuth2 Application
240+
// produces:
241+
// - application/json
242+
// parameters:
243+
// - name: id
244+
// in: path
245+
// description: Application ID to be found
246+
// type: integer
247+
// format: int64
248+
// required: true
249+
// responses:
250+
// "200":
251+
// "$ref": "#/responses/OAuth2Application"
252+
appID := ctx.ParamsInt64(":id")
253+
app, err := models.GetOAuth2ApplicationByID(appID)
254+
if err != nil {
255+
if models.IsErrOauthClientIDInvalid(err) || models.IsErrOAuthApplicationNotFound(err) {
256+
ctx.NotFound()
257+
} else {
258+
ctx.Error(http.StatusInternalServerError, "GetOauth2ApplicationByID", err)
259+
}
260+
return
261+
}
262+
263+
app.ClientSecret = ""
264+
265+
ctx.JSON(http.StatusOK, convert.ToOAuth2Application(app))
266+
}
267+
268+
// UpdateOauth2Application update OAuth2 Application
269+
func UpdateOauth2Application(ctx *context.APIContext, data api.CreateOAuth2ApplicationOptions) {
270+
// swagger:operation PATCH /user/applications/oauth2/{id} user userUpdateOAuth2Application
271+
// ---
272+
// summary: update an OAuth2 Application, this includes regenerating the client secret
273+
// produces:
274+
// - application/json
275+
// parameters:
276+
// - name: id
277+
// in: path
278+
// description: application to be updated
279+
// type: integer
280+
// format: int64
281+
// required: true
282+
// - name: body
283+
// in: body
284+
// required: true
285+
// schema:
286+
// "$ref": "#/definitions/CreateOAuth2ApplicationOptions"
287+
// responses:
288+
// "200":
289+
// "$ref": "#/responses/OAuth2Application"
290+
appID := ctx.ParamsInt64(":id")
291+
292+
err := models.UpdateOAuth2Application(models.UpdateOAuth2ApplicationOptions{
293+
Name: data.Name,
294+
UserID: ctx.User.ID,
295+
ID: appID,
296+
RedirectURIs: data.RedirectURIs,
297+
})
298+
if err != nil {
299+
ctx.Error(http.StatusBadRequest, "", "error updating oauth2 application")
300+
return
301+
}
302+
app, err := models.GetOAuth2ApplicationByID(appID)
303+
if err != nil {
304+
if models.IsErrOauthClientIDInvalid(err) || models.IsErrOAuthApplicationNotFound(err) {
305+
ctx.NotFound()
306+
} else {
307+
ctx.Error(http.StatusInternalServerError, "UpdateOauth2ApplicationByID", err)
308+
}
309+
return
310+
}
311+
secret, err := app.GenerateClientSecret()
312+
if err != nil {
313+
ctx.Error(http.StatusBadRequest, "", "error updating application secret")
314+
return
315+
}
316+
app.ClientSecret = secret
317+
318+
ctx.JSON(http.StatusOK, convert.ToOAuth2Application(app))
319+
}

templates/swagger/v1_json.tmpl

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8360,6 +8360,31 @@
83608360
}
83618361
},
83628362
"/user/applications/oauth2/{id}": {
8363+
"get": {
8364+
"produces": [
8365+
"application/json"
8366+
],
8367+
"tags": [
8368+
"user"
8369+
],
8370+
"summary": "get an OAuth2 Application",
8371+
"operationId": "userGetOAuth2Application",
8372+
"parameters": [
8373+
{
8374+
"type": "integer",
8375+
"format": "int64",
8376+
"description": "Application ID to be found",
8377+
"name": "id",
8378+
"in": "path",
8379+
"required": true
8380+
}
8381+
],
8382+
"responses": {
8383+
"200": {
8384+
"$ref": "#/responses/OAuth2Application"
8385+
}
8386+
}
8387+
},
83638388
"delete": {
83648389
"produces": [
83658390
"application/json"
@@ -8384,6 +8409,39 @@
83848409
"$ref": "#/responses/empty"
83858410
}
83868411
}
8412+
},
8413+
"patch": {
8414+
"produces": [
8415+
"application/json"
8416+
],
8417+
"tags": [
8418+
"user"
8419+
],
8420+
"summary": "update an OAuth2 Application, this includes regenerating the client secret",
8421+
"operationId": "userUpdateOAuth2Application",
8422+
"parameters": [
8423+
{
8424+
"type": "integer",
8425+
"format": "int64",
8426+
"description": "application to be updated",
8427+
"name": "id",
8428+
"in": "path",
8429+
"required": true
8430+
},
8431+
{
8432+
"name": "body",
8433+
"in": "body",
8434+
"required": true,
8435+
"schema": {
8436+
"$ref": "#/definitions/CreateOAuth2ApplicationOptions"
8437+
}
8438+
}
8439+
],
8440+
"responses": {
8441+
"200": {
8442+
"$ref": "#/responses/OAuth2Application"
8443+
}
8444+
}
83878445
}
83888446
},
83898447
"/user/emails": {

0 commit comments

Comments
 (0)