mirror of
https://github.com/coder/coder.git
synced 2025-07-06 15:41:45 +00:00
feat(site): add ability to create tokens from account tokens page (#6608)
* add token actions * added basic token form * removed token switch * refined date field * limiting lifetime days to maxTokenLifetime * broke apart files * added loader and error * fixed form layout * added some unit tests * fixed be tests * no authorize check
This commit is contained in:
42
coderd/apidoc/docs.go
generated
42
coderd/apidoc/docs.go
generated
@ -3362,6 +3362,40 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{user}/keys/tokens/tokenconfig": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"General"
|
||||
],
|
||||
"summary": "Get token config",
|
||||
"operationId": "get-token-config",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "User ID, name, or me",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TokenConfig"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{user}/keys/tokens/{keyname}": {
|
||||
"get": {
|
||||
"security": [
|
||||
@ -8121,6 +8155,14 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TokenConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"max_token_lifetime": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TraceConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
38
coderd/apidoc/swagger.json
generated
38
coderd/apidoc/swagger.json
generated
@ -2952,6 +2952,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{user}/keys/tokens/tokenconfig": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["General"],
|
||||
"summary": "Get token config",
|
||||
"operationId": "get-token-config",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "User ID, name, or me",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TokenConfig"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{user}/keys/tokens/{keyname}": {
|
||||
"get": {
|
||||
"security": [
|
||||
@ -7303,6 +7333,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TokenConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"max_token_lifetime": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TraceConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@ -339,6 +340,38 @@ func (api *API) deleteAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
httpapi.Write(ctx, rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
// @Summary Get token config
|
||||
// @ID get-token-config
|
||||
// @Security CoderSessionToken
|
||||
// @Produce json
|
||||
// @Tags General
|
||||
// @Param user path string true "User ID, name, or me"
|
||||
// @Success 200 {object} codersdk.TokenConfig
|
||||
// @Router /users/{user}/keys/tokens/tokenconfig [get]
|
||||
func (api *API) tokenConfig(rw http.ResponseWriter, r *http.Request) {
|
||||
values, err := api.DeploymentValues.WithoutSecrets()
|
||||
if err != nil {
|
||||
httpapi.InternalServerError(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
var maxTokenLifetime time.Duration
|
||||
// if --max-token-lifetime is unset (default value is math.MaxInt64)
|
||||
// send back a falsy value
|
||||
if values.MaxTokenLifetime.Value() == time.Duration(math.MaxInt64) {
|
||||
maxTokenLifetime = 0
|
||||
} else {
|
||||
maxTokenLifetime = values.MaxTokenLifetime.Value()
|
||||
}
|
||||
|
||||
httpapi.Write(
|
||||
r.Context(), rw, http.StatusOK,
|
||||
codersdk.TokenConfig{
|
||||
MaxTokenLifetime: maxTokenLifetime,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Generates a new ID and secret for an API key.
|
||||
func GenerateAPIKeyIDSecret() (id string, secret string, err error) {
|
||||
// Length of an API Key ID.
|
||||
|
@ -561,6 +561,7 @@ func New(options *Options) *API {
|
||||
r.Route("/tokens", func(r chi.Router) {
|
||||
r.Post("/", api.postToken)
|
||||
r.Get("/", api.tokens)
|
||||
r.Get("/tokenconfig", api.tokenConfig)
|
||||
r.Route("/{keyname}", func(r chi.Router) {
|
||||
r.Get("/", api.apiKeyByName)
|
||||
})
|
||||
|
@ -99,6 +99,7 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
|
||||
AssertObject: rbac.ResourceAPIKey,
|
||||
AssertAction: rbac.ActionRead,
|
||||
},
|
||||
"GET:/api/v2/users/{user}/keys/tokens/tokenconfig": {NoAuthorize: true},
|
||||
"GET:/api/v2/workspacebuilds/{workspacebuild}": {
|
||||
AssertAction: rbac.ActionRead,
|
||||
AssertObject: workspaceRBACObj,
|
||||
|
Reference in New Issue
Block a user