diff --git a/src/GZCTF/ClientApp/package.json b/src/GZCTF/ClientApp/package.json index 79f304c37..cfaff57a5 100644 --- a/src/GZCTF/ClientApp/package.json +++ b/src/GZCTF/ClientApp/package.json @@ -25,7 +25,7 @@ "@mdi/react": "^1.6.1", "@microsoft/signalr": "^7.0.9", "dayjs": "^1.11.9", - "echarts": "^5.4.2", + "echarts": "^5.4.3", "echarts-for-react": "^3.0.2", "embla-carousel": "^7.1.0", "embla-carousel-autoplay": "^7.1.0", @@ -38,8 +38,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-pdf": "^7.1.3", - "react-router": "^6.14.1", - "react-router-dom": "^6.14.1", + "react-router": "^6.14.2", + "react-router-dom": "^6.14.2", "swr": "^2.2.0", "vite-tsconfig-paths": "^4.2.0" }, @@ -53,8 +53,8 @@ "@types/prismjs": "^1.26.0", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", - "@typescript-eslint/eslint-plugin": "^6.0.0", - "@typescript-eslint/parser": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^6.1.0", + "@typescript-eslint/parser": "^6.1.0", "@vitejs/plugin-react": "^4.0.3", "axios": "^1.4.0", "babel-plugin-prismjs": "^2.1.0", @@ -63,7 +63,7 @@ "form-data": "~4.0.0", "lodash": "^4.17.21", "prettier": "~3.0.0", - "rollup": "^3.26.2", + "rollup": "^3.26.3", "swagger-typescript-api": "^13.0.0", "tslib": "^2.6.0", "typescript": "5.1.6", diff --git a/src/GZCTF/ClientApp/pnpm-lock.yaml b/src/GZCTF/ClientApp/pnpm-lock.yaml index 625292b34..66b45ef70 100644 --- a/src/GZCTF/ClientApp/pnpm-lock.yaml +++ b/src/GZCTF/ClientApp/pnpm-lock.yaml @@ -48,11 +48,11 @@ dependencies: specifier: ^1.11.9 version: 1.11.9 echarts: - specifier: ^5.4.2 - version: 5.4.2 + specifier: ^5.4.3 + version: 5.4.3 echarts-for-react: specifier: ^3.0.2 - version: 3.0.2(echarts@5.4.2)(react@18.2.0) + version: 3.0.2(echarts@5.4.3)(react@18.2.0) embla-carousel: specifier: ^7.1.0 version: 7.1.0 @@ -87,11 +87,11 @@ dependencies: specifier: ^7.1.3 version: 7.1.3(react-dom@18.2.0)(react@18.2.0) react-router: - specifier: ^6.14.1 - version: 6.14.1(react@18.2.0) + specifier: ^6.14.2 + version: 6.14.2(react@18.2.0) react-router-dom: - specifier: ^6.14.1 - version: 6.14.1(react-dom@18.2.0)(react@18.2.0) + specifier: ^6.14.2 + version: 6.14.2(react-dom@18.2.0)(react@18.2.0) swr: specifier: ^2.2.0 version: 2.2.0(react@18.2.0) @@ -128,11 +128,11 @@ devDependencies: specifier: ^18.2.7 version: 18.2.7 '@typescript-eslint/eslint-plugin': - specifier: ^6.0.0 - version: 6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.45.0)(typescript@5.1.6) + specifier: ^6.1.0 + version: 6.1.0(@typescript-eslint/parser@6.1.0)(eslint@8.45.0)(typescript@5.1.6) '@typescript-eslint/parser': - specifier: ^6.0.0 - version: 6.0.0(eslint@8.45.0)(typescript@5.1.6) + specifier: ^6.1.0 + version: 6.1.0(eslint@8.45.0)(typescript@5.1.6) '@vitejs/plugin-react': specifier: ^4.0.3 version: 4.0.3(vite@4.4.4) @@ -158,8 +158,8 @@ devDependencies: specifier: ~3.0.0 version: 3.0.0 rollup: - specifier: ^3.26.2 - version: 3.26.2 + specifier: ^3.26.3 + version: 3.26.3 swagger-typescript-api: specifier: ^13.0.0 version: 13.0.0 @@ -1257,8 +1257,8 @@ packages: react: 18.2.0 dev: false - /@remix-run/router@1.7.1: - resolution: {integrity: sha512-bgVQM4ZJ2u2CM8k1ey70o1ePFXsEzYVZoWghh6WjM8p59jQ7HxzbHW4SbnWFG7V9ig9chLawQxDTZ3xzOF8MkQ==} + /@remix-run/router@1.7.2: + resolution: {integrity: sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==} engines: {node: '>=14'} dev: false @@ -1362,8 +1362,8 @@ packages: resolution: {integrity: sha512-7yQiX6MWSFSvc/1wW5smJMZTZ4fHOd+hqLr3qr/HONDxHEa2bnYAsOcGBOEqFIjd4yetwMOdEDdeW+udRAQnHA==} dev: true - /@typescript-eslint/eslint-plugin@6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.45.0)(typescript@5.1.6): - resolution: {integrity: sha512-xuv6ghKGoiq856Bww/yVYnXGsKa588kY3M0XK7uUW/3fJNNULKRfZfSBkMTSpqGG/8ZCXCadfh8G/z/B4aqS/A==} + /@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.1.0)(eslint@8.45.0)(typescript@5.1.6): + resolution: {integrity: sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -1374,14 +1374,13 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.5.1 - '@typescript-eslint/parser': 6.0.0(eslint@8.45.0)(typescript@5.1.6) - '@typescript-eslint/scope-manager': 6.0.0 - '@typescript-eslint/type-utils': 6.0.0(eslint@8.45.0)(typescript@5.1.6) - '@typescript-eslint/utils': 6.0.0(eslint@8.45.0)(typescript@5.1.6) - '@typescript-eslint/visitor-keys': 6.0.0 + '@typescript-eslint/parser': 6.1.0(eslint@8.45.0)(typescript@5.1.6) + '@typescript-eslint/scope-manager': 6.1.0 + '@typescript-eslint/type-utils': 6.1.0(eslint@8.45.0)(typescript@5.1.6) + '@typescript-eslint/utils': 6.1.0(eslint@8.45.0)(typescript@5.1.6) + '@typescript-eslint/visitor-keys': 6.1.0 debug: 4.3.4 eslint: 8.45.0 - grapheme-splitter: 1.0.4 graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 @@ -1393,8 +1392,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@6.0.0(eslint@8.45.0)(typescript@5.1.6): - resolution: {integrity: sha512-TNaufYSPrr1U8n+3xN+Yp9g31vQDJqhXzzPSHfQDLcaO4tU+mCfODPxCwf4H530zo7aUBE3QIdxCXamEnG04Tg==} + /@typescript-eslint/parser@6.1.0(eslint@8.45.0)(typescript@5.1.6): + resolution: {integrity: sha512-hIzCPvX4vDs4qL07SYzyomamcs2/tQYXg5DtdAfj35AyJ5PIUqhsLf4YrEIFzZcND7R2E8tpQIZKayxg8/6Wbw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1403,10 +1402,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.0.0 - '@typescript-eslint/types': 6.0.0 - '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.1.6) - '@typescript-eslint/visitor-keys': 6.0.0 + '@typescript-eslint/scope-manager': 6.1.0 + '@typescript-eslint/types': 6.1.0 + '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.1.6) + '@typescript-eslint/visitor-keys': 6.1.0 debug: 4.3.4 eslint: 8.45.0 typescript: 5.1.6 @@ -1414,16 +1413,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@6.0.0: - resolution: {integrity: sha512-o4q0KHlgCZTqjuaZ25nw5W57NeykZT9LiMEG4do/ovwvOcPnDO1BI5BQdCsUkjxFyrCL0cSzLjvIMfR9uo7cWg==} + /@typescript-eslint/scope-manager@6.1.0: + resolution: {integrity: sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.0.0 - '@typescript-eslint/visitor-keys': 6.0.0 + '@typescript-eslint/types': 6.1.0 + '@typescript-eslint/visitor-keys': 6.1.0 dev: true - /@typescript-eslint/type-utils@6.0.0(eslint@8.45.0)(typescript@5.1.6): - resolution: {integrity: sha512-ah6LJvLgkoZ/pyJ9GAdFkzeuMZ8goV6BH7eC9FPmojrnX9yNCIsfjB+zYcnex28YO3RFvBkV6rMV6WpIqkPvoQ==} + /@typescript-eslint/type-utils@6.1.0(eslint@8.45.0)(typescript@5.1.6): + resolution: {integrity: sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1432,8 +1431,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.1.6) - '@typescript-eslint/utils': 6.0.0(eslint@8.45.0)(typescript@5.1.6) + '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.1.6) + '@typescript-eslint/utils': 6.1.0(eslint@8.45.0)(typescript@5.1.6) debug: 4.3.4 eslint: 8.45.0 ts-api-utils: 1.0.1(typescript@5.1.6) @@ -1442,13 +1441,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@6.0.0: - resolution: {integrity: sha512-Zk9KDggyZM6tj0AJWYYKgF0yQyrcnievdhG0g5FqyU3Y2DRxJn4yWY21sJC0QKBckbsdKKjYDV2yVrrEvuTgxg==} + /@typescript-eslint/types@6.1.0: + resolution: {integrity: sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.0.0(typescript@5.1.6): - resolution: {integrity: sha512-2zq4O7P6YCQADfmJ5OTDQTP3ktajnXIRrYAtHM9ofto/CJZV3QfJ89GEaM2BNGeSr1KgmBuLhEkz5FBkS2RQhQ==} + /@typescript-eslint/typescript-estree@6.1.0(typescript@5.1.6): + resolution: {integrity: sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1456,8 +1455,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.0.0 - '@typescript-eslint/visitor-keys': 6.0.0 + '@typescript-eslint/types': 6.1.0 + '@typescript-eslint/visitor-keys': 6.1.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1468,8 +1467,8 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@6.0.0(eslint@8.45.0)(typescript@5.1.6): - resolution: {integrity: sha512-SOr6l4NB6HE4H/ktz0JVVWNXqCJTOo/mHnvIte1ZhBQ0Cvd04x5uKZa3zT6tiodL06zf5xxdK8COiDvPnQ27JQ==} + /@typescript-eslint/utils@6.1.0(eslint@8.45.0)(typescript@5.1.6): + resolution: {integrity: sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1477,22 +1476,21 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.45.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.0.0 - '@typescript-eslint/types': 6.0.0 - '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.1.6) + '@typescript-eslint/scope-manager': 6.1.0 + '@typescript-eslint/types': 6.1.0 + '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.1.6) eslint: 8.45.0 - eslint-scope: 5.1.1 semver: 7.5.4 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys@6.0.0: - resolution: {integrity: sha512-cvJ63l8c0yXdeT5POHpL0Q1cZoRcmRKFCtSjNGJxPkcP571EfZMcNbzWAc7oK3D1dRzm/V5EwtkANTZxqvuuUA==} + /@typescript-eslint/visitor-keys@6.1.0: + resolution: {integrity: sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.0.0 + '@typescript-eslint/types': 6.1.0 eslint-visitor-keys: 3.4.1 dev: true @@ -1955,23 +1953,23 @@ packages: csstype: 3.1.2 dev: false - /echarts-for-react@3.0.2(echarts@5.4.2)(react@18.2.0): + /echarts-for-react@3.0.2(echarts@5.4.3)(react@18.2.0): resolution: {integrity: sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==} peerDependencies: echarts: ^3.0.0 || ^4.0.0 || ^5.0.0 react: ^15.0.0 || >=16.0.0 dependencies: - echarts: 5.4.2 + echarts: 5.4.3 fast-deep-equal: 3.1.3 react: 18.2.0 size-sensor: 1.0.1 dev: false - /echarts@5.4.2: - resolution: {integrity: sha512-2W3vw3oI2tWJdyAz+b8DuWS0nfXtSDqlDmqgin/lfzbkB01cuMEN66KWBlmur3YMp5nEDEEt5s23pllnAzB4EA==} + /echarts@5.4.3: + resolution: {integrity: sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==} dependencies: tslib: 2.3.0 - zrender: 5.4.3 + zrender: 5.4.4 dev: false /electron-to-chromium@1.4.461: @@ -2480,10 +2478,6 @@ packages: get-intrinsic: 1.2.1 dev: true - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true - /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true @@ -3350,26 +3344,26 @@ packages: use-sidecar: 1.1.2(@types/react@18.2.15)(react@18.2.0) dev: false - /react-router-dom@6.14.1(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-ssF6M5UkQjHK70fgukCJyjlda0Dgono2QGwqGvuk7D+EDGHdacEN3Yke2LTMjkrpHuFwBfDFsEjGVXBDmL+bWw==} + /react-router-dom@6.14.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5pWX0jdKR48XFZBuJqHosX3AAHjRAzygouMTyimnBPOLdY3WjzUSKhus2FVMihUFWzeLebDgr4r8UeQFAct7Bg==} engines: {node: '>=14'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' dependencies: - '@remix-run/router': 1.7.1 + '@remix-run/router': 1.7.2 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-router: 6.14.1(react@18.2.0) + react-router: 6.14.2(react@18.2.0) dev: false - /react-router@6.14.1(react@18.2.0): - resolution: {integrity: sha512-U4PfgvG55LdvbQjg5Y9QRWyVxIdO1LlpYT7x+tMAxd9/vmiPuJhIwdxZuIQLN/9e3O4KFDHYfR9gzGeYMasW8g==} + /react-router@6.14.2(react@18.2.0): + resolution: {integrity: sha512-09Zss2dE2z+T1D03IheqAFtK4UzQyX8nFPWx6jkwdYzGLXd5ie06A6ezS2fO6zJfEb/SpG6UocN2O1hfD+2urQ==} engines: {node: '>=14'} peerDependencies: react: '>=16.8' dependencies: - '@remix-run/router': 1.7.1 + '@remix-run/router': 1.7.2 react: 18.2.0 dev: false @@ -3485,8 +3479,8 @@ packages: dependencies: glob: 7.2.3 - /rollup@3.26.2: - resolution: {integrity: sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==} + /rollup@3.26.3: + resolution: {integrity: sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: @@ -4051,7 +4045,7 @@ packages: '@types/node': 20.4.2 esbuild: 0.18.13 postcss: 8.4.26 - rollup: 3.26.2 + rollup: 3.26.3 optionalDependencies: fsevents: 2.3.2 @@ -4182,8 +4176,8 @@ packages: engines: {node: '>=10'} dev: true - /zrender@5.4.3: - resolution: {integrity: sha512-DRUM4ZLnoaT0PBVvGBDO9oWIDBKFdAVieNWxWwK0niYzJCMwGchRk21/hsE+RKkIveH3XHCyvXcJDkgLVvfizQ==} + /zrender@5.4.4: + resolution: {integrity: sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==} dependencies: tslib: 2.3.0 dev: false diff --git a/src/GZCTF/Controllers/EditController.cs b/src/GZCTF/Controllers/EditController.cs index 0376f5edb..39a41cbba 100644 --- a/src/GZCTF/Controllers/EditController.cs +++ b/src/GZCTF/Controllers/EditController.cs @@ -517,14 +517,9 @@ public async Task UpdateGameChallenge([FromRoute] int id, [FromRo if (model.FileName is not null && string.IsNullOrWhiteSpace(model.FileName)) return BadRequest(new RequestResponse("动态附件名不可为空")); - bool hintUpdated = model.Hints is not null && - model.Hints.Count > 0 && - model.Hints.GetSetHashCode() != res.Hints?.GetSetHashCode(); - - if (!string.IsNullOrWhiteSpace(model.FlagTemplate) - && res.Type == ChallengeType.DynamicContainer - && !model.FlagTemplate.Contains("[TEAM_HASH]") - && Codec.Leet.LeetEntropy(model.FlagTemplate) < 32.0) + bool hintUpdated = model.IsHintUpdated(res.Hints?.GetSetHashCode()); + + if (res.Type == ChallengeType.DynamicContainer && !model.IsValidFlagTemplate()) return BadRequest(new RequestResponse("flag 复杂度不足,请考虑添加队伍哈希或增加长度")); res.Update(model); diff --git a/src/GZCTF/Models/Request/Edit/ChallengeUpdateModel.cs b/src/GZCTF/Models/Request/Edit/ChallengeUpdateModel.cs index b7a809411..e2e4b5f03 100644 --- a/src/GZCTF/Models/Request/Edit/ChallengeUpdateModel.cs +++ b/src/GZCTF/Models/Request/Edit/ChallengeUpdateModel.cs @@ -1,4 +1,6 @@ using System.ComponentModel.DataAnnotations; +using GZCTF.Extensions; +using GZCTF.Utils; namespace GZCTF.Models.Request.Edit; @@ -100,4 +102,27 @@ public class ChallengeUpdateModel /// 统一文件名 /// public string? FileName { get; set; } + + /// + /// 提示是否存在更新 + /// + /// 原有哈希 + /// + internal bool IsHintUpdated(int? originalHash) + => Hints is not null && Hints.Count > 0 && + Hints.GetSetHashCode() != originalHash; + + /// + /// 是否为有效的 Flag 模板 + /// + /// + internal bool IsValidFlagTemplate() + { + if (string.IsNullOrWhiteSpace(FlagTemplate)) + return false; + + return FlagTemplate.Contains("[GUID]") || + FlagTemplate.Contains("[TEAM_HASH]") || + Codec.Leet.LeetEntropy(FlagTemplate) >= 32.0; + } }