From 90da09bc2c6cdc1bc05345cef3c697ceaec10c1c Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 29 Mar 2023 16:26:20 -0500 Subject: [PATCH] chore: Make deployment admin page show better durations (#6856) * chore: Make deployment admin page show better durations Also fix group mappings --- cli/clibase/values.go | 13 ---- cli/testdata/coder_server_--help.golden | 2 +- coderd/apikey.go | 12 +-- codersdk/deployment.go | 12 +-- docs/cli/server.md | 2 +- .../DeploySettingsLayout/Options.test.tsx | 73 +++++++++++++++++++ .../DeploySettingsLayout/OptionsTable.tsx | 34 ++++++++- site/src/pages/CreateTokenPage/utils.test.tsx | 4 - 8 files changed, 115 insertions(+), 37 deletions(-) create mode 100644 site/src/components/DeploySettingsLayout/Options.test.tsx diff --git a/cli/clibase/values.go b/cli/clibase/values.go index 0ddce1ba8f..ff3d8a7437 100644 --- a/cli/clibase/values.go +++ b/cli/clibase/values.go @@ -190,19 +190,6 @@ func (d *Duration) String() string { return time.Duration(*d).String() } -func (d *Duration) MarshalJSON() ([]byte, error) { - return json.Marshal(d.String()) -} - -func (d *Duration) UnmarshalJSON(b []byte) error { - var s string - err := json.Unmarshal(b, &s) - if err != nil { - return err - } - return d.Set(s) -} - func (Duration) Type() string { return "duration" } diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index eefe266d7c..db804ca8a3 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -170,7 +170,7 @@ backed by Tailscale and WireGuard. --http-address string, $CODER_HTTP_ADDRESS (default: 127.0.0.1:3000) HTTP bind address of the server. Unset to disable the HTTP endpoint. - --max-token-lifetime duration, $CODER_MAX_TOKEN_LIFETIME (default: 2562047h47m16.854775807s) + --max-token-lifetime duration, $CODER_MAX_TOKEN_LIFETIME (default: 876600h0m0s) The maximum lifetime duration users can specify when creating an API token. diff --git a/coderd/apikey.go b/coderd/apikey.go index c05f0205dc..25a1c767dd 100644 --- a/coderd/apikey.go +++ b/coderd/apikey.go @@ -6,7 +6,6 @@ import ( "database/sql" "errors" "fmt" - "math" "net" "net/http" "strconv" @@ -354,19 +353,10 @@ func (api *API) tokenConfig(rw http.ResponseWriter, r *http.Request) { 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, + MaxTokenLifetime: values.MaxTokenLifetime.Value(), }, ) } diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 9548afec47..60c001ff08 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "flag" - "math" "net/http" "os" "path/filepath" @@ -1113,10 +1112,13 @@ when required by your organization's security policy.`, Description: "The maximum lifetime duration users can specify when creating an API token.", Flag: "max-token-lifetime", Env: "CODER_MAX_TOKEN_LIFETIME", - Default: time.Duration(math.MaxInt64).String(), - Value: &c.MaxTokenLifetime, - Group: &deploymentGroupNetworkingHTTP, - YAML: "maxTokenLifetime", + // The default value is essentially "forever", so just use 100 years. + // We have to add in the 25 leap days for the frontend to show the + // "100 years" correctly. + Default: ((100 * 365 * time.Hour * 24) + (25 * time.Hour * 24)).String(), + Value: &c.MaxTokenLifetime, + Group: &deploymentGroupNetworkingHTTP, + YAML: "maxTokenLifetime", }, { Name: "Enable swagger endpoint", diff --git a/docs/cli/server.md b/docs/cli/server.md index 60df9f642a..0cbeb0fde1 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -233,7 +233,7 @@ Output Stackdriver compatible logs to a given file. | ----------- | -------------------------------------- | | Type | duration | | Environment | $CODER_MAX_TOKEN_LIFETIME | -| Default | 2562047h47m16.854775807s | +| Default | 876600h0m0s | The maximum lifetime duration users can specify when creating an API token. diff --git a/site/src/components/DeploySettingsLayout/Options.test.tsx b/site/src/components/DeploySettingsLayout/Options.test.tsx new file mode 100644 index 0000000000..9842778510 --- /dev/null +++ b/site/src/components/DeploySettingsLayout/Options.test.tsx @@ -0,0 +1,73 @@ +import { optionValue } from "./OptionsTable" +import { DeploymentOption } from "api/types" + +const defaultOption: DeploymentOption = { + name: "", + description: "", + flag: "", + flag_shorthand: "", + value: "", + hidden: false, +} + +describe("optionValue", () => { + it.each<{ + option: DeploymentOption + expected: string | string[] | unknown + }>([ + { + option: { + ...defaultOption, + name: "Max Token Lifetime", + value: 3600 * 1e9, + }, + expected: "1 hour", + }, + { + option: { + ...defaultOption, + name: "Max Token Lifetime", + value: 24 * 3600 * 1e9, + }, + expected: "1 day", + }, + { + option: { + ...defaultOption, + name: "Session Duration", + value: 3600 * 1e9, + }, + expected: "1 hour", + }, + { + option: { + ...defaultOption, + name: "Session Duration", + value: 24 * 3600 * 1e9, + }, + expected: "1 day", + }, + { + option: { + ...defaultOption, + name: "Strict-Transport-Security", + value: 1000, + }, + expected: "1000s", + }, + { + option: { + ...defaultOption, + name: "OIDC Group Mapping", + value: { + "123": "foo", + "456": "bar", + "789": "baz", + }, + }, + expected: [`"123"->"foo"`, `"456"->"bar"`, `"789"->"baz"`], + }, + ])(`[$option.name]optionValue($option.value)`, ({ option, expected }) => { + expect(optionValue(option)).toEqual(expected) + }) +}) diff --git a/site/src/components/DeploySettingsLayout/OptionsTable.tsx b/site/src/components/DeploySettingsLayout/OptionsTable.tsx index efe99034d8..fd8b841096 100644 --- a/site/src/components/DeploySettingsLayout/OptionsTable.tsx +++ b/site/src/components/DeploySettingsLayout/OptionsTable.tsx @@ -13,6 +13,7 @@ import { } from "components/DeploySettingsLayout/Option" import { FC } from "react" import { DisabledBadge } from "./Badges" +import { intervalToDuration, formatDuration } from "date-fns" const OptionsTable: FC<{ options: DeploymentOption[] @@ -34,7 +35,11 @@ const OptionsTable: FC<{ {Object.values(options).map((option) => { - if (option.value === null || option.value === "") { + if ( + option.value === null || + option.value === "" || + option.value === undefined + ) { return null } return ( @@ -45,7 +50,7 @@ const OptionsTable: FC<{ - {option.value} + {optionValue(option)} ) @@ -56,6 +61,31 @@ const OptionsTable: FC<{ ) } +// optionValue is a helper function to format the value of a specific deployment options +export function optionValue( + option: DeploymentOption, +): string[] | string | unknown { + switch (option.name) { + case "Max Token Lifetime": + case "Session Duration": + // intervalToDuration takes ms, so convert nanoseconds to ms + return formatDuration( + intervalToDuration({ start: 0, end: (option.value as number) / 1e6 }), + ) + case "Strict-Transport-Security": + if (option.value === 0) { + return "Disabled" + } + return (option.value as number).toString() + "s" + case "OIDC Group Mapping": + return Object.entries(option.value as Record).map( + ([key, value]) => `"${key}"->"${value}"`, + ) + default: + return option.value + } +} + const useStyles = makeStyles((theme) => ({ table: { "& td": { diff --git a/site/src/pages/CreateTokenPage/utils.test.tsx b/site/src/pages/CreateTokenPage/utils.test.tsx index 2bdb20c180..4ab7d18c79 100644 --- a/site/src/pages/CreateTokenPage/utils.test.tsx +++ b/site/src/pages/CreateTokenPage/utils.test.tsx @@ -12,10 +12,6 @@ describe("unit/CreateTokenForm", () => { maxTokenLifetime: number expected: LifetimeDay[] }>([ - { - maxTokenLifetime: 0, - expected: lifetimeDayPresets, - }, { maxTokenLifetime: 6 * 24 * NANO_HOUR, expected: [] }, { maxTokenLifetime: 20 * 24 * NANO_HOUR,