From 62e550bf35db3263d63cc32710969fe3701b1f5a Mon Sep 17 00:00:00 2001 From: konrad Date: Sat, 7 Dec 2019 19:52:04 +0000 Subject: [PATCH] Add user token renew (#113) --- pkg/routes/api/v1/login.go | 34 ++++++++++++++++++++++++++++ pkg/routes/routes.go | 1 + pkg/swagger/docs.go | 45 +++++++++++++++++++++++++++++++------- pkg/swagger/swagger.json | 43 ++++++++++++++++++++++++++++++------ pkg/swagger/swagger.yaml | 33 ++++++++++++++++++++++------ 5 files changed, 134 insertions(+), 22 deletions(-) diff --git a/pkg/routes/api/v1/login.go b/pkg/routes/api/v1/login.go index 5170fdb1235..2e155571829 100644 --- a/pkg/routes/api/v1/login.go +++ b/pkg/routes/api/v1/login.go @@ -19,6 +19,7 @@ package v1 import ( "code.vikunja.io/api/pkg/models" "code.vikunja.io/web/handler" + "github.com/dgrijalva/jwt-go" "github.com/labstack/echo/v4" "net/http" ) @@ -59,3 +60,36 @@ func Login(c echo.Context) error { return c.JSON(http.StatusOK, Token{Token: t}) } + +// RenewToken gives a new token to every user with a valid token +// If the token is valid is checked in the middleware. +// @Summary Renew user token +// @Description Returns a new valid jwt user token with an extended length. +// @tags user +// @Accept json +// @Produce json +// @Success 200 {object} v1.Token +// @Failure 400 {object} models.Message "Only user token are available for renew." +// @Router /user/token [post] +func RenewToken(c echo.Context) error { + + jwtinf := c.Get("user").(*jwt.Token) + claims := jwtinf.Claims.(jwt.MapClaims) + typ := int(claims["type"].(float64)) + if typ != AuthTypeUser { + return echo.ErrBadRequest + } + + user, err := models.GetUserFromClaims(claims) + if err != nil { + return handler.HandleHTTPError(err, c) + } + + // Create token + t, err := NewUserJWTAuthtoken(user) + if err != nil { + return err + } + + return c.JSON(http.StatusOK, Token{Token: t}) +} diff --git a/pkg/routes/routes.go b/pkg/routes/routes.go index bcb13208ab3..c0a62accba3 100644 --- a/pkg/routes/routes.go +++ b/pkg/routes/routes.go @@ -190,6 +190,7 @@ func registerAPIRoutes(a *echo.Group) { a.GET("/user", apiv1.UserShow) a.POST("/user/password", apiv1.UserChangePassword) a.GET("/users", apiv1.UserList) + a.POST("/user/token", apiv1.RenewToken) listHandler := &handler.WebHandler{ EmptyStruct: func() handler.CObject { diff --git a/pkg/swagger/docs.go b/pkg/swagger/docs.go index 76873197e00..b20677d1317 100644 --- a/pkg/swagger/docs.go +++ b/pkg/swagger/docs.go @@ -1,6 +1,6 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2019-12-05 22:15:49.761451764 +0100 CET m=+0.171539379 +// 2019-12-07 20:29:10.551783293 +0100 CET m=+0.172017440 package swagger @@ -407,7 +407,7 @@ var doc = `{ "JWTKeyAuth": [] } ], - "description": "Returns a team by its ID.", + "description": "Returns a list by its ID.", "consumes": [ "application/json" ], @@ -415,13 +415,13 @@ var doc = `{ "application/json" ], "tags": [ - "team" + "list" ], - "summary": "Gets one team", + "summary": "Gets one list", "parameters": [ { "type": "integer", - "description": "Team ID", + "description": "List ID", "name": "id", "in": "path", "required": true @@ -429,13 +429,13 @@ var doc = `{ ], "responses": { "200": { - "description": "The team", + "description": "The list", "schema": { - "$ref": "#/definitions/models.Team" + "$ref": "#/definitions/models.List" } }, "403": { - "description": "The user does not have access to the team", + "description": "The user does not have access to the list", "schema": { "$ref": "#/definitions/code.vikunja.io.web.HTTPError" } @@ -4285,6 +4285,35 @@ var doc = `{ } } }, + "/user/token": { + "post": { + "description": "Returns a new valid jwt user token with an extended length.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Renew user token", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.Token" + } + }, + "400": { + "description": "Only user token are available for renew.", + "schema": { + "$ref": "#/definitions/models.Message" + } + } + } + } + }, "/users": { "get": { "security": [ diff --git a/pkg/swagger/swagger.json b/pkg/swagger/swagger.json index a3c54a4d2d8..eb0777eb76d 100644 --- a/pkg/swagger/swagger.json +++ b/pkg/swagger/swagger.json @@ -389,7 +389,7 @@ "JWTKeyAuth": [] } ], - "description": "Returns a team by its ID.", + "description": "Returns a list by its ID.", "consumes": [ "application/json" ], @@ -397,13 +397,13 @@ "application/json" ], "tags": [ - "team" + "list" ], - "summary": "Gets one team", + "summary": "Gets one list", "parameters": [ { "type": "integer", - "description": "Team ID", + "description": "List ID", "name": "id", "in": "path", "required": true @@ -411,13 +411,13 @@ ], "responses": { "200": { - "description": "The team", + "description": "The list", "schema": { - "$ref": "#/definitions/models.Team" + "$ref": "#/definitions/models.List" } }, "403": { - "description": "The user does not have access to the team", + "description": "The user does not have access to the list", "schema": { "$ref": "#/definitions/code.vikunja.io/web.HTTPError" } @@ -4267,6 +4267,35 @@ } } }, + "/user/token": { + "post": { + "description": "Returns a new valid jwt user token with an extended length.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Renew user token", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.Token" + } + }, + "400": { + "description": "Only user token are available for renew.", + "schema": { + "$ref": "#/definitions/models.Message" + } + } + } + } + }, "/users": { "get": { "security": [ diff --git a/pkg/swagger/swagger.yaml b/pkg/swagger/swagger.yaml index b4c9d3146bb..11581e5038c 100644 --- a/pkg/swagger/swagger.yaml +++ b/pkg/swagger/swagger.yaml @@ -1133,9 +1133,9 @@ paths: get: consumes: - application/json - description: Returns a team by its ID. + description: Returns a list by its ID. parameters: - - description: Team ID + - description: List ID in: path name: id required: true @@ -1144,11 +1144,11 @@ paths: - application/json responses: "200": - description: The team + description: The list schema: - $ref: '#/definitions/models.Team' + $ref: '#/definitions/models.List' "403": - description: The user does not have access to the team + description: The user does not have access to the list schema: $ref: '#/definitions/code.vikunja.io/web.HTTPError' "500": @@ -1157,9 +1157,9 @@ paths: $ref: '#/definitions/models.Message' security: - JWTKeyAuth: [] - summary: Gets one team + summary: Gets one list tags: - - team + - list post: consumes: - application/json @@ -3675,6 +3675,25 @@ paths: summary: Request password reset token tags: - user + /user/token: + post: + consumes: + - application/json + description: Returns a new valid jwt user token with an extended length. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/v1.Token' + "400": + description: Only user token are available for renew. + schema: + $ref: '#/definitions/models.Message' + summary: Renew user token + tags: + - user /users: get: consumes: