Updating entity using Java Streams API - java-8

I am performing an update operation on the user object based on the userid using streams API. Below is the code that I have written.
Is there a better way to refactor the code as I need to again fetch the updated user and send.
public User updateUser(int userId, User user){
System.out.println("User id is "+ userId);
this.userRepository
.fetchUserByUserId(userId)
.map(u -> {
u.setUserId(user.getUserId());
u.setUsername(user.getUsername());
u.setEmailAddress(user.getEmailAddress());
return u;
});
return this.userRepository.fetchUserByUserId(userId).get();
}

I do not see any reason to fetch again
You can map user to updated user and to return the new one.
public User updateUser(int userId, User user){
System.out.println(String.format("UserId is %s",userId));
return this.userRepository
.fetchUserByUserId(userId)
.map(u -> this.mergeUsers(u,user));
}
public User mergeUsers(Optional<User> dbUser, User newUser){
if(dbUser.isPresent())
return user.builder()
.emailAddress(newUser.getEmailAddress())
.username(newUser.getUsername()).build();
else
// Do something else.
}
// Setting Id is irrelevant cause it is same value.. youre fetching by this value.

Related

Understanding how ConcurrentDictionary works in WEB API

I am trying to implement Refresh key repository (JWT). At the moment it looks like this:
public class AuthenticateController : ControllerBase
{
ConcurrentDictionary<string, string> refreshTokens = new ConcurrentDictionary<string, string>();
....
....
....
public async Task<IActionResult> Login()
{
...
GenerateRefreshToken()
...
}
public string GenerateRefreshToken(ApplicationUser user)
{
var randomNumber = new byte[32];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(randomNumber);
var token = Convert.ToBase64String(randomNumber);
refreshTokens.AddOrUpdate(user.Id, token, (key, oldValue) => token);
return token;
}
}
public async Task<IActionResult> RefreshToken([FromBody] RefreshModel model)
{
....
refreshTokens.TryGetValue(user.Id, out string savedRefreshToken);
if (savedRefreshToken != model.RefreshToken)
throw new SecurityTokenException("Invalid refresh token");
...
}
(I removed the code that I thought was unnecessary to explain)
The user tries to log in, the information about the first update key is entered into the collection. I put a breakpoint, you can see that the information is entered:
After the JWT key has expired, the frontend sends a request to update the key. But the collection is empty. Why is this happening? I am definitely not clearing the collection before.
I think the problem may be that the web api processes each new request in isolation from each other.
How do I solve this?
Controllers are transient meaning they are newly instantiated every time a request comes in. So your dictionary is wiped out between requests.
To fix this, you'd made your dictionary static, like so:
private static readonly ConcurrentDictionary<string, string> refreshTokens =
new ConcurrentDictionary<string, string>();
Now it will live the lifetime of the application.

How to pass object or data from one to another controller in spring-boot web application?

I want to take a some of data from users' input and then I want to transfer these between controllers.But this transfer must be done in the background for security. I don't want to send parameters on the URL.
I want to send the user object created in page1 controller to page2.
I used the model method for this, but I was not successful.
#Controller
public class DemoController {
...
..
.
#GetMapping("/page1")
public String page1(Model model) {
User user = new User();
user.setName("TestName");
user.setSurname("TestSurname");
user.setMail("xyzabc#gmail.com");
model.addAttribute("user", user);
return "redirect:/page2";
}
#GetMapping("/page2")
public String page2(#ModelAttribute("user") User user, Model model) {
System.out.println(user.toString());
return "page2";
}
.
..
...
}
How do I transfer objects?
There are 2 solutions for this question:
Solution 1: Store object in session
Code example:
#GetMapping("/page1")
public String page1(Model model, HttpSession session) {
...
session.setAttribute("user", user);
return "redirect:/page2";
}
#GetMapping("/page2")
public String page2(Model model, HttpSession session) {
User user = null;
if (session.getAttribute("user") != null) {
user = (User) session.getAttribute("user");
System.out.println(user.toString());
}
return "page2";
}
Solution 2: use forward instead of redirect
Code example:
#GetMapping("/page1")
public String page1(Model model) {
...
model.addAttribute("user", user);
return "forward:/page2";
}
you can use either :
session
or
2)forward:/page2 instead of redirect

Get the authority of the user at the time of deleting it in jhipster

