Skip to content

Commit 6833438

Browse files
committed
Add UserConfigWrapper
Workaround for spring-projects/spring-data-relational#1343
1 parent 4806b2b commit 6833438

File tree

8 files changed

+72
-43
lines changed

8 files changed

+72
-43
lines changed

src/main/java/ru/loolzaaa/authserver/config/CustomJdbcConfiguration.java

+19-16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.springframework.data.convert.ReadingConverter;
1111
import org.springframework.data.convert.WritingConverter;
1212
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
13+
import ru.loolzaaa.authserver.model.UserConfigWrapper;
1314

1415
import java.sql.SQLException;
1516
import java.util.Arrays;
@@ -24,19 +25,20 @@ public class CustomJdbcConfiguration extends AbstractJdbcConfiguration {
2425
@Override
2526
protected List<?> userConverters() {
2627
return Arrays.asList(
27-
new JsonNodeToJsonConverter(),
28-
new JsonToJsonNodeConverter(),
29-
new StringToJsonNodeConverter(),
30-
new JsonNodeToStringConverter()
28+
new UserConfigWrapperToJsonConverter(),
29+
new JsonToUserConfigWrapperConverter(),
30+
new StringToUserConfigWrapperConverter(),
31+
new UserConfigWrapperToStringConverter()
3132
);
3233
}
3334

3435
@ReadingConverter
35-
class JsonToJsonNodeConverter implements Converter<PGobject, JsonNode> {
36+
class JsonToUserConfigWrapperConverter implements Converter<PGobject, UserConfigWrapper> {
3637
@Override
37-
public JsonNode convert(PGobject json) {
38+
public UserConfigWrapper convert(PGobject json) {
3839
try {
39-
return objectMapper.readTree(json.getValue());
40+
JsonNode jsonNode = objectMapper.readTree(json.getValue());
41+
return new UserConfigWrapper(jsonNode);
4042
} catch (JsonProcessingException | NullPointerException e) {
4143
e.printStackTrace();
4244
}
@@ -45,13 +47,13 @@ public JsonNode convert(PGobject json) {
4547
}
4648

4749
@WritingConverter
48-
class JsonNodeToJsonConverter implements Converter<JsonNode, PGobject> {
50+
class UserConfigWrapperToJsonConverter implements Converter<UserConfigWrapper, PGobject> {
4951
@Override
50-
public PGobject convert(JsonNode jsonNode) {
52+
public PGobject convert(UserConfigWrapper configWrapper) {
5153
PGobject json = new PGobject();
5254
json.setType("jsonb");
5355
try {
54-
json.setValue(objectMapper.writeValueAsString(jsonNode));
56+
json.setValue(objectMapper.writeValueAsString(configWrapper.getConfig()));
5557
} catch (SQLException | JsonProcessingException e) {
5658
e.printStackTrace();
5759
}
@@ -60,11 +62,12 @@ public PGobject convert(JsonNode jsonNode) {
6062
}
6163

6264
@ReadingConverter
63-
class StringToJsonNodeConverter implements Converter<String, JsonNode> {
65+
class StringToUserConfigWrapperConverter implements Converter<String, UserConfigWrapper> {
6466
@Override
65-
public JsonNode convert(String s) {
67+
public UserConfigWrapper convert(String s) {
6668
try {
67-
return objectMapper.readTree(s);
69+
JsonNode jsonNode = objectMapper.readTree(s);
70+
return new UserConfigWrapper(jsonNode);
6871
} catch (JsonProcessingException e) {
6972
e.printStackTrace();
7073
}
@@ -73,11 +76,11 @@ public JsonNode convert(String s) {
7376
}
7477

7578
@WritingConverter
76-
class JsonNodeToStringConverter implements Converter<JsonNode, String> {
79+
class UserConfigWrapperToStringConverter implements Converter<UserConfigWrapper, String> {
7780
@Override
78-
public String convert(JsonNode jsonNode) {
81+
public String convert(UserConfigWrapper configWrapper) {
7982
try {
80-
return objectMapper.writeValueAsString(jsonNode);
83+
return objectMapper.writeValueAsString(configWrapper.getConfig());
8184
} catch (JsonProcessingException e) {
8285
e.printStackTrace();
8386
}

src/main/java/ru/loolzaaa/authserver/model/User.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ru.loolzaaa.authserver.model;
22

3+
import com.fasterxml.jackson.annotation.JsonGetter;
34
import com.fasterxml.jackson.annotation.JsonIgnore;
45
import com.fasterxml.jackson.databind.JsonNode;
56
import lombok.Builder;
@@ -24,22 +25,27 @@ public class User {
2425
private String login;
2526
@JsonIgnore
2627
private String salt;
27-
private JsonNode config;
28+
private UserConfigWrapper config;
2829
private String name;
2930
private boolean enabled;
3031
@JsonIgnore
3132
@Transient
3233
private List<String> hashes = new LinkedList<>();
3334

3435
@Builder
35-
public User(String login, String salt, JsonNode config, String name, boolean enabled) {
36+
public User(String login, String salt, UserConfigWrapper config, String name, boolean enabled) {
3637
this.login = login;
3738
this.salt = salt;
3839
this.config = config;
3940
this.name = name;
4041
this.enabled = enabled;
4142
}
4243

44+
@JsonGetter("config")
45+
public JsonNode getJsonConfig() {
46+
return config.getConfig();
47+
}
48+
4349
@Override
4450
public boolean equals(Object o) {
4551
if (this == o) return true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package ru.loolzaaa.authserver.model;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
import lombok.Setter;
8+
9+
@AllArgsConstructor
10+
@NoArgsConstructor
11+
@Getter
12+
@Setter
13+
public class UserConfigWrapper {
14+
private JsonNode config;
15+
}

src/main/java/ru/loolzaaa/authserver/model/UserPrincipal.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class UserPrincipal implements UserDetails {
3333
public UserPrincipal(User user) {
3434
this.user = user;
3535

36-
JsonNode userConf = user.getConfig();
36+
JsonNode userConf = user.getJsonConfig();
3737
if (userConf != null) {
3838
userConf.fieldNames().forEachRemaining(s -> authorities.add(new SimpleGrantedAuthority(s)));
3939
if (userConf.has(applicationName)) {
@@ -72,7 +72,7 @@ public UserPrincipal(User user) {
7272
public UserPrincipal(User user, String app) {
7373
this(user);
7474

75-
JsonNode userConf = user.getConfig();
75+
JsonNode userConf = user.getJsonConfig();
7676
if (userConf != null) {
7777
if (app != null) {
7878
JsonNode appConfig = userConf.get(app);
@@ -85,7 +85,7 @@ public UserPrincipal(User user, String app) {
8585
appConfig.get(UserAttributes.PRIVILEGES).forEach(privilege -> this.authorities.add(new SimpleGrantedAuthority(privilege.asText())));
8686
}
8787
((ObjectNode) appConfig).remove(List.of(UserAttributes.ROLES, UserAttributes.PRIVILEGES));
88-
user.setConfig(appConfig);
88+
user.setConfig(new UserConfigWrapper(appConfig));
8989
} else throw new IllegalArgumentException(String.format("There is no application [%s] for user [%s]", app, this.user.getLogin()));
9090
}
9191
} else throw new IllegalArgumentException(String.format("There is no config for user [%s]", this.user.getLogin()));

src/main/java/ru/loolzaaa/authserver/repositories/UserRepository.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package ru.loolzaaa.authserver.repositories;
22

3-
import com.fasterxml.jackson.databind.JsonNode;
43
import org.springframework.data.jdbc.repository.query.Modifying;
54
import org.springframework.data.jdbc.repository.query.Query;
65
import org.springframework.data.repository.CrudRepository;
76
import org.springframework.data.repository.query.Param;
87
import org.springframework.stereotype.Repository;
98
import ru.loolzaaa.authserver.model.User;
9+
import ru.loolzaaa.authserver.model.UserConfigWrapper;
1010

1111
import java.util.Optional;
1212

@@ -20,7 +20,7 @@ public interface UserRepository extends CrudRepository<User, Long> {
2020

2121
@Modifying
2222
@Query("UPDATE users SET config = :config::jsonb WHERE login = :login")
23-
void updateConfigByLogin(@Param("config") JsonNode config, @Param("login") String login);
23+
void updateConfigByLogin(@Param("config") UserConfigWrapper config, @Param("login") String login);
2424

2525
@Modifying
2626
@Query("UPDATE users SET salt = :salt WHERE login = :login")

src/main/java/ru/loolzaaa/authserver/schedule/TemporaryUserCleanerTask.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import java.util.concurrent.Callable;
1717

18-
import static java.lang.String.*;
18+
import static java.lang.String.format;
1919

2020
@Log4j2
2121
@RequiredArgsConstructor
@@ -35,7 +35,7 @@ public Integer call() {
3535
for (User u : users) {
3636
UserPrincipal userPrincipal = new UserPrincipal(u);
3737
if (!userPrincipal.isAccountNonExpired()) {
38-
String pass = u.getConfig().get(UserAttributes.TEMPORARY).get("pass").asText();
38+
String pass = u.getJsonConfig().get(UserAttributes.TEMPORARY).get("pass").asText();
3939
try {
4040
RequestStatusDTO result = userControlService.deleteUser(u.getLogin(), pass);
4141
deleteUserCounter++;

src/main/java/ru/loolzaaa/authserver/services/UserControlService.java

+23-16
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import ru.loolzaaa.authserver.exception.RequestErrorException;
2121
import ru.loolzaaa.authserver.model.User;
2222
import ru.loolzaaa.authserver.model.UserAttributes;
23+
import ru.loolzaaa.authserver.model.UserConfigWrapper;
2324
import ru.loolzaaa.authserver.model.UserPrincipal;
2425
import ru.loolzaaa.authserver.repositories.UserRepository;
2526

@@ -97,11 +98,11 @@ public RequestStatusDTO createUser(String app, CreateUserRequestDTO newUser) {
9798
User user = userRepository.findByLogin(login).orElse(null);
9899

99100
if (user != null) {
100-
if (user.getConfig().has(app)) {
101+
if (user.getJsonConfig().has(app)) {
101102
log.warn("Try to add [{}] application in user [{}] where it already exist", app, login);
102103
throw new RequestErrorException("App [%s] for user [%s] already exist!", app, login);
103104
} else {
104-
((ObjectNode) user.getConfig()).set(app, newUser.getConfig());
105+
((ObjectNode) user.getJsonConfig()).set(app, newUser.getConfig());
105106
userRepository.updateConfigByLogin(user.getConfig(), login);
106107

107108
log.info("Added [{}] application for user [{}]", app, login);
@@ -127,7 +128,13 @@ public RequestStatusDTO createUser(String app, CreateUserRequestDTO newUser) {
127128
.put(UserAttributes.CREDENTIALS_EXP, Instant.now().plus(Duration.ofDays(365)).toEpochMilli());
128129
if (!config.has(app)) config.set(app, newUser.getConfig());
129130

130-
user = User.builder().login(login).salt(salt).config(config).name(name).enabled(true).build();
131+
user = User.builder()
132+
.login(login)
133+
.salt(salt)
134+
.config(new UserConfigWrapper(config))
135+
.name(name)
136+
.enabled(true)
137+
.build();
131138
userRepository.save(user);
132139

133140
jdbcTemplate.update("INSERT INTO hashes VALUES (?)", hash);
@@ -188,9 +195,9 @@ public RequestStatusDTO changeUserLockStatus(String login, Boolean enabled, Bool
188195
answer.append(enabled ? "enabled" : "disabled");
189196
}
190197
if (lock != null) {
191-
JsonNode userConfig = user.getConfig();
198+
JsonNode userConfig = user.getJsonConfig();
192199
((ObjectNode) userConfig.get(ssoServerProperties.getApplication().getName())).put(UserAttributes.LOCK, lock);
193-
userRepository.updateConfigByLogin(userConfig, login);
200+
userRepository.updateConfigByLogin(user.getConfig(), login);
194201
log.info("User [{}] {}", login, lock ? "locked" : "unlocked");
195202
answer.append(lock ? "locked" : "unlocked");
196203
}
@@ -223,11 +230,11 @@ public RequestStatusDTO changeUserPassword(String login, String oldPassword, Str
223230

224231
userRepository.updateSaltByLogin(salt, login);
225232

226-
((ObjectNode) user.getConfig().get(ssoServerProperties.getApplication().getName()))
233+
((ObjectNode) user.getJsonConfig().get(ssoServerProperties.getApplication().getName()))
227234
.put(UserAttributes.CREDENTIALS_EXP, Instant.now().plus(Duration.ofDays(365)).toEpochMilli());
228235

229-
if (user.getConfig().has(UserAttributes.TEMPORARY)) {
230-
((ObjectNode) user.getConfig().get(UserAttributes.TEMPORARY)).put("pass", newPassword);
236+
if (user.getJsonConfig().has(UserAttributes.TEMPORARY)) {
237+
((ObjectNode) user.getJsonConfig().get(UserAttributes.TEMPORARY)).put("pass", newPassword);
231238
userRepository.updateConfigByLogin(user.getConfig(), login);
232239
}
233240

@@ -258,13 +265,13 @@ public RequestStatusDTO changeApplicationConfigForUser(String login, String app,
258265
throw new RequestErrorException("There is no user with login [%s]", login);
259266
}
260267

261-
JsonNode userConfig = user.getConfig();
268+
JsonNode userConfig = user.getJsonConfig();
262269
if (!userConfig.has(app)) {
263270
log.warn("Try to change non existing config [{}] for user: {}", app, login);
264271
throw new RequestErrorException("There is no [%s] config for user [%s]", app, login);
265272
}
266273

267-
((ObjectNode) user.getConfig()).set(app, appConfig);
274+
((ObjectNode) user.getJsonConfig()).set(app, appConfig);
268275
userRepository.updateConfigByLogin(user.getConfig(), login);
269276

270277
log.info("Application [{}] config was changed for user [{}]", app, login);
@@ -285,13 +292,13 @@ public RequestStatusDTO deleteApplicationConfigForUser(String login, String app)
285292
throw new RequestErrorException("There is no user with login [%s]", login);
286293
}
287294

288-
JsonNode userConfig = user.getConfig();
295+
JsonNode userConfig = user.getJsonConfig();
289296
if (!userConfig.has(app)) {
290297
log.warn("Try to delete non existing config [{}] for user: {}", app, login);
291298
throw new RequestErrorException("There is no [%s] config for user [%s]", app, login);
292299
}
293300

294-
((ObjectNode) user.getConfig()).remove(app);
301+
((ObjectNode) user.getJsonConfig()).remove(app);
295302
userRepository.updateConfigByLogin(user.getConfig(), login);
296303

297304
log.info("Application [{}] config was deleted for user [{}]", app, login);
@@ -310,7 +317,7 @@ public RequestStatusDTO createTemporaryUser(String temporaryLogin, long dateFrom
310317
log.warn("Try to create temporary user for non existing user: {}", temporaryLogin);
311318
throw new RequestErrorException("There is no original user [%s]", temporaryLogin);
312319
}
313-
if (temporaryUser.getConfig().has(UserAttributes.TEMPORARY)) {
320+
if (temporaryUser.getJsonConfig().has(UserAttributes.TEMPORARY)) {
314321
log.warn("Try to create temporary user for ALREADY temporary user: {}", temporaryLogin);
315322
throw new RequestErrorException("Temporary users can't create other temporary users");
316323
}
@@ -340,9 +347,9 @@ public RequestStatusDTO createTemporaryUser(String temporaryLogin, long dateFrom
340347
temporaryNode.put("dateTo", dateToLdt.toLocalDate().toString());
341348
temporaryNode.put("pass", dTemporaryPassword);
342349
temporaryNode.put("originTabNumber", temporaryLogin);
343-
((ObjectNode) temporaryUser.getConfig()).set(UserAttributes.TEMPORARY, temporaryNode);
350+
((ObjectNode) temporaryUser.getJsonConfig()).set(UserAttributes.TEMPORARY, temporaryNode);
344351

345-
((ObjectNode) temporaryUser.getConfig().get(ssoServerProperties.getApplication().getName()))
352+
((ObjectNode) temporaryUser.getJsonConfig().get(ssoServerProperties.getApplication().getName()))
346353
.put(UserAttributes.CREDENTIALS_EXP, Instant.now().plus(Duration.ofDays(90)).toEpochMilli());
347354

348355
dTemporaryUser = User.builder()
@@ -368,7 +375,7 @@ private boolean checkUserAndDeleteHash(User user, String password) {
368375
try {
369376
authenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(user.getLogin(), password));
370377
} catch (AccountStatusException ex) {
371-
if (!user.getConfig().has(UserAttributes.TEMPORARY)) {
378+
if (!user.getJsonConfig().has(UserAttributes.TEMPORARY)) {
372379
throw ex;
373380
}
374381
}

src/test/java/ru/loolzaaa/authserver/services/UserServiceImplTest.java

-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ void shouldThrowExceptionIfUserNotExist() {
4848
@Test
4949
void shouldReturnUserDetailsWithoutHashes() {
5050
when(userRepository.findByLogin(anyString())).thenReturn(Optional.of(user));
51-
when(user.getConfig()).thenReturn(null);
5251
when(user.isEnabled()).thenReturn(false);
5352

5453
UserDetails userDetails = userService.loadUserByUsername("valid");
@@ -60,7 +59,6 @@ void shouldReturnUserDetailsWithoutHashes() {
6059
@Test
6160
void shouldReturnUserDetailsWithHashes() {
6261
when(userRepository.findByLogin(anyString())).thenReturn(Optional.of(user));
63-
when(user.getConfig()).thenReturn(null);
6462
when(user.isEnabled()).thenReturn(true);
6563

6664
UserDetails userDetails = userService.loadUserByUsername("valid");

0 commit comments

Comments
 (0)