From 7a167b470a63e6215f0252a10490027edf26dcdcc0898edb0024c37f549589a5 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Thu, 8 Jan 2026 15:02:01 +0300 Subject: [PATCH] =?UTF-8?q?08=2001=2025=20=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D0=BB=20=D1=87=D1=82=D0=BE=20=D0=B1=D1=8B=20=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B0=D0=B2=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D1=81=D1=8C=20=D1=82=D1=80=D0=B8=20=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B0=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8F.=20=D0=98=20=D0=B8=D0=BC=D1=8F=20?= =?UTF-8?q?=D0=B1=D0=BB=D0=BE=D0=BA=D1=87=D0=B5=D0=B9=D0=BD=D0=B0=20=D1=81?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7?= =?UTF-8?q?=20"-"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DOC/TODO то что пока отложенно на будущее.md | 2 +- .../utils/blockchain/BlockchainNameUtil.java | 62 +++++++++++++++++-- .../tempToTest/Net_AddUser_Handler.java | 28 ++++++--- .../entyties/Net_AddUser_Request.java | 12 ++++ .../entyties/Net_AddUser_Response.java | 2 +- src/test/java/test/it/utils/TestConfig.java | 18 ++++-- .../java/test/it/utils/json/JsonBuilders.java | 16 ++++- 7 files changed, 116 insertions(+), 24 deletions(-) diff --git a/DOC/TODO то что пока отложенно на будущее.md b/DOC/TODO то что пока отложенно на будущее.md index 7afb6dd..184a98e 100644 --- a/DOC/TODO то что пока отложенно на будущее.md +++ b/DOC/TODO то что пока отложенно на будущее.md @@ -1,2 +1,2 @@ Сделать возможность убрать свой лайк. (пока не надо а сложность что надо больше проверок) - хотя можно и без проверки, просто за двойной лайк или за снятие двойное лайка. Будет двойное проникновение :)) тому кто изменил код клиента и убрал проверку на клиенте - и блокчейн заблокируется и всё. -поэтому просто на каждую реакцию добавиться убрать эту ракцию . \ No newline at end of file +поэтому просто на каждую реакцию добавиться убрать эту ракцию . diff --git a/shine-server-blockchain/src/main/java/utils/blockchain/BlockchainNameUtil.java b/shine-server-blockchain/src/main/java/utils/blockchain/BlockchainNameUtil.java index d8a315a..acc55c6 100644 --- a/shine-server-blockchain/src/main/java/utils/blockchain/BlockchainNameUtil.java +++ b/shine-server-blockchain/src/main/java/utils/blockchain/BlockchainNameUtil.java @@ -1,21 +1,71 @@ package utils.blockchain; +import java.util.Objects; + public final class BlockchainNameUtil { - /** Сколько символов отрезаем с конца blockchainName, чтобы получить login. */ - /** Теперь новое правило везде использовать только 3 символа номера блокчена в конце его имени */ - public static final int BLOCKCHAIN_NAME_LOGIN_SUFFIX_LEN = 3; + /** + * Теперь новое правило: + * blockchainName = login + "-"+ 3 цифры + * Пример: "Dima-001" -> "Dima" + * + * Сколько символов отрезаем с конца blockchainName, чтобы получить login: "-001" = 4 + */ + public static final int BLOCKCHAIN_NAME_LOGIN_SUFFIX_LEN = 4; private BlockchainNameUtil() {} /** - * Извлечь login из blockchainName: отрезаем последние 3 символа. - * Пример: "Dima001" -> "Dima" + * Извлечь login из blockchainName: отрезаем последние 4 символа ("-NNN"). + * Пример: "Dima-001" -> "Dima" */ public static String loginFromBlockchainName(String blockchainName) { if (blockchainName == null) return null; + String s = blockchainName.trim(); - if (s.length() <= BLOCKCHAIN_NAME_LOGIN_SUFFIX_LEN) return null; + if (!hasDashAnd3DigitsSuffix(s)) return null; + return s.substring(0, s.length() - BLOCKCHAIN_NAME_LOGIN_SUFFIX_LEN); } + + /** + * Проверка правила: + * - blockchainName должен оканчиваться на "-"+3 цифры + * - blockchainName без суффикса "-NNN" должен равняться login + * + * ВАЖНО: + * - сравнение строгое (case-sensitive) + * - null/blank считаем невалидным + */ + public static boolean isBlockchainNameMatchesLogin(String blockchainName, String login) { + if (blockchainName == null || login == null) return false; + + String bn = blockchainName.trim(); + String lg = login.trim(); + + if (bn.isEmpty() || lg.isEmpty()) return false; + if (!hasDashAnd3DigitsSuffix(bn)) return false; + + String extracted = bn.substring(0, bn.length() - BLOCKCHAIN_NAME_LOGIN_SUFFIX_LEN); + return Objects.equals(extracted, lg); + } + + private static boolean hasDashAnd3DigitsSuffix(String s) { + if (s == null) return false; + int len = s.length(); + if (len <= BLOCKCHAIN_NAME_LOGIN_SUFFIX_LEN) return false; + + int dashPos = len - 4; + if (s.charAt(dashPos) != '-') return false; + + char c1 = s.charAt(len - 3); + char c2 = s.charAt(len - 2); + char c3 = s.charAt(len - 1); + + return isDigit(c1) && isDigit(c2) && isDigit(c3); + } + + private static boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } } \ No newline at end of file diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_AddUser_Handler.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_AddUser_Handler.java index 387ae13..e38d9b9 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_AddUser_Handler.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/Net_AddUser_Handler.java @@ -5,9 +5,9 @@ import org.slf4j.LoggerFactory; import server.logic.ws_protocol.JSON.ConnectionContext; import server.logic.ws_protocol.JSON.entyties.Net_Request; import server.logic.ws_protocol.JSON.entyties.Net_Response; +import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; import server.logic.ws_protocol.JSON.handlers.tempToTest.entyties.Net_AddUser_Request; import server.logic.ws_protocol.JSON.handlers.tempToTest.entyties.Net_AddUser_Response; -import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory; import server.logic.ws_protocol.WireCodes; import shine.db.SqliteDbController; @@ -15,6 +15,7 @@ import shine.db.dao.BlockchainStateDAO; import shine.db.dao.SolanaUsersDAO; import shine.db.entities.BlockchainStateEntry; import shine.db.entities.SolanaUserEntry; +import utils.blockchain.BlockchainNameUtil; import java.sql.Connection; import java.sql.SQLException; @@ -34,13 +35,24 @@ public class Net_AddUser_Handler implements JsonMessageHandler { if (req.getLogin() == null || req.getLogin().isBlank() || req.getBlockchainName() == null || req.getBlockchainName().isBlank() || req.getSolanaKey() == null || req.getSolanaKey().isBlank() + || req.getBlockchainKey() == null || req.getBlockchainKey().isBlank() || req.getDeviceKey() == null || req.getDeviceKey().isBlank()) { return NetExceptionResponseFactory.error( req, WireCodes.Status.BAD_REQUEST, "BAD_FIELDS", - "Некорректные поля: login/blockchainName/solanaKey/deviceKey" + "Некорректные поля: login/blockchainName/solanaKey/blockchainKey/deviceKey" + ); + } + + // blockchainName должен быть вида: -NNN + if (!BlockchainNameUtil.isBlockchainNameMatchesLogin(req.getBlockchainName(), req.getLogin())) { + return NetExceptionResponseFactory.error( + req, + WireCodes.Status.BAD_REQUEST, + "BAD_BLOCKCHAIN_NAME", + "blockchainName должен быть вида -NNN (пример: anya-001)" ); } @@ -49,13 +61,13 @@ public class Net_AddUser_Handler implements JsonMessageHandler { : req.getBchLimit(); try { - byte[] blockchainKey32 = Base64.getDecoder().decode(req.getSolanaKey()); + byte[] blockchainKey32 = Base64.getDecoder().decode(req.getBlockchainKey()); if (blockchainKey32.length != 32) { return NetExceptionResponseFactory.error( req, WireCodes.Status.BAD_REQUEST, "BAD_BLOCKCHAIN_KEY", - "solanaKey должен быть Base64(32 bytes)" + "blockchainKey должен быть Base64(32 bytes)" ); } @@ -87,20 +99,20 @@ public class Net_AddUser_Handler implements JsonMessageHandler { ); } - // 3. Создаём пользователя + // 3. Создаём пользователя (solanaKey + deviceKey) SolanaUserEntry user = new SolanaUserEntry( req.getLogin(), - req.getDeviceKey(), + req.getSolanaKey(), req.getDeviceKey() ); usersDAO.insert(c, user); - // 4. Создаём INITIAL blockchain_state + // 4. Создаём INITIAL blockchain_state (blockchainKey) BlockchainStateEntry st = new BlockchainStateEntry(); st.setBlockchainName(req.getBlockchainName()); st.setLogin(req.getLogin()); - st.setBlockchainKey(req.getSolanaKey()); // Base64(32) + st.setBlockchainKey(req.getBlockchainKey()); // Base64(32) st.setLastGlobalNumber(-1); st.setLastGlobalHash(new byte[32]); st.setFileSizeBytes(0); diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_AddUser_Request.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_AddUser_Request.java index 9a8df2e..acae651 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_AddUser_Request.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_AddUser_Request.java @@ -14,6 +14,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Request; * "login": "anya", * "blockchainName": "anya0001", * "solanaKey": "base64-ed25519-public-key-login", + * "blockchainKey": "base64-ed25519-public-key-blockchain", * "deviceKey": "base64-ed25519-public-key-device", * "bchLimit": 1000000 * } @@ -25,8 +26,16 @@ public class Net_AddUser_Request extends Net_Request { private String login; private String blockchainName; + + /** Ключ пользователя Solana (публичный ключ логина) */ private String solanaKey; + + /** Ключ блокчейна (публичный ключ блокчейна) */ + private String blockchainKey; + + /** Ключ устройства (публичный ключ устройства) */ private String deviceKey; + private Integer bchLimit; public String getLogin() { return login; } @@ -38,6 +47,9 @@ public class Net_AddUser_Request extends Net_Request { public String getSolanaKey() { return solanaKey; } public void setSolanaKey(String solanaKey) { this.solanaKey = solanaKey; } + public String getBlockchainKey() { return blockchainKey; } + public void setBlockchainKey(String blockchainKey) { this.blockchainKey = blockchainKey; } + public String getDeviceKey() { return deviceKey; } public void setDeviceKey(String deviceKey) { this.deviceKey = deviceKey; } diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_AddUser_Response.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_AddUser_Response.java index e9452c0..e1da694 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_AddUser_Response.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/tempToTest/entyties/Net_AddUser_Response.java @@ -17,4 +17,4 @@ import server.logic.ws_protocol.JSON.entyties.Net_Response; */ public class Net_AddUser_Response extends Net_Response { // При необходимости сюда можно добавить, например, флаг created/updated и т.п. -} +} \ No newline at end of file diff --git a/src/test/java/test/it/utils/TestConfig.java b/src/test/java/test/it/utils/TestConfig.java index d3b1686..1561da4 100644 --- a/src/test/java/test/it/utils/TestConfig.java +++ b/src/test/java/test/it/utils/TestConfig.java @@ -10,7 +10,7 @@ import java.util.concurrent.ConcurrentHashMap; * TestConfig — конфиг IT тестов: * - 3 пользователя (TestUser1/2/3) * - ключи по login через map (device/solana/blockchain) - * - blockchainName = login + "001" + * - blockchainName = login + "-" + "001" * * Важно: * - privateKey = Ed25519Util.generatePrivateKeyFromString(login) (sha256, 32 bytes) @@ -45,7 +45,7 @@ public final class TestConfig { public static String getBlockchainName(String login) { if (login == null) throw new IllegalArgumentException("login is null"); - return login + BCH_SUFFIX_3(); + return login + "-" + BCH_SUFFIX_3(); } // ============ key maps ============ @@ -92,6 +92,7 @@ public final class TestConfig { // ============ base64 helpers ============ public static String devicePublicKeyB64(String login) { return Base64.getEncoder().encodeToString(getDevicePublicKey(login)); } + public static String solanaPublicKeyB64(String login) { return Base64.getEncoder().encodeToString(getSolanaPublicKey(login)); } public static String blockchainPublicKeyB64(String login) { return Base64.getEncoder().encodeToString(getBlockchainPublicKey(login)); } // ============ backward-compatible helpers for "user1" ============ @@ -99,10 +100,15 @@ public final class TestConfig { public static String BCH_NAME2() { return getBlockchainName(LOGIN2()); } public static String BCH_NAME3() { return getBlockchainName(LOGIN3()); } - /** solanaKey для AddUser: по твоему решению = blockchain pubkey. */ - public static String LOGIN_PUBKEY_B64() { return blockchainPublicKeyB64(LOGIN()); } - public static String LOGIN2_PUBKEY_B64() { return blockchainPublicKeyB64(LOGIN2()); } - public static String LOGIN3_PUBKEY_B64() { return blockchainPublicKeyB64(LOGIN3()); } + /** solanaKey для AddUser: публичный ключ Solana-пользователя */ + public static String SOLANA_PUBKEY_B64() { return solanaPublicKeyB64(LOGIN()); } + public static String SOLANA2_PUBKEY_B64() { return solanaPublicKeyB64(LOGIN2()); } + public static String SOLANA3_PUBKEY_B64() { return solanaPublicKeyB64(LOGIN3()); } + + /** blockchainKey для AddUser: публичный ключ блокчейна */ + public static String BLOCKCHAIN_PUBKEY_B64() { return blockchainPublicKeyB64(LOGIN()); } + public static String BLOCKCHAIN2_PUBKEY_B64() { return blockchainPublicKeyB64(LOGIN2()); } + public static String BLOCKCHAIN3_PUBKEY_B64() { return blockchainPublicKeyB64(LOGIN3()); } public static String DEVICE_PUBKEY_B64() { return devicePublicKeyB64(LOGIN()); } public static String DEVICE2_PUBKEY_B64() { return devicePublicKeyB64(LOGIN2()); } diff --git a/src/test/java/test/it/utils/json/JsonBuilders.java b/src/test/java/test/it/utils/json/JsonBuilders.java index a866718..111d1de 100644 --- a/src/test/java/test/it/utils/json/JsonBuilders.java +++ b/src/test/java/test/it/utils/json/JsonBuilders.java @@ -16,8 +16,11 @@ public final class JsonBuilders { public static String addUser(String login) { String requestId = TestIds.next("adduser"); String blockchainName = TestConfig.getBlockchainName(login); - String solanaKeyB64 = TestConfig.blockchainPublicKeyB64(login); // solanaKey = blockchain pub + + String solanaKeyB64 = TestConfig.solanaPublicKeyB64(login); + String blockchainKeyB64 = TestConfig.blockchainPublicKeyB64(login); String deviceKeyB64 = TestConfig.devicePublicKeyB64(login); + return """ { "op": "AddUser", @@ -26,11 +29,20 @@ public final class JsonBuilders { "login": "%s", "blockchainName": "%s", "solanaKey": "%s", + "blockchainKey": "%s", "deviceKey": "%s", "bchLimit": %d } } - """.formatted(requestId, login, blockchainName, solanaKeyB64, deviceKeyB64, TestConfig.TEST_BCH_LIMIT); + """.formatted( + requestId, + login, + blockchainName, + solanaKeyB64, + blockchainKeyB64, + deviceKeyB64, + TestConfig.TEST_BCH_LIMIT + ); } // ---------------- AuthChallenge ----------------