Skip to content
Snippets Groups Projects
Commit 89c32e9f authored by Nicholas Blair's avatar Nicholas Blair
Browse files

feat: add callback for UserDetailsService#loadUserByUsername

Allows downstream projects to mutate the UWUserDetails instance returned by that core method.
parent ebdd5c9f
No related branches found
No related tags found
1 merge request!12feature: a callback interface allowing customization of UserDetailsService#loadUserByUsername
package edu.wisc.uwss.local;
import edu.wisc.uwss.UWUserDetails;
/**
* Callback interface allowing downstream projects to mutate the result to be returned from
* {@link LocalUserDetailsManagerImpl#loadUserByUsername(String)}.
*
* Example usage:
*
<pre>
class MyCustomLocalUWUserDetailsCallback implements LocalUWUserDetailsCallback<MyUWUserDetailsImpl> {
@Autowired
private MySomethingDao somethingDao;
public void success(MyUWUserDetailsImpl userDetails) {
userDetails.setMySomethingField(somethingDao.getSomethingsForUser(userDetails.getUsername());
}
}
</pre>
*
* Consumers can register any number of Beans implementing this interface; see {@link org.springframework.core.Ordered}
* if you need a particular order of execution.
*
* @author Nicholas Blair
*/
public interface LocalUWUserDetailsCallback<T extends UWUserDetails> {
/**
* Callback executed upon successfully loading the {@link UWUserDetails} for a username.
*
* @param userDetails the userDetails to modify
*/
void success(T userDetails);
}
......@@ -3,6 +3,8 @@
*/
package edu.wisc.uwss.local;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
......@@ -39,6 +41,8 @@ public class LocalUserDetailsManagerImpl implements UserDetailsManager {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private final Map<String, UWUserDetails> users = new ConcurrentHashMap<>();
@Autowired(required=false)
private List<LocalUWUserDetailsCallback> callbacks = new ArrayList<>();
@Autowired(required=false)
private LocalUserDetailsAttributesMapper localUserDetailsAttributeMapper = new LocalUserDetailsAttributesMapper.Default();
......@@ -68,6 +72,16 @@ public class LocalUserDetailsManagerImpl implements UserDetailsManager {
public void setDemoUsers(@Qualifier("demo-users") Properties properties) {
this.properties = properties;
}
/**
* Visible for testing.
*
* @param callbacks
*/
void setCallbacks(List<LocalUWUserDetailsCallback> callbacks) {
this.callbacks = callbacks;
}
/**
* Add a user. Does nothing if the argument is null or the {@link UWUserDetailsImpl#getUsername()} is blank.
*
......@@ -109,7 +123,11 @@ public class LocalUserDetailsManagerImpl implements UserDetailsManager {
if(user == null) {
throw new UsernameNotFoundException(username + " not found");
}
return SerializationUtils.clone(user);
UWUserDetails result = SerializationUtils.clone(user);
for(LocalUWUserDetailsCallback callback: callbacks) {
callback.success(result);
}
return result;
}
/**
* @param user
......
......@@ -10,6 +10,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Properties;
......@@ -30,7 +31,7 @@ import edu.wisc.uwss.UWUserDetailsImpl;
public class LocalUserDetailsManagerImplTest {
/**
* Verify {@link LocalUserDetailsServiceImpl#loadUserByUsername(String)} throws
* Verify {@link LocalUserDetailsManagerImpl#loadUserByUsername(String)} throws
* {@link UsernameNotFoundException} for an unknown user.
*/
@Test(expected=UsernameNotFoundException.class)
......@@ -275,5 +276,27 @@ public class LocalUserDetailsManagerImplTest {
manager.deleteUser(username);
assertFalse(manager.userExists(username));
}
@Test
public void loadUserByUsername_with_callback() {
boolean visited = false;
LocalUserDetailsManagerImpl manager = new LocalUserDetailsManagerImpl();
LocalUWUserDetailsCallback callback = new LocalUWUserDetailsCallback<UWUserDetailsImpl>() {
@Override
public void success(UWUserDetailsImpl userDetails) {
userDetails.setFirstName("something custom");
}
};
manager.setCallbacks(Arrays.asList(callback));
UWUserDetails user = new UWUserDetailsImpl("UW000A000", "foo", "bar", "Foo Bar", "foo@foo.wisc.edu");
// first name starts null
assertNull(user.getFirstName());
manager.addDemoUser(user);
UWUserDetails result = manager.loadUserByUsername("foo");
// observe firstname modified by the callback
assertEquals("something custom", result.getFirstName());
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment