2014-11-18 19:07:16 +03:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2018-07-07 04:54:30 +03:00
// Copyright 2018 The Gitea Authors. All rights reserved.
2014-11-18 19:07:16 +03:00
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2015-12-05 01:16:42 +03:00
package user
2014-11-18 19:07:16 +03:00
import (
2020-04-13 22:02:48 +03:00
"errors"
2020-08-28 11:09:33 +03:00
"fmt"
2019-12-20 20:07:12 +03:00
"net/http"
2020-08-28 11:09:33 +03:00
"strconv"
2019-12-20 20:07:12 +03:00
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
2020-02-29 09:19:32 +03:00
"code.gitea.io/gitea/modules/convert"
2019-08-23 19:40:30 +03:00
api "code.gitea.io/gitea/modules/structs"
2020-01-24 22:00:29 +03:00
"code.gitea.io/gitea/routers/api/v1/utils"
2014-11-18 19:07:16 +03:00
)
2016-11-24 10:04:31 +03:00
// ListAccessTokens list all the access tokens
2016-03-14 01:49:16 +03:00
func ListAccessTokens ( ctx * context . APIContext ) {
2017-11-13 10:02:25 +03:00
// swagger:operation GET /users/{username}/tokens user userGetTokens
// ---
// summary: List the authenticated user's access tokens
// produces:
// - application/json
2018-06-12 17:59:22 +03:00
// parameters:
// - name: username
// in: path
// description: username of user
// type: string
// required: true
2020-01-24 22:00:29 +03:00
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
2020-06-09 07:57:38 +03:00
// description: page size of results
2020-01-24 22:00:29 +03:00
// type: integer
2017-11-13 10:02:25 +03:00
// responses:
// "200":
// "$ref": "#/responses/AccessTokenList"
2019-12-20 20:07:12 +03:00
2020-08-28 11:09:33 +03:00
tokens , err := models . ListAccessTokens ( models . ListAccessTokensOptions { UserID : ctx . User . ID , ListOptions : utils . GetListOptions ( ctx ) } )
2014-11-18 19:07:16 +03:00
if err != nil {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "ListAccessTokens" , err )
2014-11-18 19:07:16 +03:00
return
}
apiTokens := make ( [ ] * api . AccessToken , len ( tokens ) )
for i := range tokens {
2017-02-26 08:25:35 +03:00
apiTokens [ i ] = & api . AccessToken {
2019-05-04 18:45:34 +03:00
ID : tokens [ i ] . ID ,
Name : tokens [ i ] . Name ,
TokenLastEight : tokens [ i ] . TokenLastEight ,
2017-02-26 08:25:35 +03:00
}
2014-11-18 19:07:16 +03:00
}
2019-12-20 20:07:12 +03:00
ctx . JSON ( http . StatusOK , & apiTokens )
2014-11-18 19:07:16 +03:00
}
2016-11-24 10:04:31 +03:00
// CreateAccessToken create access tokens
2016-03-14 01:49:16 +03:00
func CreateAccessToken ( ctx * context . APIContext , form api . CreateAccessTokenOption ) {
2017-11-13 10:02:25 +03:00
// swagger:operation POST /users/{username}/tokens user userCreateToken
// ---
// summary: Create an access token
// consumes:
// - application/json
// produces:
// - application/json
2018-06-12 17:59:22 +03:00
// parameters:
// - name: username
// in: path
// description: username of user
// type: string
// required: true
2018-10-21 06:40:42 +03:00
// - name: accessToken
// in: body
// schema:
// type: object
// required:
// - name
// properties:
// name:
// type: string
2017-11-13 10:02:25 +03:00
// responses:
// "200":
// "$ref": "#/responses/AccessToken"
2019-12-20 20:07:12 +03:00
2014-11-18 19:07:16 +03:00
t := & models . AccessToken {
2016-07-23 20:08:22 +03:00
UID : ctx . User . ID ,
2014-11-18 19:07:16 +03:00
Name : form . Name ,
}
2020-04-13 22:02:48 +03:00
exist , err := models . AccessTokenByNameExists ( t )
if err != nil {
ctx . InternalServerError ( err )
return
}
if exist {
ctx . Error ( http . StatusBadRequest , "AccessTokenByNameExists" , errors . New ( "access token name has been used already" ) )
return
}
2014-11-18 19:07:16 +03:00
if err := models . NewAccessToken ( t ) ; err != nil {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "NewAccessToken" , err )
2014-11-18 19:07:16 +03:00
return
}
2019-12-20 20:07:12 +03:00
ctx . JSON ( http . StatusCreated , & api . AccessToken {
2019-05-12 20:29:07 +03:00
Name : t . Name ,
Token : t . Token ,
ID : t . ID ,
TokenLastEight : t . TokenLastEight ,
2017-02-26 08:25:35 +03:00
} )
2014-11-18 19:07:16 +03:00
}
2018-07-07 04:54:30 +03:00
// DeleteAccessToken delete access tokens
func DeleteAccessToken ( ctx * context . APIContext ) {
// swagger:operation DELETE /users/{username}/tokens/{token} user userDeleteAccessToken
// ---
// summary: delete an access token
// produces:
// - application/json
// parameters:
// - name: username
// in: path
// description: username of user
// type: string
// required: true
// - name: token
// in: path
2020-08-28 11:09:33 +03:00
// description: token to be deleted, identified by ID and if not available by name
// type: string
2018-07-07 04:54:30 +03:00
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
2020-08-28 11:09:33 +03:00
// "422":
// "$ref": "#/responses/error"
token := ctx . Params ( ":id" )
tokenID , _ := strconv . ParseInt ( token , 0 , 64 )
if tokenID == 0 {
tokens , err := models . ListAccessTokens ( models . ListAccessTokensOptions {
Name : token ,
UserID : ctx . User . ID ,
} )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "ListAccessTokens" , err )
return
}
switch len ( tokens ) {
case 0 :
ctx . NotFound ( )
return
case 1 :
tokenID = tokens [ 0 ] . ID
default :
ctx . Error ( http . StatusUnprocessableEntity , "DeleteAccessTokenByID" , fmt . Errorf ( "multible matches for token name '%s'" , token ) )
return
}
}
if tokenID == 0 {
ctx . Error ( http . StatusInternalServerError , "Invalid TokenID" , nil )
return
}
2019-12-20 20:07:12 +03:00
2018-07-07 04:54:30 +03:00
if err := models . DeleteAccessTokenByID ( tokenID , ctx . User . ID ) ; err != nil {
if models . IsErrAccessTokenNotExist ( err ) {
2019-03-19 05:29:43 +03:00
ctx . NotFound ( )
2018-07-07 04:54:30 +03:00
} else {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "DeleteAccessTokenByID" , err )
2018-07-07 04:54:30 +03:00
}
return
}
2019-12-20 20:07:12 +03:00
ctx . Status ( http . StatusNoContent )
2018-07-07 04:54:30 +03:00
}
2020-02-29 09:19:32 +03:00
// CreateOauth2Application is the handler to create a new OAuth2 Application for the authenticated user
func CreateOauth2Application ( ctx * context . APIContext , data api . CreateOAuth2ApplicationOptions ) {
// swagger:operation POST /user/applications/oauth2 user userCreateOAuth2Application
// ---
// summary: creates a new OAuth2 application
// produces:
// - application/json
// parameters:
// - name: body
// in: body
// required: true
// schema:
// "$ref": "#/definitions/CreateOAuth2ApplicationOptions"
// responses:
// "201":
// "$ref": "#/responses/OAuth2Application"
app , err := models . CreateOAuth2Application ( models . CreateOAuth2ApplicationOptions {
Name : data . Name ,
UserID : ctx . User . ID ,
RedirectURIs : data . RedirectURIs ,
} )
if err != nil {
ctx . Error ( http . StatusBadRequest , "" , "error creating oauth2 application" )
return
}
secret , err := app . GenerateClientSecret ( )
if err != nil {
ctx . Error ( http . StatusBadRequest , "" , "error creating application secret" )
return
}
app . ClientSecret = secret
ctx . JSON ( http . StatusCreated , convert . ToOAuth2Application ( app ) )
}
// ListOauth2Applications list all the Oauth2 application
func ListOauth2Applications ( ctx * context . APIContext ) {
// swagger:operation GET /user/applications/oauth2 user userGetOauth2Application
// ---
// summary: List the authenticated user's oauth2 applications
// produces:
// - application/json
// parameters:
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
2020-06-09 07:57:38 +03:00
// description: page size of results
2020-02-29 09:19:32 +03:00
// type: integer
// responses:
// "200":
// "$ref": "#/responses/OAuth2ApplicationList"
apps , err := models . ListOAuth2Applications ( ctx . User . ID , utils . GetListOptions ( ctx ) )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "ListOAuth2Applications" , err )
return
}
apiApps := make ( [ ] * api . OAuth2Application , len ( apps ) )
for i := range apps {
apiApps [ i ] = convert . ToOAuth2Application ( apps [ i ] )
apiApps [ i ] . ClientSecret = "" // Hide secret on application list
}
ctx . JSON ( http . StatusOK , & apiApps )
}
// DeleteOauth2Application delete OAuth2 Application
func DeleteOauth2Application ( ctx * context . APIContext ) {
// swagger:operation DELETE /user/applications/oauth2/{id} user userDeleteOAuth2Application
// ---
// summary: delete an OAuth2 Application
// produces:
// - application/json
// parameters:
// - name: id
// in: path
// description: token to be deleted
// type: integer
// format: int64
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
appID := ctx . ParamsInt64 ( ":id" )
if err := models . DeleteOAuth2Application ( appID , ctx . User . ID ) ; err != nil {
ctx . Error ( http . StatusInternalServerError , "DeleteOauth2ApplicationByID" , err )
return
}
ctx . Status ( http . StatusNoContent )
}
2020-04-10 03:37:31 +03:00
// 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" )
2020-04-30 20:50:47 +03:00
app , err := models . UpdateOAuth2Application ( models . UpdateOAuth2ApplicationOptions {
2020-04-10 03:37:31 +03:00
Name : data . Name ,
UserID : ctx . User . ID ,
ID : appID ,
RedirectURIs : data . RedirectURIs ,
} )
if err != nil {
if models . IsErrOauthClientIDInvalid ( err ) || models . IsErrOAuthApplicationNotFound ( err ) {
ctx . NotFound ( )
} else {
ctx . Error ( http . StatusInternalServerError , "UpdateOauth2ApplicationByID" , err )
}
return
}
2020-04-30 20:50:47 +03:00
app . ClientSecret , err = app . GenerateClientSecret ( )
2020-04-10 03:37:31 +03:00
if err != nil {
ctx . Error ( http . StatusBadRequest , "" , "error updating application secret" )
return
}
ctx . JSON ( http . StatusOK , convert . ToOAuth2Application ( app ) )
}