Skip to content

Commit 1ad6578

Browse files
authored
Merge pull request #58 from battlesquid/fix/input-validation
Fix/input validation
2 parents fb6bcd6 + 99fa3c8 commit 1ad6578

File tree

7 files changed

+83
-39
lines changed

7 files changed

+83
-39
lines changed

packages/app/src/components/sidebar.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
Button,
55
Card,
66
Divider,
7-
Group,
87
ScrollArea,
98
Stack,
109
Title,
@@ -118,10 +117,10 @@ export function Sidebar(props: SidebarProps) {
118117
</Stack>
119118
</AppShell.Section>
120119
<AppShell.Section>
121-
<Group gap="xs">
120+
<Stack gap="xs">
122121
<ShareButton />
123122
<ExportButton />
124-
</Group>
123+
</Stack>
125124
</AppShell.Section>
126125
</Card>
127126
<AppShell.Section>

packages/app/src/components/sidebar_inputs/base_padding.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export function BasePaddingInput() {
1313
min={0}
1414
step={0.5}
1515
value={padding}
16+
clampBehavior="strict"
17+
allowNegative={false}
18+
allowLeadingZeros={false}
1619
onChange={(value) =>
1720
setInputs({
1821
padding: safeFloat(value, 0),

packages/app/src/components/sidebar_inputs/generate_section.tsx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ export function GenerateSection(props: GenerateSectionProps) {
8686
placeholder="Start Year"
8787
min={MIN_START_YEAR}
8888
max={new Date().getFullYear()}
89+
allowNegative={false}
90+
allowDecimal={false}
91+
allowLeadingZeros={false}
8992
stepHoldDelay={500}
9093
stepHoldInterval={100}
9194
value={startYear}
@@ -96,7 +99,9 @@ export function GenerateSection(props: GenerateSectionProps) {
9699
currentStartYear = lastValidStartYear;
97100
}
98101
if (currentStartYear > endYear) {
99-
setEndYear(currentStartYear);
102+
setEndYear(
103+
Math.min(new Date().getFullYear(), currentStartYear as number),
104+
);
100105
}
101106
}}
102107
onChange={setStartYear}
@@ -106,6 +111,9 @@ export function GenerateSection(props: GenerateSectionProps) {
106111
placeholder="End Year"
107112
min={MIN_START_YEAR}
108113
max={new Date().getFullYear()}
114+
allowNegative={false}
115+
allowDecimal={false}
116+
allowLeadingZeros={false}
109117
stepHoldDelay={500}
110118
stepHoldInterval={100}
111119
value={endYear}
@@ -116,27 +124,30 @@ export function GenerateSection(props: GenerateSectionProps) {
116124
currentEndYear = lastValidEndYear;
117125
}
118126
if (currentEndYear < startYear) {
119-
setStartYear(currentEndYear);
127+
setStartYear(
128+
Math.min(new Date().getFullYear(), currentEndYear as number),
129+
);
120130
}
121131
}}
122132
onChange={setEndYear}
123133
/>
124134
</Group>
125135
<Button
126-
className="mona-sans-wide"
127136
fullWidth
137+
className="mona-sans-wide"
138+
tt="uppercase"
128139
disabled={name.trim() === ""}
140+
variant="light"
141+
size="xs"
129142
onClick={() =>
130143
setInputs({
131144
name,
132145
startYear: startYear as number,
133146
endYear: endYear as number,
134147
})
135148
}
136-
variant="light"
137-
size="xs"
138149
>
139-
GENERATE
150+
Generate
140151
</Button>
141152
</>
142153
);

packages/app/src/components/sidebar_inputs/scale.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export function ScaleInput() {
1313
min={1}
1414
step={0.1}
1515
value={scale}
16+
clampBehavior="strict"
17+
allowNegative={false}
18+
allowLeadingZeros={false}
1619
onChange={(value) => setInputs({ scale: safeFloat(value, 1) })}
1720
/>
1821
);

packages/app/src/components/sidebar_inputs/tower_dampening.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ export function TowerDampeningInput() {
1212
min={1}
1313
allowDecimal={false}
1414
value={dampening}
15-
onChange={(value) =>
15+
clampBehavior="strict"
16+
allowNegative={false}
17+
onChange={(value) => {
18+
console.log(value);
1619
setInputs({
1720
dampening: safeInt(value, 1),
18-
})
19-
}
21+
});
22+
}}
2023
/>
2124
);
2225
}

packages/app/src/share/urlShare.ts

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,63 @@ import {
44
} from "lz-string";
55
import { z } from "zod";
66

