Public Access
feat(settings): store a favorite platform
This commit is contained in:
1 parent
315e22c220
commit
ea4ae089ff
14 files changed
+103
-3
No files matched your search
@@ -3,6 +3,7 @@ package auth_service.modules.user.api;
|
||||
import auth_service.shared.security.UserPrincipal;
|
||||
import auth_service.modules.user.api.dto.request.AppearanceRequest;
|
||||
import auth_service.modules.user.api.dto.request.DashboardTilesRequest;
|
||||
import auth_service.modules.user.api.dto.request.FavoritePlatformRequest;
|
||||
import auth_service.modules.user.api.dto.request.ProfileTilesRequest;
|
||||
import auth_service.modules.user.api.dto.request.ProfileStyleRequest;
|
||||
import auth_service.modules.user.api.dto.request.UserSettingsRequest;
|
||||
@@ -62,6 +63,13 @@ public class UserController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PutMapping(value = "/settings/favorite-platform", version = "1.0")
|
||||
public ResponseEntity<Void> updateFavoritePlatform(@AuthenticationPrincipal UserPrincipal principal,
|
||||
@Valid @RequestBody FavoritePlatformRequest request) {
|
||||
this.userService.updateFavoritePlatform(principal.getIdAsLong(), request.platform());
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PutMapping(value = "/settings/profile-style", version = "1.0")
|
||||
public ResponseEntity<Void> updateProfileStyle(@AuthenticationPrincipal UserPrincipal principal,
|
||||
@Valid @RequestBody ProfileStyleRequest request) {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package auth_service.modules.user.api.dto.request;
|
||||
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* @param platform free text like Core's game platform: the frontend offers the list; null clears it
|
||||
*/
|
||||
public record FavoritePlatformRequest(@Size(max = 32) @Pattern(regexp = ".*\\S.*") String platform) {
|
||||
}
|
||||
@@ -7,5 +7,6 @@ import java.util.List;
|
||||
@Builder
|
||||
public record SettingsResponse(long id, boolean useDarkTheme, String language, boolean publicProfile,
|
||||
AppearanceResponse appearance, ProfileStyleResponse profileStyle,
|
||||
List<TileResponse> dashboardTiles, List<TileResponse> profileTiles) {
|
||||
List<TileResponse> dashboardTiles, List<TileResponse> profileTiles,
|
||||
String favoritePlatform) {
|
||||
}
|
||||
@@ -47,6 +47,7 @@ public abstract class ApiMapper {
|
||||
.dashboardTiles(user.getSettings().getDashboardTiles() == null ? null
|
||||
: toApi(user.getSettings().getDashboardTiles()))
|
||||
.profileTiles(toApi(user.getSettings().getProfileTiles()))
|
||||
.favoritePlatform(user.getSettings().getFavoritePlatform())
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public class UserSettings {
|
||||
private List<Tile> dashboardTiles;
|
||||
@Builder.Default
|
||||
private List<Tile> profileTiles = DEFAULT_PROFILE_TILES;
|
||||
private String favoritePlatform;
|
||||
|
||||
/** Also the column default of user_settings.profile_tiles. */
|
||||
public static final List<Tile> DEFAULT_PROFILE_TILES = List.of(new Tile("SUMMARY", "M"), new Tile("STATUS", "M"),
|
||||
|
||||
@@ -38,6 +38,8 @@ public interface UserRepository {
|
||||
|
||||
void updateProfileTiles(long userId, List<Tile> tiles);
|
||||
|
||||
void updateFavoritePlatform(long userId, String platform);
|
||||
|
||||
void updateProfileStyle(long userId, ProfileStyle style);
|
||||
|
||||
Optional<SteamIdHolder> findSteamIdHolder(long steamId);
|
||||
|
||||
@@ -110,6 +110,12 @@ public class UserRepositoryImpl implements UserRepository {
|
||||
settingsOf(userId).setProfileTiles(Tile.storedAll(tiles));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateFavoritePlatform(long userId, String platform) {
|
||||
settingsOf(userId).setFavoritePlatform(platform);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateProfileStyle(long userId, ProfileStyle style) {
|
||||
|
||||
@@ -71,6 +71,9 @@ public class UserSettingsEntity {
|
||||
@Column(name = "dashboard_tiles")
|
||||
private List<String> dashboardTiles;
|
||||
|
||||
@Column(name = "favorite_platform")
|
||||
private String favoritePlatform;
|
||||
|
||||
@JdbcTypeCode(SqlTypes.ARRAY)
|
||||
@Column(name = "profile_tiles", nullable = false)
|
||||
private List<String> profileTiles = Tile.storedAll(UserSettings.DEFAULT_PROFILE_TILES);
|
||||
|
||||
@@ -37,6 +37,7 @@ public abstract class EntityMapper {
|
||||
.dashboardTiles(entity.getSettings().getDashboardTiles() == null ? null
|
||||
: entity.getSettings().getDashboardTiles().stream().map(Tile::parse).toList())
|
||||
.profileTiles(entity.getSettings().getProfileTiles().stream().map(Tile::parse).toList())
|
||||
.favoritePlatform(entity.getSettings().getFavoritePlatform())
|
||||
.build();
|
||||
} else {
|
||||
// Fallback default settings for users without an entry in the database
|
||||
|
||||
@@ -112,6 +112,13 @@ public class UserService {
|
||||
userRepository.updateProfileTiles(userId, Tile.distinct(tiles));
|
||||
}
|
||||
|
||||
@RequiresRole(Role.USER)
|
||||
@Transactional
|
||||
@CacheEvict(value = "usersByEmail", allEntries = true)
|
||||
public void updateFavoritePlatform(long userId, String platform) {
|
||||
userRepository.updateFavoritePlatform(userId, platform == null ? null : platform.strip());
|
||||
}
|
||||
|
||||
@RequiresRole(Role.USER)
|
||||
@Transactional
|
||||
@CacheEvict(value = "usersByEmail", allEntries = true)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
-- The platform preselected when a game is added by hand or imported (Core item 23), an IGDB abbreviation such as
|
||||
-- 'PS5'. NULL: none.
|
||||
ALTER TABLE user_settings ADD COLUMN favorite_platform VARCHAR(32);
|
||||
@@ -36,6 +36,7 @@ import java.util.List;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -355,7 +356,7 @@ class UserControllerTest extends AbstractWebMvcTest {
|
||||
String email = "test@example.com";
|
||||
UserSettings settings = UserSettings.builder().language("en").theme("dark")
|
||||
.dashboardTiles(List.of(new Tile("STATS_TREND", "L")))
|
||||
.profileTiles(List.of(new Tile("PLAYING", "S"))).build();
|
||||
.profileTiles(List.of(new Tile("PLAYING", "S"))).favoritePlatform("PS5").build();
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken(new UserPrincipal("1", email, null), null, Collections.emptyList())
|
||||
);
|
||||
@@ -366,7 +367,8 @@ class UserControllerTest extends AbstractWebMvcTest {
|
||||
.andExpect(jsonPath("$.settings.dashboardTiles[0].id").value("STATS_TREND"))
|
||||
.andExpect(jsonPath("$.settings.dashboardTiles[0].size").value("L"))
|
||||
.andExpect(jsonPath("$.settings.profileTiles[0].id").value("PLAYING"))
|
||||
.andExpect(jsonPath("$.settings.profileTiles[0].size").value("S"));
|
||||
.andExpect(jsonPath("$.settings.profileTiles[0].size").value("S"))
|
||||
.andExpect(jsonPath("$.settings.favoritePlatform").value("PS5"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -410,6 +412,38 @@ class UserControllerTest extends AbstractWebMvcTest {
|
||||
verify(userService).updateDashboardTiles(1L, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateFavoritePlatform_StoresOrClearsIt() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
|
||||
new UserPrincipal("1", "test@example.com", null), null, Collections.emptyList()));
|
||||
|
||||
mockMvc.perform(put("/api/users/settings/favorite-platform")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"platform\":\"PS5\"}"))
|
||||
.andExpect(status().isNoContent());
|
||||
mockMvc.perform(put("/api/users/settings/favorite-platform")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"platform\":null}"))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
verify(userService).updateFavoritePlatform(1L, "PS5");
|
||||
verify(userService).updateFavoritePlatform(1L, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateFavoritePlatform_BlankOrTooLong_Is400() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
|
||||
new UserPrincipal("1", "test@example.com", null), null, Collections.emptyList()));
|
||||
|
||||
for (String platform : List.of(" ", "x".repeat(33))) {
|
||||
mockMvc.perform(put("/api/users/settings/favorite-platform")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"platform\":\"" + platform + "\"}"))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
verify(userService, never()).updateFavoritePlatform(anyLong(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateProfileTiles_StoresTheTiles() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
|
||||
|
||||
@@ -330,6 +330,28 @@ class UserRepositoryTest extends AbstractPersistenceTest {
|
||||
assertEquals(profile, saved.getProfileTiles());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateFavoritePlatform_StoresAndClears() {
|
||||
UserEntity userEntity = entityManager.persist(UserEntity.builder()
|
||||
.email("favorite@example.com")
|
||||
.password("password")
|
||||
.enabled(true)
|
||||
.registrationDate(LocalDateTime.now())
|
||||
.build());
|
||||
assertNull(userRepository.findByEmail("favorite@example.com").orElseThrow().getSettings().getFavoritePlatform());
|
||||
|
||||
userRepository.updateFavoritePlatform(userEntity.getId(), "Switch");
|
||||
entityManager.flush();
|
||||
entityManager.clear();
|
||||
assertEquals("Switch", userRepository.findByEmail("favorite@example.com").orElseThrow().getSettings()
|
||||
.getFavoritePlatform());
|
||||
|
||||
userRepository.updateFavoritePlatform(userEntity.getId(), null);
|
||||
entityManager.flush();
|
||||
entityManager.clear();
|
||||
assertNull(userRepository.findByEmail("favorite@example.com").orElseThrow().getSettings().getFavoritePlatform());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateDashboardTiles_NullResetsToTheDefault() {
|
||||
UserEntity userEntity = entityManager.persist(UserEntity.builder()
|
||||
|
||||
Reference in new issue
Block a user