feat(profile): role claim in the profile ticket
Build, Test & Push Auth Service / quality-check (push) Successful in 54s
Build, Test & Push Auth Service / docker (push) Successful in 1m29s

The public profile ticket now carries the user's role so Core can check
ownership of shop items. PLATFORM_ADMIN gets every catalog item for free.
The role comes from the users table; a ticket without the claim means USER.
This commit is contained in:
lobo committed 2026-10-01 13:14:27 +02:00
1 parent 6b6ac44551
commit e72222a37f
9 files changed
+28 -12

No files matched your search

@@ -113,7 +113,7 @@ class JwtServiceTest extends AbstractUnitTest {
@Test
void generateProfileTicket_NamesTheUserAndExpiresSoon() {
var ticket = jwtService.generateProfileTicket(42L, List.of(), List.of());
var ticket = jwtService.generateProfileTicket(42L, Role.USER, List.of(), List.of());
var claims = Jwts.parser().verifyWith(publicKey).build().parseSignedClaims(ticket).getPayload();
assertEquals(List.of("tbp-public-profile"), List.copyOf(claims.getAudience()));
@@ -123,9 +123,17 @@ class JwtServiceTest extends AbstractUnitTest {
assertTrue(secondsLeft > 0 && secondsLeft <= 600, "expires in " + secondsLeft + "s");
}
@Test
void generateProfileTicket_CarriesTheRole() {
String ticket = jwtService.generateProfileTicket(42L, Role.PLATFORM_ADMIN, List.of(), List.of());
Claims claims = Jwts.parser().verifyWith(publicKey).build().parseSignedClaims(ticket).getPayload();
assertEquals("PLATFORM_ADMIN", claims.get("role", String.class));
}
@Test
void generateProfileTicket_CarriesTheSharedStatGroups() {
String ticket = jwtService.generateProfileTicket(42L, List.of("PILE", "TREND"), List.of("PLAYING", "STATS"));
String ticket = jwtService.generateProfileTicket(42L, Role.USER, List.of("PILE", "TREND"), List.of("PLAYING", "STATS"));
Claims claims = Jwts.parser().verifyWith(publicKey).build().parseSignedClaims(ticket).getPayload();
assertEquals(List.of("PILE", "TREND"), claims.get("profileStats", List.class));
@@ -134,7 +142,7 @@ class JwtServiceTest extends AbstractUnitTest {
@Test
void parseLoginToken_ProfileTicketIsNoLoginToken() {
assertEquals(Optional.empty(), jwtService.parseLoginToken(jwtService.generateProfileTicket(42L, List.of(), List.of())));
assertEquals(Optional.empty(), jwtService.parseLoginToken(jwtService.generateProfileTicket(42L, Role.USER, List.of(), List.of())));
}
@Test
@@ -218,7 +226,7 @@ class JwtServiceTest extends AbstractUnitTest {
assertEquals(ContractFixture.token("login"),
payload(jwtService.generateToken("42", 76561198000000001L, Role.USER)));
assertEquals(ContractFixture.token("publicProfile"),
payload(jwtService.generateProfileTicket(42L, List.of("OVERVIEW"), List.of("SUMMARY"))));
payload(jwtService.generateProfileTicket(42L, Role.USER, List.of("OVERVIEW"), List.of("SUMMARY"))));
assertEquals(ContractFixture.token("service"), payload(jwtService.generateServiceToken()));
}
@@ -68,6 +68,7 @@ class PublicProfileControllerTest extends AbstractIntegrationTest {
var claims = Jwts.parser().verifyWith(key).build().parseSignedClaims(ticket).getPayload();
assertEquals(String.valueOf(publicUserId), claims.get("profileUserId", String.class));
assertEquals(List.of(), claims.get("profileStats", List.class));
assertEquals("USER", claims.get("role", String.class));
}
@Test
@@ -120,6 +121,7 @@ class PublicProfileControllerTest extends AbstractIntegrationTest {
Claims claims = Jwts.parser().verifyWith(key).build().parseSignedClaims(ticket).getPayload();
assertEquals(List.of("PLAYING"), claims.get("sections", List.class));
assertEquals(List.of(), claims.get("profileStats", List.class));
assertEquals("USER", claims.get("role", String.class));
}
@Test
@@ -13,6 +13,7 @@
"aud": ["tbp-public-profile"],
"sub": "public-profile",
"profileUserId": "42",
"role": "USER",
"profileStats": ["OVERVIEW"],
"sections": ["SUMMARY"]
},