MotorSignal-App/lib/services/social/handle_validator.dart

97 lines
2.4 KiB
Dart

/// Validation and normalization logic for MotorSignal rider handles.
class HandleValidationResult {
final bool isValid;
final String? error;
final String? normalizedHandle;
const HandleValidationResult._({
required this.isValid,
this.error,
this.normalizedHandle,
});
factory HandleValidationResult.valid(String normalized) =>
HandleValidationResult._(isValid: true, normalizedHandle: normalized);
factory HandleValidationResult.invalid(String error) =>
HandleValidationResult._(isValid: false, error: error);
}
class HandleValidator {
static const int minLength = 3;
static const int maxLength = 20;
static final RegExp _formatRegex = RegExp(r'^[a-z][a-z0-9_]{2,19}$');
static const Set<String> reservedHandles = {
'admin',
'administrator',
'motorsignal',
'motorcloud',
'support',
'system',
'mod',
'moderator',
'help',
'official',
'root',
'api',
'bot',
'test',
'dev',
'developer',
'staff',
'security',
'null',
'undefined',
'guest',
'anonymous',
'safety',
'emergency',
'police',
'marshal',
'leader',
'host',
};
/// Normalizes a handle: trims whitespace and lowercases.
static String normalize(String handle) => handle.trim().toLowerCase();
/// Validates a handle format and checks against reserved names.
static HandleValidationResult validate(String rawHandle) {
final normalized = normalize(rawHandle);
if (normalized.isEmpty) {
return HandleValidationResult.invalid('Handle cannot be empty');
}
if (normalized.length < minLength) {
return HandleValidationResult.invalid(
'Handle must be at least $minLength characters',
);
}
if (normalized.length > maxLength) {
return HandleValidationResult.invalid(
'Handle cannot exceed $maxLength characters',
);
}
if (!RegExp(r'^[a-z]').hasMatch(normalized)) {
return HandleValidationResult.invalid('Handle must start with a letter');
}
if (!_formatRegex.hasMatch(normalized)) {
return HandleValidationResult.invalid(
'Handle can only contain lowercase letters, numbers, and underscores',
);
}
if (reservedHandles.contains(normalized)) {
return HandleValidationResult.invalid('This handle is reserved');
}
return HandleValidationResult.valid(normalized);
}
}