7-
import type { SkylineModelInputParameters } from "../stores/parameters";
7+
import {
8+
DEFAULT_INPUT_PARAMETERS,
9+
type SkylineModelInputParameters,
10+
} from "../stores/parameters";
811
import { ExportFormat } from "../three/export";
912
import { SkylineBaseShape } from "../three/types";
1013

1114
export const URL_PARAM_KEY = "s";
1215

1316
export const MinimalShareSchema = z.object({
14-
v: z.literal(1),
15-
type: z.literal("minimal"),
16-
name: z.string(),
17-
startYear: z.number().int(),
18-
endYear: z.number().int(),
17+
v: z.literal(1).catch(1),
18+
type: z.literal("minimal").catch("minimal"),
19+
name: z.string().catch(DEFAULT_INPUT_PARAMETERS.name),
20+
startYear: z
21+
.number()
22+
.int()
23+
.max(new Date().getFullYear())
24+
.catch(DEFAULT_INPUT_PARAMETERS.startYear),
25+
endYear: z
26+
.number()
27+
.int()
28+
.max(new Date().getFullYear())
29+
.catch(DEFAULT_INPUT_PARAMETERS.endYear),
1930
});
2031

2132
export const FullShareSchema = z.object({
22-
v: z.literal(1),
23-
type: z.literal("full"),
24-
name: z.string(),
25-
nameOverride: z.string(),
26-
startYear: z.number().int(),
27-
endYear: z.number().int(),
28-
insetText: z.boolean(),
29-
towerSize: z.number(),
30-
dampening: z.number(),
31-
shape: z.nativeEnum(SkylineBaseShape),
32-
padding: z.number(),
33-
textDepth: z.number(),
34-
color: z.string(),
35-
showContributionColor: z.boolean(),
36-
scale: z.number(),
37-
exportFormat: z.nativeEnum(ExportFormat),
38-
logoOffset: z.number(),
39-
nameOffset: z.number(),
40-
yearOffset: z.number(),
33+
v: z.literal(1).catch(1),
34+
type: z.literal("full").catch("full"),
35+
name: z.string().catch(DEFAULT_INPUT_PARAMETERS.name),
36+
startYear: z
37+
.number()
38+
.int()
39+
.max(new Date().getFullYear())
40+
.catch(DEFAULT_INPUT_PARAMETERS.startYear),
41+
endYear: z
42+
.number()
43+
.int()
44+
.max(new Date().getFullYear())
45+
.catch(DEFAULT_INPUT_PARAMETERS.endYear),
46+
nameOverride: z.string().catch(DEFAULT_INPUT_PARAMETERS.nameOverride),
47+
insetText: z.boolean().catch(DEFAULT_INPUT_PARAMETERS.insetText),
48+
towerSize: z.number().catch(DEFAULT_INPUT_PARAMETERS.towerSize),
49+
dampening: z.number().min(1).catch(DEFAULT_INPUT_PARAMETERS.dampening),
50+
shape: z.enum(SkylineBaseShape).catch(DEFAULT_INPUT_PARAMETERS.shape),
51+
padding: z.number().min(0).catch(DEFAULT_INPUT_PARAMETERS.padding),
52+
textDepth: z.number().catch(DEFAULT_INPUT_PARAMETERS.textDepth),
53+
color: z.string().catch(DEFAULT_INPUT_PARAMETERS.color),
54+
showContributionColor: z
55+
.boolean()
56+
.catch(DEFAULT_INPUT_PARAMETERS.showContributionColor),
57+
scale: z.number().min(1).catch(DEFAULT_INPUT_PARAMETERS.scale),
58+
exportFormat: z
59+
.enum(ExportFormat)
60+
.catch(DEFAULT_INPUT_PARAMETERS.exportFormat),
61+
logoOffset: z.number().catch(DEFAULT_INPUT_PARAMETERS.logoOffset),
62+
nameOffset: z.number().catch(DEFAULT_INPUT_PARAMETERS.nameOffset),
63+
yearOffset: z.number().catch(DEFAULT_INPUT_PARAMETERS.yearOffset),
4164
});
4265

4366
export const ShareSchema = z.union([MinimalShareSchema, FullShareSchema]);

packages/app/src/utils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@ export const safeFloat = (value: string | number, min: number) => {
2121
if (value === "") {
2222
return min;
2323
}
24-
return Number.parseFloat(`${value}`);
24+
const safeValue = Number.parseFloat(`${value}`);
25+
return Math.max(safeValue, min);
2526
};
2627

2728
export const safeInt = (value: string | number, min: number) => {
2829
if (value === "") {
2930
return min;
3031
}
31-
return Number.parseInt(`${value}`);
32+
const safeValue = Number.parseInt(`${value}`);
33+
return Math.max(safeValue, min);
3234
};
3335

3436
export const safeString = (value: string, fallback: string) => {

0 commit comments

Comments
 (0)