6 Commits

Author SHA1 Message Date
Jose
18c2f0f00b hotfix: merge <<< HEAD ---- >>> SHA1 messages stood on the code somehow 2025-11-14 19:55:18 +01:00
Jose
3a194f2616 Merge pull request 'release 1.2.1' (#3) from dev into main
Reviewed-on: #3
2025-11-14 19:31:00 +01:00
Jose
2611ab62d5 Merge remote-tracking branch 'refs/remotes/origin/dev' into dev 2025-11-14 19:26:44 +01:00
Jose
748feabf24 add: generic JWT token extraction
refactor: change project and POMs' names accordingly
2025-11-14 19:21:31 +01:00
Jose
14ea92dab9 Merge pull request 'fix: huertos admin permissions; improve: abstract auth guard' (#2) from hotfix/huertos-admin-permissions into main
Reviewed-on: #2
2025-11-14 19:11:55 +01:00
Jose
92847e87aa fix: huertos admin permissions; improve: abstract auth guard 2025-11-14 19:10:20 +01:00
13 changed files with 90 additions and 66 deletions

View File

@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>backlib</artifactId> <artifactId>backlib</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<properties> <properties>
<maven.compiler.source>23</maven.compiler.source> <maven.compiler.source>23</maven.compiler.source>

View File

@@ -14,13 +14,13 @@ import net.miarma.api.backlib.util.JsonUtil;
* Maneja extracción de JWT y verificación básica. * Maneja extracción de JWT y verificación básica.
* Los microservicios solo implementan getUserEntity y hasPermission. * Los microservicios solo implementan getUserEntity y hasPermission.
*/ */
@SuppressWarnings("unchecked") // arreglar el warning de heap pollution de los arrays de genéricos @SuppressWarnings("unchecked")
public abstract class AbstractAuthGuard<U, R extends Enum<R> & IUserRole> { public abstract class AbstractAuthGuard<U, R extends Enum<R> & IUserRole> {
protected abstract R parseRole(String roleStr); protected abstract R parseRole(String roleStr);
protected abstract void getUserEntity(int userId, RoutingContext ctx, Consumer<U> callback); protected abstract void getUserEntity(int userId, RoutingContext ctx, Consumer<U> callback);
protected abstract boolean hasPermission(U user, R role, R... allowedRoles); protected abstract boolean hasPermission(U user, R role);
public Handler<RoutingContext> check(R... allowedRoles) { public Handler<RoutingContext> check(R... allowedRoles) {
return ctx -> { return ctx -> {
String token = extractToken(ctx); String token = extractToken(ctx);
@@ -30,16 +30,26 @@ public abstract class AbstractAuthGuard<U, R extends Enum<R> & IUserRole> {
} }
int userId = JWTManager.getInstance().extractUserId(token); int userId = JWTManager.getInstance().extractUserId(token);
String roleStr = JWTManager.getInstance().extractRole(token);
R role;
try {
role = parseRole(roleStr);
} catch (Exception e) {
JsonUtil.sendJson(ctx, ApiStatus.UNAUTHORIZED, "Invalid role");
return;
}
ctx.put("userId", userId);
ctx.put("role", role);
getUserEntity(userId, ctx, entity -> { getUserEntity(userId, ctx, entity -> {
if (entity == null) { if (entity == null) {
JsonUtil.sendJson(ctx, ApiStatus.UNAUTHORIZED, "User not found"); JsonUtil.sendJson(ctx, ApiStatus.UNAUTHORIZED, "User not found");
return; return;
} }
R userRole = extractRoleFromEntity(entity); if (allowedRoles.length == 0 || isRoleAllowed(role, allowedRoles)) {
if (allowedRoles.length == 0 || hasPermission(entity, userRole, allowedRoles)) {
ctx.put("userEntity", entity); ctx.put("userEntity", entity);
ctx.next(); ctx.next();
} else { } else {
@@ -49,15 +59,11 @@ public abstract class AbstractAuthGuard<U, R extends Enum<R> & IUserRole> {
}; };
} }
protected R extractRoleFromEntity(U user) { protected boolean isRoleAllowed(R role, R... allowedRoles) {
try { for (R allowed : allowedRoles) if (role == allowed) return true; return false;
return (R) user.getClass().getMethod("getRole").invoke(user);
} catch (Exception e) {
return null;
}
} }
private String extractToken(RoutingContext ctx) { protected String extractToken(RoutingContext ctx) {
String authHeader = ctx.request().getHeader("Authorization"); String authHeader = ctx.request().getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) { if (authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.substring(7); return authHeader.substring(7);

View File

@@ -5,8 +5,8 @@
<parent> <parent>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>miarma-backend</artifactId> <artifactId>miarma-ecosystem</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
</parent> </parent>
<artifactId>bootstrap</artifactId> <artifactId>bootstrap</artifactId>

View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>core</artifactId> <artifactId>core</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<properties> <properties>
<maven.compiler.source>23</maven.compiler.source> <maven.compiler.source>23</maven.compiler.source>
@@ -20,9 +20,8 @@
<dependency> <dependency>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>backlib</artifactId> <artifactId>backlib</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<scope>provided</scope> </dependency>
</dependency>
</dependencies> </dependencies>
</project>
</project>

View File

@@ -29,10 +29,8 @@ public class CoreAuthGuard extends AbstractAuthGuard<UserEntity, CoreUserRole> {
} }
@Override @Override
protected boolean hasPermission(UserEntity member, CoreUserRole userRole, CoreUserRole... allowedRoles) { protected boolean hasPermission(UserEntity user, CoreUserRole userRole) {
if (member == null) return false; return user.getGlobal_role() == CoreUserRole.ADMIN;
if (member.getGlobal_role() == CoreUserRole.ADMIN) return true;
return false;
} }
} }

View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>huertos</artifactId> <artifactId>huertos</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<properties> <properties>
<maven.compiler.source>23</maven.compiler.source> <maven.compiler.source>23</maven.compiler.source>
@@ -20,9 +20,8 @@
<dependency> <dependency>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>backlib</artifactId> <artifactId>backlib</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<scope>provided</scope> </dependency>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -2,14 +2,19 @@ package net.miarma.api.microservices.huertos.routing.middlewares;
import java.util.function.Consumer; import java.util.function.Consumer;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.RoutingContext;
import net.miarma.api.backlib.Constants.HuertosUserRole; import net.miarma.api.backlib.Constants.HuertosUserRole;
import net.miarma.api.backlib.http.ApiStatus;
import net.miarma.api.backlib.middlewares.AbstractAuthGuard; import net.miarma.api.backlib.middlewares.AbstractAuthGuard;
import net.miarma.api.backlib.security.JWTManager;
import net.miarma.api.backlib.util.JsonUtil;
import net.miarma.api.microservices.huertos.entities.MemberEntity; import net.miarma.api.microservices.huertos.entities.MemberEntity;
import net.miarma.api.microservices.huertos.services.MemberService; import net.miarma.api.microservices.huertos.services.MemberService;
public class HuertosAuthGuard extends AbstractAuthGuard<MemberEntity, HuertosUserRole> { public class HuertosAuthGuard extends AbstractAuthGuard<MemberEntity, HuertosUserRole> {
private final MemberService memberService;
private final MemberService memberService;
public HuertosAuthGuard(MemberService memberService) { public HuertosAuthGuard(MemberService memberService) {
this.memberService = memberService; this.memberService = memberService;
@@ -22,20 +27,50 @@ public class HuertosAuthGuard extends AbstractAuthGuard<MemberEntity, HuertosUse
@Override @Override
protected void getUserEntity(int userId, RoutingContext ctx, Consumer<MemberEntity> callback) { protected void getUserEntity(int userId, RoutingContext ctx, Consumer<MemberEntity> callback) {
memberService.getById(userId).onComplete(ar -> { memberService.getById(userId).onComplete(ar -> {
if (ar.succeeded()) callback.accept(ar.result()); if (ar.succeeded()) callback.accept(ar.result());
else callback.accept(null); else callback.accept(null);
}); });
} }
@Override @Override
protected boolean hasPermission(MemberEntity member, HuertosUserRole userRole, HuertosUserRole... allowedRoles) { protected boolean hasPermission(MemberEntity member, HuertosUserRole userRole) {
if (member == null) return false; return member.getRole() == HuertosUserRole.ADMIN;
if (member.getRole() == HuertosUserRole.ADMIN || member.getRole() == HuertosUserRole.DEV) return true; }
for (HuertosUserRole role : allowedRoles) {
if (member.getRole() == role) return true; @Override
} public Handler<RoutingContext> check(HuertosUserRole... allowedRoles) {
return false; return ctx -> {
String token = extractToken(ctx);
if (token == null || !JWTManager.getInstance().isValid(token)) {
JsonUtil.sendJson(ctx, ApiStatus.UNAUTHORIZED, "Invalid or missing token");
return;
}
int userId = JWTManager.getInstance().extractUserId(token);
getUserEntity(userId, ctx, member -> {
if (member == null) {
JsonUtil.sendJson(ctx, ApiStatus.UNAUTHORIZED, "User not found");
return;
}
HuertosUserRole role = HuertosUserRole.USER;
if (member.getRole() != null) {
role = member.getRole();
}
ctx.put("userId", userId);
ctx.put("role", role);
ctx.put("userEntity", member);
if (allowedRoles.length == 0 || isRoleAllowed(role, allowedRoles)) {
ctx.next();
} else {
JsonUtil.sendJson(ctx, ApiStatus.FORBIDDEN, "Forbidden");
}
});
};
} }
} }

View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>huertosdecine</artifactId> <artifactId>huertosdecine</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<properties> <properties>
<maven.compiler.source>23</maven.compiler.source> <maven.compiler.source>23</maven.compiler.source>
@@ -20,8 +20,7 @@
<dependency> <dependency>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>backlib</artifactId> <artifactId>backlib</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -29,13 +29,8 @@ public class CineAuthGuard extends AbstractAuthGuard<ViewerEntity, CineUserRole>
} }
@Override @Override
protected boolean hasPermission(ViewerEntity member, CineUserRole userRole, CineUserRole... allowedRoles) { protected boolean hasPermission(ViewerEntity user, CineUserRole userRole) {
if (member == null) return false; return user.getRole() == CineUserRole.ADMIN;
if (member.getRole() == CineUserRole.ADMIN) return true;
for (CineUserRole role : allowedRoles) {
if (member.getRole() == role) return true;
}
return false;
} }
} }

View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>miarmacraft</artifactId> <artifactId>miarmacraft</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<properties> <properties>
<maven.compiler.source>23</maven.compiler.source> <maven.compiler.source>23</maven.compiler.source>
@@ -20,8 +20,7 @@
<dependency> <dependency>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>backlib</artifactId> <artifactId>backlib</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -29,13 +29,8 @@ public class MMCAuthGuard extends AbstractAuthGuard<PlayerEntity, MMCUserRole> {
} }
@Override @Override
protected boolean hasPermission(PlayerEntity member, MMCUserRole userRole, MMCUserRole... allowedRoles) { protected boolean hasPermission(PlayerEntity user, MMCUserRole userRole) {
if (member == null) return false; return user.getRole() == MMCUserRole.ADMIN;
if (member.getRole() == MMCUserRole.ADMIN) return true;
for (MMCUserRole role : allowedRoles) {
if (member.getRole() == role) return true;
}
return false;
} }
} }

View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>mpaste</artifactId> <artifactId>mpaste</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<properties> <properties>
<maven.compiler.source>23</maven.compiler.source> <maven.compiler.source>23</maven.compiler.source>
@@ -20,8 +20,7 @@
<dependency> <dependency>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>backlib</artifactId> <artifactId>backlib</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -4,8 +4,8 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.miarma.api</groupId> <groupId>net.miarma.api</groupId>
<artifactId>miarma-backend</artifactId> <artifactId>miarma-ecosystem</artifactId>
<version>1.2.0</version> <version>1.2.1</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<modules> <modules>