mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
chore: Make deployment admin page show better durations (#6856)
* chore: Make deployment admin page show better durations Also fix group mappings
This commit is contained in:
@ -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"
|
||||
}
|
||||
|
2
cli/testdata/coder_server_--help.golden
vendored
2
cli/testdata/coder_server_--help.golden
vendored
@ -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.
|
||||
|
||||
|
@ -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(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -1113,7 +1112,10 @@ 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(),
|
||||
// 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",
|
||||
|
@ -233,7 +233,7 @@ Output Stackdriver compatible logs to a given file.
|
||||
| ----------- | -------------------------------------- |
|
||||
| Type | <code>duration</code> |
|
||||
| Environment | <code>$CODER_MAX_TOKEN_LIFETIME</code> |
|
||||
| Default | <code>2562047h47m16.854775807s</code> |
|
||||
| Default | <code>876600h0m0s</code> |
|
||||
|
||||
The maximum lifetime duration users can specify when creating an API token.
|
||||
|
||||
|
73
site/src/components/DeploySettingsLayout/Options.test.tsx
Normal file
73
site/src/components/DeploySettingsLayout/Options.test.tsx
Normal file
@ -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)
|
||||
})
|
||||
})
|
@ -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<{
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{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<{
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
<OptionValue>{option.value}</OptionValue>
|
||||
<OptionValue>{optionValue(option)}</OptionValue>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
@ -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<string, string>).map(
|
||||
([key, value]) => `"${key}"->"${value}"`,
|
||||
)
|
||||
default:
|
||||
return option.value
|
||||
}
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
table: {
|
||||
"& td": {
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user