getByUserId(UUID userId) {
+ byte[] idBytes = UuidUtil.uuidToBin(userId);
+ return repository.findAll().stream()
+ .filter(i -> i.getUserId().equals(userId))
+ .toList();
+ }
+}
diff --git a/huertos/src/main/java/net/miarma/backend/huertos/util/UsernameGenerator.java b/huertos/src/main/java/net/miarma/backend/huertos/util/UsernameGenerator.java
new file mode 100644
index 0000000..1f7018b
--- /dev/null
+++ b/huertos/src/main/java/net/miarma/backend/huertos/util/UsernameGenerator.java
@@ -0,0 +1,9 @@
+package net.miarma.backend.huertos.util;
+
+import java.util.Locale;
+
+public class UsernameGenerator {
+ public static String generate(String name, Integer number) {
+ return name.split(" ")[0].toLowerCase() + number;
+ }
+}
diff --git a/huertos/src/main/java/net/miarma/backend/huertos/validation/DniValidator.java b/huertos/src/main/java/net/miarma/backend/huertos/validation/DniValidator.java
new file mode 100644
index 0000000..10af1f6
--- /dev/null
+++ b/huertos/src/main/java/net/miarma/backend/huertos/validation/DniValidator.java
@@ -0,0 +1,66 @@
+package net.miarma.backend.huertos.validation;
+
+/**
+ * Validador de DNI/NIE español.
+ *
+ * Este validador comprueba si un DNI o NIE es válido según las reglas establecidas por la legislación española.
+ * Un DNI debe tener 8 dígitos seguidos de una letra, y un NIE debe comenzar con X, Y o Z seguido de 7 dígitos y una letra.
+ *
+ * @author José Manuel Amador Gallardo
+ */
+public class DniValidator {
+
+ /**
+ * Valida un DNI o NIE español.
+ *
+ * @param id El DNI o NIE a validar.
+ * @return true si el DNI/NIE es válido, false en caso contrario.
+ */
+ public static boolean isValid(String id) {
+ if (id == null || id.length() != 9) {
+ return false;
+ }
+
+ id = id.toUpperCase(); // Pa evitar problemas con minúsculas
+ String numberPart;
+ char letterPart = id.charAt(8);
+
+ if (id.startsWith("X") || id.startsWith("Y") || id.startsWith("Z")) {
+ // NIE
+ char prefix = id.charAt(0);
+ String numericPrefix = switch (prefix) {
+ case 'X' -> "0";
+ case 'Y' -> "1";
+ case 'Z' -> "2";
+ default -> null;
+ };
+
+ if (numericPrefix == null) return false;
+
+ numberPart = numericPrefix + id.substring(1, 8);
+ } else {
+ // DNI
+ numberPart = id.substring(0, 8);
+ }
+
+ if (!numberPart.matches("\\d{8}")) {
+ return false;
+ }
+
+ int number = Integer.parseInt(numberPart);
+ char expectedLetter = calculateLetter(number);
+
+ return letterPart == expectedLetter;
+ }
+
+ /**
+ * Calcula la letra correspondiente a un número de DNI.
+ *
+ * @param number El número del DNI (8 dígitos).
+ * @return La letra correspondiente.
+ */
+ private static char calculateLetter(int number) {
+ String letters = "TRWAGMYFPDXBNJZSQVHLCKE";
+ return letters.charAt(number % 23);
+ }
+}
diff --git a/huertos/src/main/java/net/miarma/backend/huertos/validation/RequestValidator.java b/huertos/src/main/java/net/miarma/backend/huertos/validation/RequestValidator.java
new file mode 100644
index 0000000..66b4e1d
--- /dev/null
+++ b/huertos/src/main/java/net/miarma/backend/huertos/validation/RequestValidator.java
@@ -0,0 +1,90 @@
+package net.miarma.backend.huertos.validation;
+
+import net.miarma.backend.huertos.model.RequestMetadata;
+import net.miarma.backlib.exception.BadRequestException;
+import net.miarma.backlib.exception.ValidationException;
+
+import java.util.regex.Pattern;
+
+public class RequestValidator {
+
+ private static final Pattern DNI_PATTERN = Pattern.compile("\\d{8}[A-Za-z]");
+ private static final Pattern EMAIL_PATTERN = Pattern.compile("^[\\w.%+-]+@[\\w.-]+\\.[a-zA-Z]{2,6}$");
+ private static final Pattern PHONE_PATTERN = Pattern.compile("^\\+?\\d{9,15}$");
+
+ public static void validate(RequestMetadata metadata, Byte requestType) {
+ if (metadata.getRequestId() == null) {
+ throw new BadRequestException("Estos metadatos deben pertenecer a una solicitud (falta ID)");
+ }
+
+ if (isBlank(metadata.getDisplayName())) {
+ throw new BadRequestException("El nombre a mostrar es obligatorio");
+ } else if (metadata.getDisplayName().length() < 3) {
+ throw new ValidationException("displayName", "El nombre a mostrar debe tener al menos 3 caracteres");
+ }
+
+ if (isBlank(metadata.getDni())) {
+ throw new BadRequestException("El DNI es obligatorio");
+ } else if (!DNI_PATTERN.matcher(metadata.getDni()).matches()) {
+ throw new ValidationException("dni", "Formato de DNI inválido (ej: 12345678A)");
+ } else if (!DniValidator.isValid(metadata.getDni())) {
+ throw new ValidationException("dni", "Este DNI no es un DNI real");
+ }
+
+ if (isBlank(metadata.getEmail())) {
+ throw new BadRequestException("El email es obligatorio");
+ } else if (!EMAIL_PATTERN.matcher(metadata.getEmail()).matches()) {
+ throw new ValidationException("email", "Email inválido");
+ }
+
+ if (isBlank(metadata.getUsername())) {
+ throw new BadRequestException("El usuario es obligatorio");
+ } else if (metadata.getUsername().length() < 3) {
+ throw new ValidationException("username", "El usuario debe tener al menos 3 caracteres");
+ }
+
+ if (metadata.getType() == null) {
+ throw new BadRequestException("El tipo de usuario es obligatorio");
+ }
+
+ if (requestType == 2) {
+ if (metadata.getPlotNumber() == null) {
+ throw new BadRequestException("El colaborador debe tener huerto");
+ }
+ }
+
+ if (requestType == 0 || requestType == 1) {
+ if (metadata.getMemberNumber() == null) {
+ throw new BadRequestException("El número de socio es obligatorio");
+ }
+ }
+
+ if (requestType == 0) {
+ if (metadata.getAddress() == null || metadata.getZipCode() == null || metadata.getCity() == null) {
+ throw new BadRequestException("La dirección, código postal y ciudad son obligatorios");
+ }
+ }
+
+ if (requestType == 0) {
+ if (isBlank(metadata.getAddress())) {
+ throw new ValidationException("address", "La dirección es obligatoria");
+ }
+ if (isBlank(metadata.getZipCode())) {
+ throw new ValidationException("zipCode", "El código postal es obligatorio");
+ } else if(metadata.getZipCode().length() < 5) {
+ throw new ValidationException("zipCode", "El código postal debe tener 5 dígitos");
+ }
+ if (isBlank(metadata.getCity())) {
+ throw new ValidationException("city", "La ciudad es obligatoria");
+ }
+ }
+
+ if (metadata.getPhone() != null && !PHONE_PATTERN.matcher(metadata.getPhone()).matches()) {
+ throw new ValidationException("phone", "Teléfono inválido (debe tener 9 dígitos)");
+ }
+ }
+
+ private static boolean isBlank(String s) {
+ return s == null || s.trim().isEmpty();
+ }
+}
diff --git a/huertos/src/main/resources/application-dev.yml b/huertos/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..c0e66ab
--- /dev/null
+++ b/huertos/src/main/resources/application-dev.yml
@@ -0,0 +1,28 @@
+server:
+ port: 8081
+ servlet:
+ context-path: /v2/huertos
+
+spring:
+ datasource:
+ url: jdbc:mariadb://localhost:3306/miarma_v2
+ username: admin
+ password: ${DB_PASS}
+ driver-class-name: org.mariadb.jdbc.Driver
+
+logging:
+ level:
+ org.hibernate.SQL: DEBUG
+ org.hibernate.orm.jdbc.bind: TRACE
+
+core:
+ url: http://localhost:8080/v2/core
+
+huertos:
+ user: SYSTEM
+ password: ${HUERTOS_PASS}
+
+mail:
+ smtp:
+ server: smtp.dondominio.com
+ port: 587
\ No newline at end of file
diff --git a/huertos/src/main/resources/application-prod.yml b/huertos/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..56dca05
--- /dev/null
+++ b/huertos/src/main/resources/application-prod.yml
@@ -0,0 +1,27 @@
+server:
+ port: 8081
+ servlet:
+ context-path: /v2/huertos
+
+spring:
+ datasource:
+ url: jdbc:mariadb://mariadb:3306/miarma_v2
+ username: ${DB_USER}
+ password: ${DB_PASS}
+ driver-class-name: org.mariadb.jdbc.Driver
+
+logging:
+ level:
+ org.hibernate.SQL: WARN
+
+core:
+ url: http://core:8080/v2/core
+
+huertos:
+ user: SYSTEM
+ password: ${HUERTOS_PASS}
+
+mail:
+ smtp:
+ server: smtp.dondominio.com
+ port: 587
\ No newline at end of file
diff --git a/huertos/src/main/resources/application.yml b/huertos/src/main/resources/application.yml
new file mode 100644
index 0000000..87de0a8
--- /dev/null
+++ b/huertos/src/main/resources/application.yml
@@ -0,0 +1,25 @@
+spring:
+ application:
+ name: huertos-service
+
+ jpa:
+ open-in-view: false
+ hibernate:
+ ddl-auto: validate
+ properties:
+ hibernate:
+ jdbc:
+ time_zone: UTC
+
+ jackson:
+ default-property-inclusion: non_null
+ time-zone: Europe/Madrid
+
+jwt:
+ expiration-ms: 3600000
+
+management:
+ endpoints:
+ web:
+ exposure:
+ include: health,info
diff --git a/minecraft/.classpath b/minecraft/.classpath
deleted file mode 100644
index f7e4a1d..0000000
--- a/minecraft/.classpath
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/minecraft/.project b/minecraft/.project
deleted file mode 100644
index b356ec0..0000000
--- a/minecraft/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- minecraft
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
- org.eclipse.m2e.core.maven2Nature
-
-
diff --git a/minecraft/.settings/org.eclipse.jdt.core.prefs b/minecraft/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 2f5cc74..0000000
--- a/minecraft/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,8 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
-org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.8
diff --git a/minecraft/.settings/org.eclipse.m2e.core.prefs b/minecraft/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/minecraft/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/minecraft/minecraft.iml b/minecraft/minecraft.iml
new file mode 100644
index 0000000..68a9707
--- /dev/null
+++ b/minecraft/minecraft.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/minecraft/pom.xml b/minecraft/pom.xml
index a72edf0..2531777 100644
--- a/minecraft/pom.xml
+++ b/minecraft/pom.xml
@@ -9,6 +9,18 @@
minecraft
+
+ 25
+ 25
+
+
+
+
+ gitea
+ https://git.miarma.net/api/packages/Gallardo7761/maven
+
+
+
diff --git a/mpaste/.classpath b/mpaste/.classpath
deleted file mode 100644
index f7e4a1d..0000000
--- a/mpaste/.classpath
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/mpaste/.project b/mpaste/.project
deleted file mode 100644
index 499668e..0000000
--- a/mpaste/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- mpaste
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
- org.eclipse.m2e.core.maven2Nature
-
-
diff --git a/mpaste/.settings/org.eclipse.jdt.core.prefs b/mpaste/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 2f5cc74..0000000
--- a/mpaste/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,8 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
-org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.8
diff --git a/mpaste/.settings/org.eclipse.m2e.core.prefs b/mpaste/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/mpaste/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/mpaste/mpaste.iml b/mpaste/mpaste.iml
new file mode 100644
index 0000000..68a9707
--- /dev/null
+++ b/mpaste/mpaste.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mpaste/pom.xml b/mpaste/pom.xml
index 4a8b476..fbff362 100644
--- a/mpaste/pom.xml
+++ b/mpaste/pom.xml
@@ -9,6 +9,18 @@
mpaste
+
+ 25
+ 25
+
+
+
+
+ gitea
+ https://git.miarma.net/api/packages/Gallardo7761/maven
+
+
+
diff --git a/pom.xml b/pom.xml
index 4e76ab2..5acf6c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,12 +15,14 @@
minecraft
cine
mpaste
- websocket
+ backlib
25
4.0.1
+ 25
+ 25
diff --git a/target/classes/META-INF/MANIFEST.MF b/target/classes/META-INF/MANIFEST.MF
deleted file mode 100644
index a5622f8..0000000
--- a/target/classes/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,4 +0,0 @@
-Manifest-Version: 1.0
-Build-Jdk-Spec: 21
-Created-By: Maven Integration for Eclipse
-
diff --git a/target/classes/META-INF/maven/net.miarma/backend/pom.properties b/target/classes/META-INF/maven/net.miarma/backend/pom.properties
deleted file mode 100644
index e27ed27..0000000
--- a/target/classes/META-INF/maven/net.miarma/backend/pom.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-#Generated by Maven Integration for Eclipse
-#Fri Jan 16 02:26:12 CET 2026
-artifactId=backend
-groupId=net.miarma
-m2e.projectLocation=/home/jomaa/git/miarma-backend
-m2e.projectName=backend
-version=1.0.0
diff --git a/target/classes/META-INF/maven/net.miarma/backend/pom.xml b/target/classes/META-INF/maven/net.miarma/backend/pom.xml
deleted file mode 100644
index 3b1fee6..0000000
--- a/target/classes/META-INF/maven/net.miarma/backend/pom.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
- 4.0.0
- net.miarma
- backend
- 1.0.0
-
\ No newline at end of file