I need to get the authority of the user which I am going to delete. My attempt as follows.
#DeleteMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
#Timed
#Secured({AuthoritiesConstants.ADMIN, AuthoritiesConstants.LECTURER})
public ResponseEntity<Void> deleteUser(#PathVariable String login) {
log.debug("REST request to delete User: {}", login);
boolean hasAuthorityAdmin = false;
boolean hasAuthorityMember = false;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
hasAuthorityAdmin = authorities.contains(new SimpleGrantedAuthority(AuthoritiesConstants.ADMIN));
hasAuthorityMember = authorities.contains(new SimpleGrantedAuthority(AuthoritiesConstants.MEMBER));
if (hasAuthorityAdmin) {
// delete user
userService.deleteUser(login);
} else {
if (hasAuthorityMember) {
// delete user if it is a student
if (**x**.contains(AuthoritiesConstants.STUDENT)) {
userService.deleteUser(login);
}
}
}
return ResponseEntity.ok().headers(HeaderUtil.createAlert("userManagement.deleted", login)).build();
}
There instead of x I need a method to retrieve it? That means I need to retrieve the authority which I am going to delete. So anyone have idea. This is inside the userResource.java. Can anyone help me with the code?
Suppose that I am logged in as an member. Then I am going to delete student. So when I am click the delete button of the student record, should be able to get the ROLE_STUDENT via a method.
This should do it :
if (hasAuthorityMember) {
Optional<User> user = userService.getUserWithAuthoritiesByLogin(login);
Set<Authority> currentUserAuthorities = user.get().getAuthorities();
for(Authority auth : currentUserAuthorities) {
// delete user if it is a student
if(auth.getName().equals(AuthoritiesConstants.STUDENT)) {
userService.deleteUser(login);
}
}
}
With UserService, you get the user and his authorities thanks to its login, and for each of its authorities (if there are many), we check the name of the authority. If corresponds to Student, you then delete the user.

Spring Oauth with multiple users tables

I am creating an application using Spring with Oauth2 as a backend for two apps (provider app and a consumer app). I have two different types of users; Providers, and consumers, each with its own db table.
The problem I am facing is that I cannot find a way to know if the request is coming from a provider or a customer, as each one will be in a different db table.
The username is Not unique between the two tables. So, a provider and a consumer can have the same username (and password).
I think any of the following solutions will suffice, however, I can’t find any way to implement any of them.
Having two different endpoints for each user class. e.g. “/provider/oauth/token” and “/consumer/oauth/token”. Each with its custom authentication manager.
Or: Having two authorization servers in the same Spring application, and then mapping their “/oauth/token” to different endpoints.
Or: Sending custom data in the oauth request to know where the request is coming from, and then dynamically selecting an authentication manager.
Or: Associating different authentication manager to different OAuth clients, and then ensuring that each app will have its respective client ID.
If any of these solutions is possible, or if there is another way to accomplish this, please let me know.
Any help is appreciated.
Edit - Solution
Following the answer below, I added another client with a different client ID, check the id in the UserDetailsService and then decide which db to use. Here is the code:
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
User user = (User) authentication.getPrincipal();
String username = user.getUsername();
if (username.equals(OAuth2Configuration.provider_app))
// Load from provider db
else if (username.equals(OAuth2Configuration.consumer_app))
// Load from consumer db
else
throw new UsernameNotFoundException("ClientID " + username + " not found.");
}
};
}
UsernamePasswordAuthenticationToken is used as /oauth/token is protected with Basic Oauth using the client id and secret.
I think you should be able to look inside SecurityContextHolder.getContext().getAuthentication.
This should be an instance of OAuth2Authentication, from which you can (after you cast) call getOAuth2Request() to get the original Oauth2Request details.
With this information you can have a single UserDetailsService that can delegate lookups to the correct db tables. You could use scopes or resourceIds to help determine what db table to use.
You could use the third option. but this is not a good principal to follow. you can send a custom param in the oauth/token end point. it can be accessed by AutoWiring HttpServletRequest in the userDetailsService.
UserDetailsService
#Autowired
private HttpServletRequest httpServletRequest;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
String userType = httpServletRequest.getParameter("user_type");
LOGGER.info("Load user method \n Username : " + username + "\nuser_type : " + userType);
if (userType == null) {
throw new CustomOauthException("User type is required !");
}
if (userType.equals(String.valueOf(MOBILE_USER))) {
//get user..
} else if (userType.equals(String.valueOf(DRIVER))) {
//get driver..
} else if (userType.equals(String.valueOf(ADMIN))) {
//get admin
}
throw new CustomOauthException("User type is not valid !");
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("Exception : " + e.getMessage());
throw new CustomOauthException(e.getMessage());
}
}

Best way to log in, log out, and store session attributes in JSF

