You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

app.go 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package user
  6. import (
  7. "errors"
  8. "fmt"
  9. "net/http"
  10. "strconv"
  11. "code.gitea.io/gitea/models"
  12. "code.gitea.io/gitea/modules/context"
  13. "code.gitea.io/gitea/modules/convert"
  14. api "code.gitea.io/gitea/modules/structs"
  15. "code.gitea.io/gitea/modules/web"
  16. "code.gitea.io/gitea/routers/api/v1/utils"
  17. )
  18. // ListAccessTokens list all the access tokens
  19. func ListAccessTokens(ctx *context.APIContext) {
  20. // swagger:operation GET /users/{username}/tokens user userGetTokens
  21. // ---
  22. // summary: List the authenticated user's access tokens
  23. // produces:
  24. // - application/json
  25. // parameters:
  26. // - name: username
  27. // in: path
  28. // description: username of user
  29. // type: string
  30. // required: true
  31. // - name: page
  32. // in: query
  33. // description: page number of results to return (1-based)
  34. // type: integer
  35. // - name: limit
  36. // in: query
  37. // description: page size of results
  38. // type: integer
  39. // responses:
  40. // "200":
  41. // "$ref": "#/responses/AccessTokenList"
  42. opts := models.ListAccessTokensOptions{UserID: ctx.User.ID, ListOptions: utils.GetListOptions(ctx)}
  43. count, err := models.CountAccessTokens(opts)
  44. if err != nil {
  45. ctx.InternalServerError(err)
  46. return
  47. }
  48. tokens, err := models.ListAccessTokens(opts)
  49. if err != nil {
  50. ctx.InternalServerError(err)
  51. return
  52. }
  53. apiTokens := make([]*api.AccessToken, len(tokens))
  54. for i := range tokens {
  55. apiTokens[i] = &api.AccessToken{
  56. ID: tokens[i].ID,
  57. Name: tokens[i].Name,
  58. TokenLastEight: tokens[i].TokenLastEight,
  59. }
  60. }
  61. ctx.SetTotalCountHeader(count)
  62. ctx.JSON(http.StatusOK, &apiTokens)
  63. }
  64. // CreateAccessToken create access tokens
  65. func CreateAccessToken(ctx *context.APIContext) {
  66. // swagger:operation POST /users/{username}/tokens user userCreateToken
  67. // ---
  68. // summary: Create an access token
  69. // consumes:
  70. // - application/json
  71. // produces:
  72. // - application/json
  73. // parameters:
  74. // - name: username
  75. // in: path
  76. // description: username of user
  77. // type: string
  78. // required: true
  79. // - name: userCreateToken
  80. // in: body
  81. // schema:
  82. // "$ref": "#/definitions/CreateAccessTokenOption"
  83. // responses:
  84. // "201":
  85. // "$ref": "#/responses/AccessToken"
  86. // "400":
  87. // "$ref": "#/responses/error"
  88. form := web.GetForm(ctx).(*api.CreateAccessTokenOption)
  89. t := &models.AccessToken{
  90. UID: ctx.User.ID,
  91. Name: form.Name,
  92. }
  93. exist, err := models.AccessTokenByNameExists(t)
  94. if err != nil {
  95. ctx.InternalServerError(err)
  96. return
  97. }
  98. if exist {
  99. ctx.Error(http.StatusBadRequest, "AccessTokenByNameExists", errors.New("access token name has been used already"))
  100. return
  101. }
  102. if err := models.NewAccessToken(t); err != nil {
  103. ctx.Error(http.StatusInternalServerError, "NewAccessToken", err)
  104. return
  105. }
  106. ctx.JSON(http.StatusCreated, &api.AccessToken{
  107. Name: t.Name,
  108. Token: t.Token,
  109. ID: t.ID,
  110. TokenLastEight: t.TokenLastEight,
  111. })
  112. }
  113. // DeleteAccessToken delete access tokens
  114. func DeleteAccessToken(ctx *context.APIContext) {
  115. // swagger:operation DELETE /users/{username}/tokens/{token} user userDeleteAccessToken
  116. // ---
  117. // summary: delete an access token
  118. // produces:
  119. // - application/json
  120. // parameters:
  121. // - name: username
  122. // in: path
  123. // description: username of user
  124. // type: string
  125. // required: true
  126. // - name: token
  127. // in: path
  128. // description: token to be deleted, identified by ID and if not available by name
  129. // type: string
  130. // required: true
  131. // responses:
  132. // "204":
  133. // "$ref": "#/responses/empty"
  134. // "404":
  135. // "$ref": "#/responses/notFound"
  136. // "422":
  137. // "$ref": "#/responses/error"
  138. token := ctx.Params(":id")
  139. tokenID, _ := strconv.ParseInt(token, 0, 64)
  140. if tokenID == 0 {
  141. tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{
  142. Name: token,
  143. UserID: ctx.User.ID,
  144. })
  145. if err != nil {
  146. ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err)
  147. return
  148. }
  149. switch len(tokens) {
  150. case 0:
  151. ctx.NotFound()
  152. return
  153. case 1:
  154. tokenID = tokens[0].ID
  155. default:
  156. ctx.Error(http.StatusUnprocessableEntity, "DeleteAccessTokenByID", fmt.Errorf("multiple matches for token name '%s'", token))
  157. return
  158. }
  159. }
  160. if tokenID == 0 {
  161. ctx.Error(http.StatusInternalServerError, "Invalid TokenID", nil)
  162. return
  163. }
  164. if err := models.DeleteAccessTokenByID(tokenID, ctx.User.ID); err != nil {
  165. if models.IsErrAccessTokenNotExist(err) {
  166. ctx.NotFound()
  167. } else {
  168. ctx.Error(http.StatusInternalServerError, "DeleteAccessTokenByID", err)
  169. }
  170. return
  171. }
  172. ctx.Status(http.StatusNoContent)
  173. }
  174. // CreateOauth2Application is the handler to create a new OAuth2 Application for the authenticated user
  175. func CreateOauth2Application(ctx *context.APIContext) {
  176. // swagger:operation POST /user/applications/oauth2 user userCreateOAuth2Application
  177. // ---
  178. // summary: creates a new OAuth2 application
  179. // produces:
  180. // - application/json
  181. // parameters:
  182. // - name: body
  183. // in: body
  184. // required: true
  185. // schema:
  186. // "$ref": "#/definitions/CreateOAuth2ApplicationOptions"
  187. // responses:
  188. // "201":
  189. // "$ref": "#/responses/OAuth2Application"
  190. // "400":
  191. // "$ref": "#/responses/error"
  192. data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions)
  193. app, err := models.CreateOAuth2Application(models.CreateOAuth2ApplicationOptions{
  194. Name: data.Name,
  195. UserID: ctx.User.ID,
  196. RedirectURIs: data.RedirectURIs,
  197. })
  198. if err != nil {
  199. ctx.Error(http.StatusBadRequest, "", "error creating oauth2 application")
  200. return
  201. }
  202. secret, err := app.GenerateClientSecret()
  203. if err != nil {
  204. ctx.Error(http.StatusBadRequest, "", "error creating application secret")
  205. return
  206. }
  207. app.ClientSecret = secret
  208. ctx.JSON(http.StatusCreated, convert.ToOAuth2Application(app))
  209. }
  210. // ListOauth2Applications list all the Oauth2 application
  211. func ListOauth2Applications(ctx *context.APIContext) {
  212. // swagger:operation GET /user/applications/oauth2 user userGetOauth2Application
  213. // ---
  214. // summary: List the authenticated user's oauth2 applications
  215. // produces:
  216. // - application/json
  217. // parameters:
  218. // - name: page
  219. // in: query
  220. // description: page number of results to return (1-based)
  221. // type: integer
  222. // - name: limit
  223. // in: query
  224. // description: page size of results
  225. // type: integer
  226. // responses:
  227. // "200":
  228. // "$ref": "#/responses/OAuth2ApplicationList"
  229. apps, total, err := models.ListOAuth2Applications(ctx.User.ID, utils.GetListOptions(ctx))
  230. if err != nil {
  231. ctx.Error(http.StatusInternalServerError, "ListOAuth2Applications", err)
  232. return
  233. }
  234. apiApps := make([]*api.OAuth2Application, len(apps))
  235. for i := range apps {
  236. apiApps[i] = convert.ToOAuth2Application(apps[i])
  237. apiApps[i].ClientSecret = "" // Hide secret on application list
  238. }
  239. ctx.SetTotalCountHeader(total)
  240. ctx.JSON(http.StatusOK, &apiApps)
  241. }
  242. // DeleteOauth2Application delete OAuth2 Application
  243. func DeleteOauth2Application(ctx *context.APIContext) {
  244. // swagger:operation DELETE /user/applications/oauth2/{id} user userDeleteOAuth2Application
  245. // ---
  246. // summary: delete an OAuth2 Application
  247. // produces:
  248. // - application/json
  249. // parameters:
  250. // - name: id
  251. // in: path
  252. // description: token to be deleted
  253. // type: integer
  254. // format: int64
  255. // required: true
  256. // responses:
  257. // "204":
  258. // "$ref": "#/responses/empty"
  259. // "404":
  260. // "$ref": "#/responses/notFound"
  261. appID := ctx.ParamsInt64(":id")
  262. if err := models.DeleteOAuth2Application(appID, ctx.User.ID); err != nil {
  263. if models.IsErrOAuthApplicationNotFound(err) {
  264. ctx.NotFound()
  265. } else {
  266. ctx.Error(http.StatusInternalServerError, "DeleteOauth2ApplicationByID", err)
  267. }
  268. return
  269. }
  270. ctx.Status(http.StatusNoContent)
  271. }
  272. // GetOauth2Application get OAuth2 Application
  273. func GetOauth2Application(ctx *context.APIContext) {
  274. // swagger:operation GET /user/applications/oauth2/{id} user userGetOAuth2Application
  275. // ---
  276. // summary: get an OAuth2 Application
  277. // produces:
  278. // - application/json
  279. // parameters:
  280. // - name: id
  281. // in: path
  282. // description: Application ID to be found
  283. // type: integer
  284. // format: int64
  285. // required: true
  286. // responses:
  287. // "200":
  288. // "$ref": "#/responses/OAuth2Application"
  289. // "404":
  290. // "$ref": "#/responses/notFound"
  291. appID := ctx.ParamsInt64(":id")
  292. app, err := models.GetOAuth2ApplicationByID(appID)
  293. if err != nil {
  294. if models.IsErrOauthClientIDInvalid(err) || models.IsErrOAuthApplicationNotFound(err) {
  295. ctx.NotFound()
  296. } else {
  297. ctx.Error(http.StatusInternalServerError, "GetOauth2ApplicationByID", err)
  298. }
  299. return
  300. }
  301. app.ClientSecret = ""
  302. ctx.JSON(http.StatusOK, convert.ToOAuth2Application(app))
  303. }
  304. // UpdateOauth2Application update OAuth2 Application
  305. func UpdateOauth2Application(ctx *context.APIContext) {
  306. // swagger:operation PATCH /user/applications/oauth2/{id} user userUpdateOAuth2Application
  307. // ---
  308. // summary: update an OAuth2 Application, this includes regenerating the client secret
  309. // produces:
  310. // - application/json
  311. // parameters:
  312. // - name: id
  313. // in: path
  314. // description: application to be updated
  315. // type: integer
  316. // format: int64
  317. // required: true
  318. // - name: body
  319. // in: body
  320. // required: true
  321. // schema:
  322. // "$ref": "#/definitions/CreateOAuth2ApplicationOptions"
  323. // responses:
  324. // "200":
  325. // "$ref": "#/responses/OAuth2Application"
  326. // "404":
  327. // "$ref": "#/responses/notFound"
  328. appID := ctx.ParamsInt64(":id")
  329. data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions)
  330. app, err := models.UpdateOAuth2Application(models.UpdateOAuth2ApplicationOptions{
  331. Name: data.Name,
  332. UserID: ctx.User.ID,
  333. ID: appID,
  334. RedirectURIs: data.RedirectURIs,
  335. })
  336. if err != nil {
  337. if models.IsErrOauthClientIDInvalid(err) || models.IsErrOAuthApplicationNotFound(err) {
  338. ctx.NotFound()
  339. } else {
  340. ctx.Error(http.StatusInternalServerError, "UpdateOauth2ApplicationByID", err)
  341. }
  342. return
  343. }
  344. app.ClientSecret, err = app.GenerateClientSecret()
  345. if err != nil {
  346. ctx.Error(http.StatusBadRequest, "", "error updating application secret")
  347. return
  348. }
  349. ctx.JSON(http.StatusOK, convert.ToOAuth2Application(app))
  350. }