Skip to content

Commit 90da09b

Browse files
authored
chore: Make deployment admin page show better durations (coder#6856)
* chore: Make deployment admin page show better durations Also fix group mappings
1 parent 872037b commit 90da09b

File tree

8 files changed

+115
-37
lines changed

8 files changed

+115
-37
lines changed

cli/clibase/values.go

-13
Original file line numberDiff line numberDiff line change
@@ -190,19 +190,6 @@ func (d *Duration) String() string {
190190
return time.Duration(*d).String()
191191
}
192192

193-
func (d *Duration) MarshalJSON() ([]byte, error) {
194-
return json.Marshal(d.String())
195-
}
196-
197-
func (d *Duration) UnmarshalJSON(b []byte) error {
198-
var s string
199-
err := json.Unmarshal(b, &s)
200-
if err != nil {
201-
return err
202-
}
203-
return d.Set(s)
204-
}
205-
206193
func (Duration) Type() string {
207194
return "duration"
208195
}

cli/testdata/coder_server_--help.golden

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ backed by Tailscale and WireGuard.
170170
--http-address string, $CODER_HTTP_ADDRESS (default: 127.0.0.1:3000)
171171
HTTP bind address of the server. Unset to disable the HTTP endpoint.
172172

173-
--max-token-lifetime duration, $CODER_MAX_TOKEN_LIFETIME (default: 2562047h47m16.854775807s)
173+
--max-token-lifetime duration, $CODER_MAX_TOKEN_LIFETIME (default: 876600h0m0s)
174174
The maximum lifetime duration users can specify when creating an API
175175
token.
176176

coderd/apikey.go

+1-11
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"database/sql"
77
"errors"
88
"fmt"
9-
"math"
109
"net"
1110
"net/http"
1211
"strconv"
@@ -354,19 +353,10 @@ func (api *API) tokenConfig(rw http.ResponseWriter, r *http.Request) {
354353
return
355354
}
356355

357-
var maxTokenLifetime time.Duration
358-
// if --max-token-lifetime is unset (default value is math.MaxInt64)
359-
// send back a falsy value
360-
if values.MaxTokenLifetime.Value() == time.Duration(math.MaxInt64) {
361-
maxTokenLifetime = 0
362-
} else {
363-
maxTokenLifetime = values.MaxTokenLifetime.Value()
364-
}
365-
366356
httpapi.Write(
367357
r.Context(), rw, http.StatusOK,
368358
codersdk.TokenConfig{
369-
MaxTokenLifetime: maxTokenLifetime,
359+
MaxTokenLifetime: values.MaxTokenLifetime.Value(),
370360
},
371361
)
372362
}