I am very new to JSF, and I am pretty confused about the best practices of managing user logins. There are a lot of answers floating around, but they require knowledge of JSF and Java EE which I don't seem to have.
When working with a classic JSP project, I handle logins in a very simple way. When a user successfully logs in, a session attribute "isLoggedIn" is created with the value true. When the user logs out, the session is invalidated. If the "isLoggedIn" attribute is either false or missing, pages that require you to be logged in redirect to the login screen.
How would this sort of thing be done in JSF? Should I store things like login status, username, and user role in an HttpSession, or in a managed session bean?
A lot of answers that I found say that you should use request.getRemoteUser() to manage logins, but don't give any further explanation. From what I was able to gather, this method is useful if you are using domain credentials to log into the application. So is it of any use if I'm storing user credentials (username + salted and hashed password) in a database?
It would be very helpful if someone can show me how a website with the following two pages would work:
A login page where one can enter a username and password and press a "Login" button.
A page with the message "Login Successful", and a logout button. When the log out button is pressed, the user is logged out and brought to the login page.
If a user tries to go to the second page while they are not logged in, they will be redirected to the first page.
Like I said before, I am very new to JSF and I simply cannot find a good tutorial for how to handle this sort of thing. So any links that you feel are useful will be appreciated.
If it matters, I am using the MyFaces implementation, and the PrimeFaces component library.
You have two basic options:
Use container-based authentication.
Roll your own.
The first option is the officially recommended approach, and the exact details will vary depending upon what servlet container and/or web framework you are using.
Frankly, however, I often find configuring container-based authentication to be more trouble than it is worth (and more trouble than simply building a custom authentication layer that does what I want). So if you're interested in rolling your own, the approach I generally take (using Spring and Hibernate) is to have a User class like:
#Entity
#Table(name="users")
#NamedQueries({
#NamedQuery(name="User.findAll", query="SELECT u FROM User u"),
#NamedQuery(name="User.findByPrimaryEmail", query="SELECT u FROM User u WHERE u.primaryEmail = :email")
})
public class User {
//fields
private long id;
private String primaryEmail;
private String firstName;
private String lastName;
private String hashedPassword;
private String salt;
//...
//relationships
//...
public User() {
primaryEmail = null;
firstName = null;
lastName = null;
salt = null;
hashedPassword = null;
//...
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(unique=true)
public String getPrimaryEmail() {
return primaryEmail;
}
public void setPrimaryEmail(String email) {
this.primaryEmail = email;
if (this.primaryEmail != null) {
this.primaryEmail = email.toLowerCase();
}
}
#Column
public String getHashedPassword() {
return hashedPassword;
}
public void setHashedPassword(String hashedPassword) {
this.hashedPassword = hashedPassword;
}
#Column
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
//(getters and setters for any other columns and relationships)
#Transient
public void setPassword(String passwordPlaintext) throws NoSuchAlgorithmException, InvalidKeySpecException {
if (this.getSalt() == null) {
this.setSalt(StringUtilities.randomStringOfLength(16));
}
this.setHashedPassword(this.computeHash(passwordPlaintext, this.getSalt()));
}
#Transient
public boolean checkPasswordForLogin(String passwordPlaintext) throws NoSuchAlgorithmException, InvalidKeySpecException {
if (StringUtilities.isEmpty(passwordPlaintext)) {
return false;
}
return this.getHashedPassword().equals(this.computeHash(passwordPlaintext, this.getSalt()));
}
#Transient
private String computeHash(String password, String salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 2048, 160);
SecretKeyFactory fact = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
//I encode to base64 so that I can treat the hash as text in computations and when storing it in the DB
return Base64.encodeBytes(fact.generateSecret(spec).getEncoded());
}
}
And then a simple login form like:
<form id="loginForm" method="POST" action="/r/submitLogin">
<div class="formRow">
<span class="formLabel">Email</span> <input type="text" class="textInput" name="email" />
</div>
<div class="formRow">
<span class="formLabel">Password</span> <input type="password" class="textInput" name="pass" />
</div>
<div class="formRow">
<input type="submit" class="submitButton" value="Log In" />
</div>
</form>
And a submitLogin implementation that goes like:
public ModelAndView submitLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String email = request.getParameter("email");
String pass = request.getParameter("pass");
EntityManager em = DatabaseUtil.getEntityManager(request); //get an EntityManager, you can also use dependency-injection to do this if you prefer
User user = getUserByPrimaryEmail(email, em); //lookup the user by email address
if (user == null) {
//invalid username
request.setAttribute("error", "User not found");
return login(request, response);
}
try {
if (user.checkPasswordForLogin(pass)) {
//valid login, remember the user in the session
request.getSession().setAttribute(Constants.SESSION_USER_KEY, user);
//send the user to the default page
response.sendRedirect("/r/indexPage");
return null;
}
else {
//invalid password
request.setAttribute("error", "Incorrect password");
return login(request, response);
}
}
catch (Exception e) {
//should only happen if checkPasswordForLogin() throws NoSuchAlgorithmException/InvalidKeySpecException
LOG.error("Login processing failed!", e);
request.setAttribute("error", "Cannot generate password hash?!?!?");
return login(request, response);
}
}
That's all there is to it, for a basic implementation at any rate. You can of course build features on top of this, such as "remember me" cookies/persistent logins, user roles, statuses, access levels, and so on. But for basic login/logout this is all you really need.
With this approach, the logged-in user will be available by doing request.getSession().getAttribute(Constants.USER_KEY), where Constants.USER_KEY is just some arbitrary string that you define. I typically use something along the lines of "<appName>.user".
If using container-based authentication, the user will typically be exposed by calling request.getUserPrincipal().

Resources