122 lines
4.0 KiB
Java
122 lines
4.0 KiB
Java
|
|
package ins.frontend.utils;
|
||
|
|
|
||
|
|
import org.openautonomousconnection.webserver.utils.PasswordHasher;
|
||
|
|
|
||
|
|
import java.util.Objects;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Registration service for creating users with secure password hashing and basic validation.
|
||
|
|
*/
|
||
|
|
public final class RegistrationService {
|
||
|
|
|
||
|
|
private static final int USERNAME_MIN = 5;
|
||
|
|
private static final int USERNAME_MAX = 256;
|
||
|
|
private static final int PASSWORD_MIN = 6;
|
||
|
|
private static final int PASSWORD_MAX = 256;
|
||
|
|
|
||
|
|
private final UserDao userDao;
|
||
|
|
private final PasswordHasher hasher;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates a registration service.
|
||
|
|
*
|
||
|
|
* @param userDao user DAO
|
||
|
|
* @param hasher password hasher
|
||
|
|
*/
|
||
|
|
public RegistrationService(UserDao userDao, PasswordHasher hasher) {
|
||
|
|
this.userDao = Objects.requireNonNull(userDao, "userDao");
|
||
|
|
this.hasher = Objects.requireNonNull(hasher, "hasher");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static String normalizeUsername(String u) {
|
||
|
|
if (u == null) return null;
|
||
|
|
String t = u.trim();
|
||
|
|
return t.isEmpty() ? null : t;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static String validate(String username, String password) {
|
||
|
|
if (username == null) return "Missing username.";
|
||
|
|
if (password == null) return "Missing password.";
|
||
|
|
|
||
|
|
if (username.length() < USERNAME_MIN) return "Username too short (min " + USERNAME_MIN + ").";
|
||
|
|
if (username.length() > USERNAME_MAX) return "Username too long (max " + USERNAME_MAX + ").";
|
||
|
|
|
||
|
|
// Allow only a safe subset to avoid weird edge cases in UI and future.
|
||
|
|
for (int i = 0; i < username.length(); i++) {
|
||
|
|
char c = username.charAt(i);
|
||
|
|
boolean ok = (c >= 'a' && c <= 'z')
|
||
|
|
|| (c >= 'A' && c <= 'Z')
|
||
|
|
|| (c >= '0' && c <= '9')
|
||
|
|
|| c == '_' || c == '-' || c == '.';
|
||
|
|
if (!ok) return "Username contains invalid characters.";
|
||
|
|
}
|
||
|
|
|
||
|
|
if (password.length() < PASSWORD_MIN) return "Password too short (min " + PASSWORD_MIN + ").";
|
||
|
|
if (password.length() > PASSWORD_MAX) return "Password too long.";
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Registers a new user.
|
||
|
|
*
|
||
|
|
* @param usernameRaw raw username (from form)
|
||
|
|
* @param passwordRaw raw password (from form)
|
||
|
|
* @return result containing either userId or an error message
|
||
|
|
*/
|
||
|
|
public Result register(String usernameRaw, String passwordRaw) {
|
||
|
|
String username = normalizeUsername(usernameRaw);
|
||
|
|
String password = (passwordRaw == null) ? "" : passwordRaw;
|
||
|
|
|
||
|
|
String validationError = validate(username, password);
|
||
|
|
if (validationError != null) {
|
||
|
|
return Result.error(validationError);
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
// Choose: store username as-is OR store sha256(username).
|
||
|
|
// Your schema says: username(sha256 hex or plain) -> keep it plain for now.
|
||
|
|
String usernameStored = username;
|
||
|
|
|
||
|
|
if (userDao.findByUsername(usernameStored).isPresent()) {
|
||
|
|
return Result.error("Username already exists.");
|
||
|
|
}
|
||
|
|
|
||
|
|
String passwordEncoded = hasher.hash(password);
|
||
|
|
int userId = userDao.createUserWithNewUuid(usernameStored, passwordEncoded);
|
||
|
|
|
||
|
|
return Result.ok(userId);
|
||
|
|
} catch (Exception e) {
|
||
|
|
return Result.error("Registration failed: " + e.getMessage());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Registration result.
|
||
|
|
*
|
||
|
|
* @param ok whether succeeded
|
||
|
|
* @param userId created user id, or -1
|
||
|
|
* @param error error message, or null
|
||
|
|
*/
|
||
|
|
public record Result(boolean ok, int userId, String error) {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates a success result.
|
||
|
|
*
|
||
|
|
* @param userId user id
|
||
|
|
* @return result
|
||
|
|
*/
|
||
|
|
public static Result ok(int userId) {
|
||
|
|
return new Result(true, userId, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates an error result.
|
||
|
|
*
|
||
|
|
* @param error error message
|
||
|
|
* @return result
|
||
|
|
*/
|
||
|
|
public static Result error(String error) {
|
||
|
|
return new Result(false, -1, error);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|