package im.rosetta.executors; import java.util.Arrays; import java.util.HashSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import im.rosetta.Failures; import im.rosetta.client.tags.ECIAuthentificate; import im.rosetta.database.entity.User; import im.rosetta.database.repository.UserRepository; import im.rosetta.network.enums.ResultCode; import im.rosetta.network.packet.PacketResult; import im.rosetta.network.packet.PacketUserInfo; import im.rosetta.service.services.UserService; import io.orprotocol.ProtocolException; import io.orprotocol.client.Client; import io.orprotocol.packet.PacketExecutor; public class ExecutorUserInfo extends PacketExecutor { private final UserRepository userRepository = new UserRepository(); private final UserService userService = new UserService(userRepository); private final HashSet blockedUsernames = new HashSet<>(Arrays.asList( "user", "admin", "rosettasupport", "rosettaupdates", "freddie871", "updates", "deleted", "safety", "secure", "rosettasafe", "rosettadev1" )); @Override public void onPacketReceived(PacketUserInfo packet, Client client) throws Exception, ProtocolException { ECIAuthentificate eciAuthentificate = client.getTag(ECIAuthentificate.class); String username = packet.getUsername(); String title = packet.getTitle(); if(eciAuthentificate == null || !eciAuthentificate.hasAuthorized()){ /** * Только для авторизованных пользователей, а этот пользователь - не авторизован */ client.disconnect(Failures.HANDSHAKE_NOT_COMPLETED); return; } User user = userService.fromClient(client); if(user == null){ /** * Пользователь с таким ключем не найден в базе, * такого не может быть, но лучше чтобы была дополнительная проверка */ client.disconnect(Failures.DATA_MISSMATCH); return; } ResultCode usernameResult = tryChangeUsername(user, username); if(usernameResult == ResultCode.USERNAME_TAKEN){ /** * Это имя пользователя уже занято, отправляем клиенту ошибку */ PacketResult result = new PacketResult(); result.setResultCode(ResultCode.USERNAME_TAKEN); client.send(result); return; } if(usernameResult != ResultCode.SUCCESS){ /** * Не удалось сменить username, отправляем клиенту ошибку */ PacketResult result = new PacketResult(); result.setResultCode(ResultCode.INVALID); client.send(result); return; } ResultCode titleResult = tryChangeTitle(user, title); if(titleResult != ResultCode.SUCCESS){ /** * Не удалось сменить title, отправляем клиенту ошибку */ PacketResult result = new PacketResult(); result.setResultCode(ResultCode.INVALID); client.send(result); return; } /** * Отправляем клиенту успешный результат */ PacketResult result = new PacketResult(); result.setResultCode(ResultCode.SUCCESS); client.send(result); } /** * Пробует сменить username * @param user пользователь * @param username имя пользователя для смены * @return вернет false если смена прошла неудачно или true если username * не нуждается в изменении или изменен */ public ResultCode tryChangeUsername(User user, String username){ String targetRegexp = "^[a-z][a-z0-9_]{4,15}$"; Pattern pattern = Pattern.compile(targetRegexp); Matcher matcher = pattern.matcher(username); if(user.getUsername().equalsIgnoreCase(username)){ /** * Пользователь не меняет имя, значит операция прошла успешно, * по крайней мере нам не нужно возвращать клиенту код ошибки */ return ResultCode.SUCCESS; } if(!matcher.matches()){ /** * Не подходит по регулярному выражению */ return ResultCode.INVALID; } if(blockedUsernames.contains(username)){ /** * Это имя пользователя не доступно для смены */ return ResultCode.INVALID; } if(userService.isUsernameTaken(username)){ /** * Такое имя пользователя уже занято */ return ResultCode.USERNAME_TAKEN; } /** * Меняем имя пользователя */ user.setUsername(username); userRepository.update(user); return ResultCode.SUCCESS; } /** * Пробует сменить заголовок пользователя (title) * @param user пользователь * @param username имя пользователя для смены * @return вернет false если смена прошла неудачно или true если title * не нуждается в изменении или изменен */ public ResultCode tryChangeTitle(User user, String title) { String targetRegexp = "^[a-zA-Z0-9а-яА-Я _-]{1,22}$"; Pattern pattern = Pattern.compile(targetRegexp); Matcher matcher = pattern.matcher(title); if(user.getTitle().equalsIgnoreCase(title)){ /** * Пользователь не меняет имя, значит операция прошла успешно, * по крайней мере нам не нужно возвращать клиенту код ошибки */ return ResultCode.SUCCESS; } if(!matcher.matches()){ /** * Не подходит по регулярному выражению */ return ResultCode.INVALID; } /** * Меняем имя пользователя */ user.setTitle(title); userRepository.update(user); return ResultCode.SUCCESS; } }