codersdk/deployment.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"encoding/json"
66
"flag"
7-
"math"
87
"net/http"
98
"os"
109
"path/filepath"
@@ -1113,10 +1112,13 @@ when required by your organization's security policy.`,
11131112
Description: "The maximum lifetime duration users can specify when creating an API token.",
11141113
Flag: "max-token-lifetime",
11151114
Env: "CODER_MAX_TOKEN_LIFETIME",
1116-
Default: time.Duration(math.MaxInt64).String(),
1117-
Value: &c.MaxTokenLifetime,
1118-
Group: &deploymentGroupNetworkingHTTP,
1119-
YAML: "maxTokenLifetime",
1115+
// The default value is essentially "forever", so just use 100 years.
1116+
// We have to add in the 25 leap days for the frontend to show the
1117+
// "100 years" correctly.
1118+
Default: ((100 * 365 * time.Hour * 24) + (25 * time.Hour * 24)).String(),
1119+
Value: &c.MaxTokenLifetime,
1120+
Group: &deploymentGroupNetworkingHTTP,
1121+
YAML: "maxTokenLifetime",
11201122
},
11211123
{
11221124
Name: "Enable swagger endpoint",

docs/cli/server.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ Output Stackdriver compatible logs to a given file.
233233
| ----------- | -------------------------------------- |
234234
| Type | <code>duration</code> |
235235
| Environment | <code>$CODER_MAX_TOKEN_LIFETIME</code> |
236-
| Default | <code>2562047h47m16.854775807s</code> |
236+
| Default | <code>876600h0m0s</code> |
237237

238238
The maximum lifetime duration users can specify when creating an API token.
239239

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { optionValue } from "./OptionsTable"
2+
import { DeploymentOption } from "api/types"
3+
4+
const defaultOption: DeploymentOption = {
5+
name: "",
6+
description: "",
7+
flag: "",
8+
flag_shorthand: "",
9+
value: "",
10+
hidden: false,
11+
}
12+
13+
describe("optionValue", () => {
14+
it.each<{
15+
option: DeploymentOption
16+
expected: string | string[] | unknown
17+
}>([
18+
{
19+
option: {
20+
...defaultOption,
21+
name: "Max Token Lifetime",
22+
value: 3600 * 1e9,
23+
},
24+
expected: "1 hour",
25+
},
26+
{
27+
option: {
28+
...defaultOption,
29+
name: "Max Token Lifetime",
30+
value: 24 * 3600 * 1e9,
31+
},
32+
expected: "1 day",
33+
},
34+
{
35+
option: {
36+
...defaultOption,
37+
name: "Session Duration",
38+
value: 3600 * 1e9,
39+
},
40+
expected: "1 hour",
41+
},
42+
{
43+
option: {
44+
...defaultOption,
45+
name: "Session Duration",
46+
value: 24 * 3600 * 1e9,
47+
},
48+
expected: "1 day",
49+
},
50+
{
51+
option: {
52+
...defaultOption,
53+
name: "Strict-Transport-Security",
54+
value: 1000,
55+
},
56+
expected: "1000s",
57+
},
58+
{
59+
option: {
60+
...defaultOption,
61+
name: "OIDC Group Mapping",
62+
value: {
63+
"123": "foo",
64+
"456": "bar",
65+
"789": "baz",
66+
},
67+
},
68+
expected: [`"123"->"foo"`, `"456"->"bar"`, `"789"->"baz"`],
69+
},
70+
])(`[$option.name]optionValue($option.value)`, ({ option, expected }) => {
71+
expect(optionValue(option)).toEqual(expected)
72+
})
73+
})

site/src/components/DeploySettingsLayout/OptionsTable.tsx

+32-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from "components/DeploySettingsLayout/Option"
1414
import { FC } from "react"
1515
import { DisabledBadge } from "./Badges"
16+
import { intervalToDuration, formatDuration } from "date-fns"
1617

1718
const OptionsTable: FC<{
1819
options: DeploymentOption[]
@@ -34,7 +35,11 @@ const OptionsTable: FC<{
3435
</TableHead>
3536
<TableBody>
3637
{Object.values(options).map((option) => {
37-
if (option.value === null || option.value === "") {
38+
if (
39+
option.value === null ||
40+
option.value === "" ||
41+
option.value === undefined
42+
) {
3843
return null
3944
}
4045
return (
@@ -45,7 +50,7 @@ const OptionsTable: FC<{
4550
</TableCell>
4651

4752
<TableCell>
48-
<OptionValue>{option.value}</OptionValue>
53+
<OptionValue>{optionValue(option)}</OptionValue>
4954
</TableCell>
5055
</TableRow>
5156
)
@@ -56,6 +61,31 @@ const OptionsTable: FC<{
5661
)
5762
}
5863

64+
// optionValue is a helper function to format the value of a specific deployment options
65+
export function optionValue(
66+
option: DeploymentOption,
67+
): string[] | string | unknown {
68+
switch (option.name) {
69+
case "Max Token Lifetime":
70+
case "Session Duration":
71+
// intervalToDuration takes ms, so convert nanoseconds to ms
72+
return formatDuration(
73+
intervalToDuration({ start: 0, end: (option.value as number) / 1e6 }),
74+
)
75+
case "Strict-Transport-Security":
76+
if (option.value === 0) {
77+
return "Disabled"
78+
}
79+
return (option.value as number).toString() + "s"
80+
case "OIDC Group Mapping":
81+
return Object.entries(option.value as Record<string, string>).map(
82+
([key, value]) => `"${key}"->"${value}"`,
83+
)
84+
default:
85+
return option.value
86+
}
87+
}
88+
5989
const useStyles = makeStyles((theme) => ({
6090
table: {
6191
"& td": {

site/src/pages/CreateTokenPage/utils.test.tsx

-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ describe("unit/CreateTokenForm", () => {
1212
maxTokenLifetime: number
1313
expected: LifetimeDay[]
1414
}>([
15-
{
16-
maxTokenLifetime: 0,
17-
expected: lifetimeDayPresets,
18-
},
1915
{ maxTokenLifetime: 6 * 24 * NANO_HOUR, expected: [] },
2016
{
2117
maxTokenLifetime: 20 * 24 * NANO_HOUR,

0 commit comments

Comments
 (0)