From 5bc88b78a9b967dabc4bc5804b240016bf01e087 Mon Sep 17 00:00:00 2001 From: zhaodongsheng Date: Sun, 9 Jun 2024 08:16:45 +0800 Subject: [PATCH] (improvement)(login) encrypt password (#1081) (#1116) --- README.md | 2 +- README_CN.md | 2 +- .../adaptor/DefaultUserAdaptor.java | 31 ++- .../persistence/dataobject/UserDO.java | 10 + .../utils/AESEncryptionUtil.java | 59 ++++++ .../main/resources/mapper/UserDOMapper.xml | 13 +- .../src/main/resources/db/data-h2.sql | 10 +- .../src/main/resources/db/data-mysql.sql | 4 +- .../src/main/resources/db/schema-h2.sql | 3 +- .../src/main/resources/db/schema-mysql.sql | 3 +- .../util/AESEncryptionUtilTest.java | 35 ++++ webapp/packages/supersonic-fe/package.json | 2 +- .../supersonic-fe/src/pages/Login/index.tsx | 12 +- .../packages/supersonic-fe/src/utils/utils.ts | 13 ++ webapp/pnpm-lock.yaml | 185 +++++++++++------- 15 files changed, 289 insertions(+), 95 deletions(-) create mode 100644 auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/utils/AESEncryptionUtil.java create mode 100644 launchers/standalone/src/test/java/com/tencent/supersonic/util/AESEncryptionUtilTest.java diff --git a/README.md b/README.md index 76b93826d..96d6d9ee9 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ The high-level architecture and main process flow is as follows: ## Quick Demo ### Online playground -Visit http://117.72.46.148:9080 with username/password: admin/admin. Please do not modify system configurations. We will restart to reset configurations regularly every weekend. +Visit http://117.72.46.148:9080 to register and experience as a new user. Please do not modify system configurations. We will restart to reset configurations regularly every weekend. ## Local build SuperSonic comes with sample semantic models as well as chat conversations that can be used as a starting point. Please follow the steps: diff --git a/README_CN.md b/README_CN.md index 1fa992d81..efa27a95c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -53,7 +53,7 @@ SuperSonic的整体架构和主流程如下图所示: ## 快速体验 ### 线上环境体验 -访问http://117.72.46.148:9080 用户名/密码:admin/admin. 请勿修改系统配置。我们每周末定期重启重置配置。 +访问http://117.72.46.148:9080 注册新用户体验. 请勿修改系统配置。我们每周末定期重启重置配置。 ### 本地构建 diff --git a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/adaptor/DefaultUserAdaptor.java b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/adaptor/DefaultUserAdaptor.java index 203f914d4..b7aed34e7 100644 --- a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/adaptor/DefaultUserAdaptor.java +++ b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/adaptor/DefaultUserAdaptor.java @@ -9,6 +9,7 @@ import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword; import com.tencent.supersonic.auth.api.authentication.request.UserReq; import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO; import com.tencent.supersonic.auth.authentication.persistence.repository.UserRepository; +import com.tencent.supersonic.auth.authentication.utils.AESEncryptionUtil; import com.tencent.supersonic.auth.authentication.utils.UserTokenUtils; import com.tencent.supersonic.common.util.ContextUtils; import org.springframework.beans.BeanUtils; @@ -72,6 +73,14 @@ public class DefaultUserAdaptor implements UserAdaptor { } UserDO userDO = new UserDO(); BeanUtils.copyProperties(userReq, userDO); + try { + byte[] salt = AESEncryptionUtil.generateSalt(userDO.getName()); + userDO.setSalt(AESEncryptionUtil.getStringFromBytes(salt)); + System.out.println("salt: " + userDO.getSalt()); + userDO.setPassword(AESEncryptionUtil.encrypt(userReq.getPassword(), salt)); + } catch (Exception e) { + throw new RuntimeException("password encrypt error, please try again"); + } userRepository.addUser(userDO); } @@ -82,12 +91,24 @@ public class DefaultUserAdaptor implements UserAdaptor { if (userDO == null) { throw new RuntimeException("user not exist,please register"); } - if (userDO.getPassword().equals(userReq.getPassword())) { - UserWithPassword user = UserWithPassword.get(userDO.getId(), userDO.getName(), userDO.getDisplayName(), - userDO.getEmail(), userDO.getPassword(), userDO.getIsAdmin()); - return userTokenUtils.generateToken(user); + + try { + String password = AESEncryptionUtil.encrypt(userReq.getPassword(), + AESEncryptionUtil.getBytesFromString(userDO.getSalt())); + System.out.println("userReq.getPassword(): " + userReq.getPassword()); + System.out.println("password: " + password); + System.out.println("userDO.getPassword(): " + userDO.getPassword()); + if (userDO.getPassword().equals(password)) { + UserWithPassword user = UserWithPassword.get(userDO.getId(), userDO.getName(), userDO.getDisplayName(), + userDO.getEmail(), userDO.getPassword(), userDO.getIsAdmin()); + return userTokenUtils.generateToken(user); + } else { + throw new RuntimeException("password not correct, please try again"); + } + } catch (Exception e) { + throw new RuntimeException("password encrypt error, please try again"); } - throw new RuntimeException("password not correct, please try again"); + } @Override diff --git a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/persistence/dataobject/UserDO.java b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/persistence/dataobject/UserDO.java index af32a9aff..759a0b373 100644 --- a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/persistence/dataobject/UserDO.java +++ b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/persistence/dataobject/UserDO.java @@ -16,6 +16,8 @@ public class UserDO { */ private String password; + private String salt; + /** * */ @@ -79,6 +81,14 @@ public class UserDO { this.password = password == null ? null : password.trim(); } + public String getSalt() { + return salt; + } + + public void setSalt(String salt) { + this.salt = salt == null ? null : salt.trim(); + } + /** * * @return display_name diff --git a/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/utils/AESEncryptionUtil.java b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/utils/AESEncryptionUtil.java new file mode 100644 index 000000000..718e3819b --- /dev/null +++ b/auth/authentication/src/main/java/com/tencent/supersonic/auth/authentication/utils/AESEncryptionUtil.java @@ -0,0 +1,59 @@ +package com.tencent.supersonic.auth.authentication.utils; + +import javax.crypto.Cipher; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import javax.crypto.spec.IvParameterSpec; +import java.security.MessageDigest; +import java.security.spec.KeySpec; +import java.util.Base64; + +public class AESEncryptionUtil { + + private static final String ALGORITHM = "AES/CBC/PKCS5Padding"; + private static final String ENCODE = "UTF-8"; + private static final String SECRET_KEY_ALGORITHM = "PBKDF2WithHmacSHA256"; + private static final int ITERATIONS = 65536; + private static final int KEY_LENGTH = 256; + + public static byte[] generateSalt(String username) throws Exception { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(username.getBytes(ENCODE)); + byte[] hash = md.digest(); + // 通常只需要使用盐的一部分作为盐值,例如16字节 + byte[] salt = new byte[16]; + System.arraycopy(hash, 0, salt, 0, salt.length); + return salt; + } + + public static String encrypt(String password, byte[] salt) throws Exception { + // TODO 固定IV,确保每次加密时使用相同的IV,该值应该安全保管 + byte[] iv = "supersonic@bicom".getBytes(ENCODE); + IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); + + KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS, KEY_LENGTH); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(SECRET_KEY_ALGORITHM); + byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); + SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); + + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); + + byte[] encrypted = cipher.doFinal(password.getBytes(ENCODE)); + byte[] combined = new byte[iv.length + encrypted.length]; + System.arraycopy(iv, 0, combined, 0, iv.length); + System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length); + + return Base64.getEncoder().encodeToString(combined); + } + + public static String getStringFromBytes(byte[] salt) { + return Base64.getEncoder().encodeToString(salt); + } + + public static byte[] getBytesFromString(String encodeSalt) { + return Base64.getDecoder().decode(encodeSalt); + } + +} \ No newline at end of file diff --git a/auth/authentication/src/main/resources/mapper/UserDOMapper.xml b/auth/authentication/src/main/resources/mapper/UserDOMapper.xml index c1933db89..783906d5d 100644 --- a/auth/authentication/src/main/resources/mapper/UserDOMapper.xml +++ b/auth/authentication/src/main/resources/mapper/UserDOMapper.xml @@ -5,6 +5,7 @@ + @@ -39,7 +40,7 @@ - id, name, password, display_name, email, is_admin + id, name, password, salt, display_name, email, is_admin - insert into s2_user (id, name, password, + insert into s2_user (id, name, password, salt, display_name, email, is_admin ) - values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, + values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{salt,jdbcType=VARCHAR}, #{displayName,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{isAdmin,jdbcType=INTEGER} ) @@ -78,6 +79,9 @@ password, + + salt, + display_name, @@ -98,6 +102,9 @@ #{password,jdbcType=VARCHAR}, + + #{salt,jdbcType=VARCHAR}, + #{displayName,jdbcType=VARCHAR}, diff --git a/launchers/standalone/src/main/resources/db/data-h2.sql b/launchers/standalone/src/main/resources/db/data-h2.sql index b02eb480d..a1da0e280 100644 --- a/launchers/standalone/src/main/resources/db/data-h2.sql +++ b/launchers/standalone/src/main/resources/db/data-h2.sql @@ -1,9 +1,9 @@ -- sample user -MERGE INTO s2_user (id, `name`, password, display_name, email, is_admin) values (1, 'admin','admin','admin','admin@xx.com', 1); -MERGE INTO s2_user (id, `name`, password, display_name, email) values (2, 'jack','123456','jack','jack@xx.com'); -MERGE INTO s2_user (id, `name`, password, display_name, email) values (3, 'tom','123456','tom','tom@xx.com'); -MERGE INTO s2_user (id, `name`, password, display_name, email, is_admin) values (4, 'lucy','123456','lucy','lucy@xx.com', 1); -MERGE INTO s2_user (id, `name`, password, display_name, email) values (5, 'alice','123456','alice','alice@xx.com'); +MERGE INTO s2_user (id, `name`, password, salt, display_name, email, is_admin) values (1, 'admin11','c3VwZXJzb25pY0BiaWNvbQIY4hJ2TJ0bM4aJLIAEreUBTMlveZUDOTINOon+hs59pSoijg6AoB6m3khO/6lX/g==','jGl25bVBBBW96Qi9Te4V3w==','admin11','admin@xx.com', 1); +MERGE INTO s2_user (id, `name`, password, salt, display_name, email) values (2, 'jack','123456','123456','jack','jack@xx.com'); +MERGE INTO s2_user (id, `name`, password, salt, display_name, email) values (3, 'tom','123456','123456','tom','tom@xx.com'); +MERGE INTO s2_user (id, `name`, password, salt, display_name, email, is_admin) values (4, 'lucy','123456','123456','lucy','lucy@xx.com', 1); +MERGE INTO s2_user (id, `name`, password, salt, display_name, email) values (5, 'alice','123456','123456','alice','alice@xx.com'); MERGE INTO s2_available_date_info(`id`,`item_id` ,`type` ,`date_format` ,`start_date` ,`end_date` ,`unavailable_date` ,`created_at` ,`created_by` ,`updated_at` ,`updated_by` ) values (1 , 1, 'dimension', 'yyyy-MM-dd', DATEADD('DAY', -28, CURRENT_DATE()), DATEADD('DAY', -1, CURRENT_DATE()), '[]', '2023-06-01', 'admin', '2023-06-01', 'admin'); diff --git a/launchers/standalone/src/main/resources/db/data-mysql.sql b/launchers/standalone/src/main/resources/db/data-mysql.sql index 8ad7a7fd8..fcbe36b96 100644 --- a/launchers/standalone/src/main/resources/db/data-mysql.sql +++ b/launchers/standalone/src/main/resources/db/data-mysql.sql @@ -1,6 +1,6 @@ -- sample user -insert into s2_user (id, `name`, password, display_name, email, is_admin) values (1, 'admin','admin','admin','admin@xx.com', 1); -insert into s2_user (id, `name`, password, display_name, email, is_admin) values (4, 'lucy','123456','lucy','lucy@xx.com', 1); +insert into s2_user (id, `name`, password, salt, display_name, email, is_admin) values (1, 'admin','admin','admin','admin@xx.com', 1); +insert into s2_user (id, `name`, password, salt, display_name, email, is_admin) values (4, 'lucy','123456','lucy','lucy@xx.com', 1); INSERT INTO s2_available_date_info (`item_id`, `type`, `date_format`, `start_date`, `end_date`, `unavailable_date`, `created_at`, `created_by`, `updated_at`, `updated_by`) diff --git a/launchers/standalone/src/main/resources/db/schema-h2.sql b/launchers/standalone/src/main/resources/db/schema-h2.sql index 44c02570a..f954188bf 100644 --- a/launchers/standalone/src/main/resources/db/schema-h2.sql +++ b/launchers/standalone/src/main/resources/db/schema-h2.sql @@ -88,7 +88,8 @@ create table IF NOT EXISTS s2_user id INT AUTO_INCREMENT, name varchar(100) not null, display_name varchar(100) null, - password varchar(100) null, + password varchar(256) null, + salt varchar(256) NULL, email varchar(100) null, is_admin INT null, PRIMARY KEY (`id`) diff --git a/launchers/standalone/src/main/resources/db/schema-mysql.sql b/launchers/standalone/src/main/resources/db/schema-mysql.sql index aa1f05753..cecc87af6 100644 --- a/launchers/standalone/src/main/resources/db/schema-mysql.sql +++ b/launchers/standalone/src/main/resources/db/schema-mysql.sql @@ -426,7 +426,8 @@ create table s2_user id int(11) NOT NULL AUTO_INCREMENT, name varchar(100) not null, display_name varchar(100) null, - password varchar(100) null, + password varchar(256) null, + salt varchar(256) DEFAULT NULL COMMENT 'md5密码盐', email varchar(100) null, is_admin int(11) null, PRIMARY KEY (`id`) diff --git a/launchers/standalone/src/test/java/com/tencent/supersonic/util/AESEncryptionUtilTest.java b/launchers/standalone/src/test/java/com/tencent/supersonic/util/AESEncryptionUtilTest.java new file mode 100644 index 000000000..1a45b42ea --- /dev/null +++ b/launchers/standalone/src/test/java/com/tencent/supersonic/util/AESEncryptionUtilTest.java @@ -0,0 +1,35 @@ +package com.tencent.supersonic.util; + +import com.tencent.supersonic.auth.authentication.utils.AESEncryptionUtil; + +public class AESEncryptionUtilTest { + + public static boolean areByteArraysEqual(byte[] array1, byte[] array2) { + if (array1.length != array2.length) { + return false; + } + for (int i = 0; i < array1.length; i++) { + if (array1[i] != array2[i]) { + return false; + } + } + return true; + } + + public static void main(String[] args) throws Exception { + byte[] salt = AESEncryptionUtil.generateSalt("zhangsan1234"); + System.out.println("salt: " + salt); + String encodeSalt = AESEncryptionUtil.getStringFromBytes(salt); + System.out.println("encodeSalt: " + encodeSalt); + byte[] decodeSalt = AESEncryptionUtil.getBytesFromString(encodeSalt); + System.out.println("decodeSalt: " + decodeSalt); + + System.out.println("areByteArraysEqual: " + areByteArraysEqual(salt, decodeSalt)); + + String password = AESEncryptionUtil.encrypt("zhangsan1234", salt); + System.out.println("password: " + password); + String password2 = AESEncryptionUtil.encrypt("zhangsan1234", decodeSalt); + System.out.println("password2: " + password2); + + } +} diff --git a/webapp/packages/supersonic-fe/package.json b/webapp/packages/supersonic-fe/package.json index 1d50bd0d4..fa2a5cc2f 100644 --- a/webapp/packages/supersonic-fe/package.json +++ b/webapp/packages/supersonic-fe/package.json @@ -74,7 +74,7 @@ "compression-webpack-plugin": "^11.0.0", "copy-to-clipboard": "^3.3.1", "cross-env": "^7.0.3", - "crypto-js": "^4.0.0", + "crypto-js": "^4.2.0", "dayjs": "^1.11.10", "echarts": "^5.0.2", "echarts-for-react": "^3.0.1", diff --git a/webapp/packages/supersonic-fe/src/pages/Login/index.tsx b/webapp/packages/supersonic-fe/src/pages/Login/index.tsx index 3732506f4..7e1e4f7e4 100644 --- a/webapp/packages/supersonic-fe/src/pages/Login/index.tsx +++ b/webapp/packages/supersonic-fe/src/pages/Login/index.tsx @@ -13,6 +13,7 @@ import { postUserLogin, userRegister } from './services'; import { AUTH_TOKEN_KEY } from '@/common/constants'; import { queryCurrentUser } from '@/services/user'; import { history, useModel } from 'umi'; +import {encryptPassword} from "@/utils/utils"; const { Item } = Form; const LoginPage: React.FC = () => { @@ -43,21 +44,24 @@ const LoginPage: React.FC = () => { message.success(msg); }; + + // 处理登录按钮响应 const handleLogin = async () => { const { validateFields } = form; const content = await validateFields(); - await loginDone(content); + await loginDone({...content, password: encryptPassword(content.password)}); }; // 处理注册弹窗确定按钮 const handleRegister = async (values: RegisterFormDetail) => { - const { code } = await userRegister({ ...values }); + const enCodeValues = { ...values, password: encryptPassword(values.password) }; + const { code } = await userRegister(enCodeValues); if (code === 200) { message.success('注册成功'); setCreateModalVisible(false); // 注册完自动帮用户登录 - await loginDone(values); + await loginDone(enCodeValues); } }; @@ -103,7 +107,7 @@ const LoginPage: React.FC = () => { } /> diff --git a/webapp/packages/supersonic-fe/src/utils/utils.ts b/webapp/packages/supersonic-fe/src/utils/utils.ts index 7136b3742..1f48b8fd0 100644 --- a/webapp/packages/supersonic-fe/src/utils/utils.ts +++ b/webapp/packages/supersonic-fe/src/utils/utils.ts @@ -3,6 +3,7 @@ import { message } from 'antd'; import numeral from 'numeral'; import copy from 'copy-to-clipboard'; import { isString } from 'lodash'; +import CryptoJS from 'crypto-js'; /* eslint no-useless-escape:0 */ const reg = @@ -470,3 +471,15 @@ export const objToArray = (_obj: ObjToArrayParams, keyType: string = 'string') = }; }); }; + +export function encryptPassword(password: string, username: string) { + if (!password) { + return password; + } + // TODO This key should be stored in a secure place + const key = CryptoJS.enc.Utf8.parse('supersonic@2024'); + const srcs = CryptoJS.enc.Utf8.parse(password); + const encrypted = CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7}); + return encrypted.toString(); + +}; diff --git a/webapp/pnpm-lock.yaml b/webapp/pnpm-lock.yaml index 2deaa67cc..f4260b1cd 100644 --- a/webapp/pnpm-lock.yaml +++ b/webapp/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - importers: packages/chat-sdk: @@ -364,7 +360,7 @@ importers: specifier: ^7.0.3 version: 7.0.3 crypto-js: - specifier: ^4.0.0 + specifier: ^4.2.0 version: 4.2.0 dayjs: specifier: ^1.11.10 @@ -582,7 +578,7 @@ packages: babel-plugin-import: 1.13.8 babel-runtime-jsx-plus: 0.1.5 classnames: 2.5.1 - dva-core: 2.0.4(redux@4.2.1) + dva-core: 2.0.4(redux@3.7.2) dva-immer: 1.0.2(dva@2.5.0-beta.2) dva-loading: 3.0.25(dva-core@2.0.4) history: 5.3.0 @@ -5549,7 +5545,7 @@ packages: dependencies: '@babel/core': 7.24.5 postcss: 8.4.38 - postcss-syntax: 0.36.2(postcss@8.4.38) + postcss-syntax: 0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39) transitivePeerDependencies: - supports-color dev: true @@ -7185,6 +7181,18 @@ packages: - react-router dev: true + /@umijs/bundler-utils@3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0): + resolution: {integrity: sha512-irJUU/eWa2GG6JCkz172lMi+jiq7ZXatE2N7Tq/lokZUYu9R9BRaRN7dphgBlAUfOP3aBtjx51/5yZdYAeW0yQ==} + dependencies: + '@umijs/babel-preset-umi': 3.5.41 + '@umijs/types': 3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0) + '@umijs/utils': 3.5.41 + transitivePeerDependencies: + - react + - react-dom + - react-router + dev: true + /@umijs/bundler-utils@4.2.5: resolution: {integrity: sha512-Hj8Uda4E/Bf9aIWLfMiixxjFRRXaVDQDU1MbUf7HhDtpgmfeQfIfWhzWRat9B8TfPLDA4KI3yW1EPdlNHGBiSA==} dependencies: @@ -7248,6 +7256,31 @@ packages: - react-router dev: true + /@umijs/bundler-webpack@3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0): + resolution: {integrity: sha512-n4HIrDUE3QfN5xSTWJlRz5wzsnWggzRJhEDJZ6l23BWiwWasFW6QMGCnFWLwO93ei273LovylD5vZhI221tBtQ==} + hasBin: true + dependencies: + '@umijs/bundler-utils': 3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0) + '@umijs/case-sensitive-paths-webpack-plugin': 1.0.1 + '@umijs/deps': 3.5.41 + '@umijs/types': 3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0) + '@umijs/utils': 3.5.41 + jest-worker: 26.6.2 + node-libs-browser: 2.2.1 + normalize-url: 1.9.1 + postcss: 7.0.32 + postcss-flexbugs-fixes: 4.2.1 + postcss-loader: 3.0.0 + postcss-preset-env: 6.7.0 + postcss-safe-parser: 4.0.2 + terser: 5.14.2 + webpack-chain: 6.5.1 + transitivePeerDependencies: + - react + - react-dom + - react-router + dev: true + /@umijs/bundler-webpack@4.2.5(typescript@4.9.5)(webpack@5.91.0): resolution: {integrity: sha512-kABzFUTbkgccf2XwMiKEEVyfBuvZZSnFFU7E1uu2OQg3x7rv5dnF9yrMGwvul4I0KClPZAabd5eaf7WuKYyBAA==} hasBin: true @@ -7522,7 +7555,7 @@ packages: eslint-plugin-react: 7.33.2(eslint@8.35.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.35.0) postcss: 8.4.38 - postcss-syntax: 0.36.2(postcss@8.4.38) + postcss-syntax: 0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39) stylelint-config-standard: 25.0.0(stylelint@14.8.2) transitivePeerDependencies: - eslint @@ -7692,7 +7725,7 @@ packages: umi: 3.x dependencies: fast-deep-equal: 3.1.1 - umi: 3.5.41(react-router@5.2.0) + umi: 3.5.41(react-router@6.23.1) dev: true /@umijs/plugin-run@4.2.5: @@ -7824,7 +7857,7 @@ packages: mime: 1.4.1 react: 16.14.0 react-refresh: 0.10.0 - react-router: 5.2.0(react@18.3.1) + react-router: 5.2.0(react@16.14.0) react-router-config: 5.1.1(react-router@5.2.0)(react@16.14.0) react-router-dom: 5.2.0(react@16.14.0) regenerator-runtime: 0.13.5 @@ -7962,6 +7995,23 @@ packages: - react-router dev: true + /@umijs/renderer-react@3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0): + resolution: {integrity: sha512-DmExaziU84uFXv09gYXpFk/tHB+mjINUD8YmYULjbQ+QQA9so2zkxNSv9gYy5hXNepheUMd+uriV/qUB6HNBVg==} + peerDependencies: + react: 16.x || 17.x + react-dom: 16.x || 17.x + dependencies: + '@types/react': 16.14.60 + '@types/react-dom': 16.9.24 + '@types/react-router-config': 5.0.2 + '@umijs/runtime': 3.5.41(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + react-router-config: 5.1.1(react-router@6.23.1)(react@16.14.0) + transitivePeerDependencies: + - react-router + dev: true + /@umijs/renderer-react@4.2.5(react-dom@18.1.0)(react@18.1.0): resolution: {integrity: sha512-WuV2ye/A9NY5eHQ9VH6pD1MEgeuBbn18AU9dpJku5gaQ0kigPIMfMLVuon1Cvwc2XA9ab+5HcpwsJiAqrde3EQ==} peerDependencies: @@ -8001,7 +8051,7 @@ packages: express: 4.19.2 lodash: 4.17.21 prettier: 2.8.8 - umi: 3.5.41(react-router@5.2.0) + umi: 3.5.41(react-router@6.23.1) transitivePeerDependencies: - supports-color dev: true @@ -8084,6 +8134,22 @@ packages: - react-router dev: true + /@umijs/types@3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0): + resolution: {integrity: sha512-pxvLiQ99EL8Yu98F/ZMojG9ukDptC315cnxSnRYOdS34F57oiIgW0Zoi0TrKlA0pVIQxC2MXzyQwy+HfDmB23Q==} + dependencies: + '@umijs/babel-preset-umi': 3.5.41 + '@umijs/core': 3.5.41 + '@umijs/deps': 3.5.41 + '@umijs/renderer-react': 3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0) + '@umijs/server': 3.5.41 + '@umijs/utils': 3.5.41 + webpack-chain: 6.5.1 + transitivePeerDependencies: + - react + - react-dom + - react-router + dev: true + /@umijs/ui@3.0.1: resolution: {integrity: sha512-zcz37AJH0xt/6XVVbyO/hmsK9Hq4vH23HZ4KYVi5A8rbM9KeJkJigTS7ELOdArawZhVNGe+h3a5Oixs4a2QsWw==} dev: true @@ -10340,6 +10406,7 @@ packages: /core-js@3.6.5: resolution: {integrity: sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==} + deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. requiresBuild: true dev: true @@ -11676,6 +11743,21 @@ packages: warning: 3.0.0 dev: true + /dva-core@2.0.4(redux@3.7.2): + resolution: {integrity: sha512-Zh39llFyItu9HKXKfCZVf9UFtDTcypdAjGBew1S+wK8BGVzFpm1GPTdd6uIMeg7O6STtCvt2Qv+RwUut1GFynA==} + peerDependencies: + redux: 4.x + dependencies: + '@babel/runtime': 7.24.5 + flatten: 1.0.3 + global: 4.4.0 + invariant: 2.2.4 + is-plain-object: 2.0.4 + redux: 3.7.2 + redux-saga: 0.16.2 + warning: 3.0.0 + dev: true + /dva-core@2.0.4(redux@4.2.1): resolution: {integrity: sha512-Zh39llFyItu9HKXKfCZVf9UFtDTcypdAjGBew1S+wK8BGVzFpm1GPTdd6uIMeg7O6STtCvt2Qv+RwUut1GFynA==} peerDependencies: @@ -17686,19 +17768,6 @@ packages: tiny-warning: 1.0.3 dev: true - /mini-create-react-context@0.4.1(prop-types@15.8.1)(react@18.3.1): - resolution: {integrity: sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - peerDependencies: - prop-types: ^15.0.0 - react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - '@babel/runtime': 7.24.5 - prop-types: 15.8.1 - react: 18.3.1 - tiny-warning: 1.0.3 - dev: true - /mini-css-extract-plugin@2.9.0(webpack@5.91.0): resolution: {integrity: sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==} engines: {node: '>= 12.13.0'} @@ -18096,7 +18165,7 @@ packages: dev: true /normalize-url@1.9.1: - resolution: {integrity: sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=} + resolution: {integrity: sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==} engines: {node: '>=4'} dependencies: object-assign: 4.1.1 @@ -20412,30 +20481,6 @@ packages: postcss-scss: 2.1.1 dev: true - /postcss-syntax@0.36.2(postcss@8.4.38): - resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==} - peerDependencies: - postcss: '>=5.0.0' - postcss-html: '*' - postcss-jsx: '*' - postcss-less: '*' - postcss-markdown: '*' - postcss-scss: '*' - peerDependenciesMeta: - postcss-html: - optional: true - postcss-jsx: - optional: true - postcss-less: - optional: true - postcss-markdown: - optional: true - postcss-scss: - optional: true - dependencies: - postcss: 8.4.38 - dev: true - /postcss-unique-selectors@5.1.1(postcss@8.4.38): resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} engines: {node: ^10 || ^12 || >=14.0} @@ -22869,7 +22914,18 @@ packages: dependencies: '@babel/runtime': 7.24.5 react: 16.14.0 - react-router: 5.2.0(react@18.3.1) + react-router: 5.2.0(react@16.14.0) + dev: true + + /react-router-config@5.1.1(react-router@6.23.1)(react@16.14.0): + resolution: {integrity: sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==} + peerDependencies: + react: '>=15' + react-router: '>=5' + dependencies: + '@babel/runtime': 7.24.5 + react: 16.14.0 + react-router: 6.23.1(react@18.3.1) dev: true /react-router-dom@4.3.1(react@18.3.1): @@ -22983,24 +23039,6 @@ packages: tiny-warning: 1.0.3 dev: true - /react-router@5.2.0(react@18.3.1): - resolution: {integrity: sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==} - peerDependencies: - react: '>=15' - dependencies: - '@babel/runtime': 7.24.5 - history: 4.10.1 - hoist-non-react-statics: 3.3.2 - loose-envify: 1.4.0 - mini-create-react-context: 0.4.1(prop-types@15.8.1)(react@18.3.1) - path-to-regexp: 1.8.0 - prop-types: 15.8.1 - react: 18.3.1 - react-is: 16.13.1 - tiny-invariant: 1.3.3 - tiny-warning: 1.0.3 - dev: true - /react-router@6.23.1(react@18.3.1): resolution: {integrity: sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==} engines: {node: '>=14.0.0'} @@ -26344,16 +26382,16 @@ packages: slash2: 2.0.0 dev: true - /umi@3.5.41(react-router@5.2.0): + /umi@3.5.41(react-router@6.23.1): resolution: {integrity: sha512-sjgfFGC3E5jG5Cn8pXdwODDgPW1hnlkn24f7+onNnNdq77syuc4s3R5z7BKQHbjiWtVVIV1VOFMYE9JsJYnOPQ==} hasBin: true dependencies: - '@umijs/bundler-webpack': 3.5.41(react-dom@16.14.0)(react-router@5.2.0)(react@16.14.0) + '@umijs/bundler-webpack': 3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0) '@umijs/core': 3.5.41 '@umijs/deps': 3.5.41 '@umijs/preset-built-in': 3.5.41(react-dom@16.14.0)(react@16.14.0) '@umijs/runtime': 3.5.41(react@16.14.0) - '@umijs/types': 3.5.41(react-dom@16.14.0)(react-router@5.2.0)(react@16.14.0) + '@umijs/types': 3.5.41(react-dom@16.14.0)(react-router@6.23.1)(react@16.14.0) '@umijs/utils': 3.5.41 react: 16.14.0 react-dom: 16.14.0(react@16.14.0) @@ -26990,6 +27028,7 @@ packages: /webpack-chain@6.5.1: resolution: {integrity: sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==} engines: {node: '>=8'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. dependencies: deepmerge: 1.5.2 javascript-stringify: 2.1.0 @@ -27682,3 +27721,7 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} dev: false + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false