Skip to content

Commit

Permalink
feat: make commit writeup optional
Browse files Browse the repository at this point in the history
  • Loading branch information
GZTimeWalker committed Dec 31, 2023
1 parent 91a3f59 commit 0d679ee
Show file tree
Hide file tree
Showing 19 changed files with 1,058 additions and 1,143 deletions.
1,989 changes: 925 additions & 1,064 deletions src/GZCTF/ClientApp/src/Api.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/GZCTF/ClientApp/src/components/ChallengeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const ChallengeCard: FC<ChallengeCardProps> = (props: ChallengeCardProps) => {
<Stack spacing={0}>
<Text c={theme.colorScheme === 'dark' ? '' : 'dark'}>{blood?.name}</Text>
<Text size="xs" c="dimmed">
{dayjs(blood?.submitTimeUTC).format('YY/MM/DD HH:mm:ss')}
{dayjs(blood?.submitTimeUtc).format('YY/MM/DD HH:mm:ss')}
</Text>
</Stack>
}
Expand Down
36 changes: 21 additions & 15 deletions src/GZCTF/ClientApp/src/components/ChallengePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,17 @@ const ChallengePanel: FC = () => {
return (
<Group spacing="sm" noWrap position="apart" align="flex-start" miw="calc(100% - 20rem)">
<Stack miw="10rem">
<Button
leftIcon={<Icon path={mdiFileUploadOutline} size={1} />}
onClick={() => setWriteupSubmitOpened(true)}
>
提交 Writeup
</Button>
<Divider />
{game?.writeupRequired && (
<>
<Button
leftIcon={<Icon path={mdiFileUploadOutline} size={1} />}
onClick={() => setWriteupSubmitOpened(true)}
>
提交 Writeup
</Button>
<Divider />
</>
)}
<Switch
checked={hideSolved}
onChange={(e) => setHideSolved(e.target.checked)}
Expand Down Expand Up @@ -236,14 +240,16 @@ const ChallengePanel: FC = () => {
</Stack>
)}
</ScrollArea>
<WriteupSubmitModal
opened={writeupSubmitOpened}
onClose={() => setWriteupSubmitOpened(false)}
withCloseButton={false}
size="40%"
gameId={numId}
wpddl={data.wpddl}
/>
{game?.writeupRequired && (
<WriteupSubmitModal
opened={writeupSubmitOpened}
onClose={() => setWriteupSubmitOpened(false)}
withCloseButton={false}
size="40%"
gameId={numId}
writeupDeadline={data.writeupDeadline}
/>
)}
{challenge?.id && (
<ChallengeDetailModal
size="40%"
Expand Down
8 changes: 6 additions & 2 deletions src/GZCTF/ClientApp/src/components/WriteupSubmitModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ import api from '@Api'

interface WriteupSubmitModalProps extends ModalProps {
gameId: number
wpddl: string
writeupDeadline: string
}

export const WriteupSubmitModal: FC<WriteupSubmitModalProps> = ({ gameId, wpddl, ...props }) => {
export const WriteupSubmitModal: FC<WriteupSubmitModalProps> = ({
gameId,
writeupDeadline: wpddl,
...props
}) => {
const { data, mutate } = api.game.useGameGetWriteup(gameId, OnceSWRConfig)

const theme = useMantineTheme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const GameCreateModal: FC<GameCreateModalProps> = (props) => {
title,
start: start.toJSON(),
end: end.toJSON(),
wpddl: end.add(3, 'h').toJSON(),
})
.then((data) => {
showNotification({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const TeamWriteupCard: FC<TeamWriteupCardProps> = ({ writeup, selected, ...props
{writeup.team?.name}
</Text>
<Text lineClamp={1} size="xs" c="dimmed">
{dayjs(writeup.uploadTimeUTC).format('YYYY-MM-DD HH:mm')}
{dayjs(writeup.uploadTimeUtc).format('YYYY-MM-DD HH:mm')}
</Text>
</Stack>
</Group>
Expand Down
2 changes: 1 addition & 1 deletion src/GZCTF/ClientApp/src/components/admin/UserEditModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ const UserEditModal: FC<UserEditModalProps> = (props) => {
最后访问时间
</Text>
<Text size="sm" span fw={500} ff={theme.fontFamilyMonospace}>
{dayjs(user.lastVisitedUTC).format('YYYY-MM-DD HH:mm:ss')}
{dayjs(user.lastVisitedUtc).format('YYYY-MM-DD HH:mm:ss')}
</Text>
</Group>
</Stack>
Expand Down
74 changes: 39 additions & 35 deletions src/GZCTF/ClientApp/src/pages/admin/games/[id]/Info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
Input,
MultiSelect,
NumberInput,
PasswordInput,
SimpleGrid,
Stack,
Switch,
Expand All @@ -23,6 +22,7 @@ import { useModals } from '@mantine/modals'
import { notifications, showNotification, updateNotification } from '@mantine/notifications'
import {
mdiCheck,
mdiClipboard,
mdiClose,
mdiContentSaveOutline,
mdiDeleteOutline,
Expand Down Expand Up @@ -85,7 +85,7 @@ const GameInfoEdit: FC = () => {
setEnd(dayjs(gameSource.end))
setOrganizations(gameSource.organizations || [])

const wpddl = dayjs(gameSource.wpddl).diff(gameSource.end, 'h')
const wpddl = dayjs(gameSource.writeupDeadline).diff(gameSource.end, 'h')
setWpddl(wpddl < 0 ? 0 : wpddl)
}
}, [id, gameSource])
Expand Down Expand Up @@ -140,7 +140,7 @@ const GameInfoEdit: FC = () => {
inviteCode: game.inviteCode?.length ?? 0 > 6 ? game.inviteCode : null,
start: start.toJSON(),
end: end.toJSON(),
wpddl: end.add(wpddl, 'h').toJSON(),
writeupDeadline: end.add(wpddl, 'h').toJSON(),
})
.then(() => {
showNotification({
Expand Down Expand Up @@ -172,6 +172,15 @@ const GameInfoEdit: FC = () => {
.catch((e) => showErrorNotification(e, t))
}

const onCopyPublicKey = () => {
clipboard.copy(game?.publicKey || '')
showNotification({
color: 'teal',
message: '公钥已复制到剪贴板',
icon: <Icon path={mdiCheck} size={1} />,
})
}

return (
<WithGameEditTab
headProps={{ position: 'apart' }}
Expand Down Expand Up @@ -202,6 +211,13 @@ const GameInfoEdit: FC = () => {
>
删除比赛
</Button>
<Button
leftIcon={<Icon path={mdiClipboard} size={1} />}
disabled={disabled}
onClick={onCopyPublicKey}
>
复制公钥
</Button>
<Button
leftIcon={<Icon path={mdiContentSaveOutline} size={1} />}
disabled={disabled}
Expand Down Expand Up @@ -240,24 +256,20 @@ const GameInfoEdit: FC = () => {
value={game?.containerCountLimit}
onChange={(e) => game && setGame({ ...game, containerCountLimit: Number(e) })}
/>
<PasswordInput
value={game?.publicKey || ''}
label="比赛签名公钥"
description="用于校验队伍 Token"
readOnly
onClick={() => {
clipboard.copy(game?.publicKey || '')
showNotification({
color: 'teal',
message: '公钥已复制到剪贴板',
icon: <Icon path={mdiCheck} size={1} />,
})
}}
styles={{
innerInput: {
cursor: 'copy',
},
}}

<TextInput
label="邀请码"
description="留空则不启用邀请码报名"
value={game?.inviteCode || ''}
disabled={disabled}
onChange={(e) => game && setGame({ ...game, inviteCode: e.target.value })}
rightSection={
<ActionIcon
onClick={() => game && setGame({ ...game, inviteCode: GenerateRandomCode() })}
>
<Icon path={mdiRefresh} size={1} />
</ActionIcon>
}
/>
<DatePickerInput
label="开始日期"
Expand Down Expand Up @@ -342,19 +354,11 @@ const GameInfoEdit: FC = () => {
</Grid.Col>
<Grid.Col span={3}>
<Stack spacing="xs">
<TextInput
label="邀请码"
description="留空则不启用邀请码报名"
value={game?.inviteCode || ''}
<Switch
disabled={disabled}
onChange={(e) => game && setGame({ ...game, inviteCode: e.target.value })}
rightSection={
<ActionIcon
onClick={() => game && setGame({ ...game, inviteCode: GenerateRandomCode() })}
>
<Icon path={mdiRefresh} size={1} />
</ActionIcon>
}
checked={game?.writeupRequired ?? false}
label={SwitchLabel('需要 Writeup', '是否启用比赛的 Writeup 提交功能')}
onChange={(e) => game && setGame({ ...game, writeupRequired: e.target.checked })}
/>
<Switch
disabled={disabled}
Expand Down Expand Up @@ -394,13 +398,13 @@ const GameInfoEdit: FC = () => {
</Text>
</Group>
}
value={game?.wpNote}
value={game?.writeupNote}
w="100%"
autosize
disabled={disabled}
minRows={3}
maxRows={3}
onChange={(e) => game && setGame({ ...game, wpNote: e.target.value })}
onChange={(e) => game && setGame({ ...game, writeupNote: e.target.value })}
/>
<MultiSelect
label={
Expand Down
5 changes: 5 additions & 0 deletions src/GZCTF/Controllers/GameController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ public async Task<IActionResult> ChallengesWithTeamInfo([FromRoute] int id, Canc
ScoreboardItem = boardItem,
TeamToken = context.Participation!.Token,
Challenges = scoreboard.Challenges,
WriteupRequired = context.Game!.WriteupRequired,
WriteupDeadline = context.Game!.WriteupDeadline
});
}
Expand Down Expand Up @@ -854,6 +855,10 @@ public async Task<IActionResult> SubmitWriteup([FromRoute] int id, IFormFile fil
return context.Result;

Game game = context.Game!;

if (!game.WriteupRequired)
return BadRequest(new RequestResponse(localizer[nameof(Resources.Program.Game_WriteupNotNeeded)]));

Participation part = context.Participation!;
Team team = part.Team;

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,14 @@ protected override void Up(MigrationBuilder migrationBuilder)
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Title = table.Column<string>(type: "text", nullable: false),
PublicKey = table.Column<string>(type: "text", nullable: false),
PrivateKey = table.Column<string>(type: "text", nullable: false),
PublicKey = table.Column<string>(type: "character varying(63)", maxLength: 63, nullable: false),
PrivateKey = table.Column<string>(type: "character varying(63)", maxLength: 63, nullable: false),
Hidden = table.Column<bool>(type: "boolean", nullable: false),
PosterHash = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
Summary = table.Column<string>(type: "text", nullable: false),
Content = table.Column<string>(type: "text", nullable: false),
AcceptWithoutReview = table.Column<bool>(type: "boolean", nullable: false),
WriteupRequired = table.Column<bool>(type: "boolean", nullable: false),
InviteCode = table.Column<string>(type: "text", nullable: true),
Organizations = table.Column<string>(type: "text", nullable: true),
TeamMemberCountLimit = table.Column<int>(type: "integer", nullable: false),
Expand Down
15 changes: 9 additions & 6 deletions src/GZCTF/Migrations/AppDbContextModelSnapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,11 +362,13 @@ protected override void BuildModel(ModelBuilder modelBuilder)

b.Property<string>("PrivateKey")
.IsRequired()
.HasColumnType("text");
.HasMaxLength(63)
.HasColumnType("character varying(63)");

b.Property<string>("PublicKey")
.IsRequired()
.HasColumnType("text");
.HasMaxLength(63)
.HasColumnType("character varying(63)");

b.Property<DateTimeOffset>("StartTimeUtc")
.HasColumnType("timestamp with time zone")
Expand All @@ -384,13 +386,14 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("text");

b.Property<DateTimeOffset>("WriteupDeadline")
.HasColumnType("timestamp with time zone")
.HasAnnotation("Relational:JsonPropertyName", "wpddl");
.HasColumnType("timestamp with time zone");

b.Property<string>("WriteupNote")
.IsRequired()
.HasColumnType("text")
.HasAnnotation("Relational:JsonPropertyName", "wpnote");
.HasColumnType("text");

b.Property<bool>("WriteupRequired")
.HasColumnType("boolean");

b.HasKey("Id");

Expand Down
Loading

0 comments on commit 0d679ee

Please sign in to comment.