I am trying to create a mini chat application that has users table. The users table has a field called isAdmin that identifies that such a particular user is an admin and if isAdmin is set to false such a user is a customer
the user.java table fields
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "userId")
private Long id;
#Column(nullable = false)
private String name;
#Column(unique = true, nullable = false)
private String email;
#Column(nullable = false)
private long timestamp;
#Column(nullable = true)
private boolean isAdmin;
When I am trying to save a user, I try maintaining a request-response setAttribute method parameter using email field to hold the session attribute email is unique in my db
snippet of the code
#RequestMapping(value = "/create-user", method = RequestMethod.POST)
public ModelAndView createUser(HttpServletRequest request,
HttpServletResponse response,
#RequestParam String name,
#RequestParam String email) {
try {
// create new user object
User user = new User();
user.setName(name);
user.setEmail(email);
user.setTimestamp(new Date().getTime());
// save user in db (if new)
if (_userDao.getByEmail(email) == null) {
request.getSession().setAttribute("email", email);
_userDao.save(user);
}
} catch (Exception e) {
e.printStackTrace();
//logger.error("Exception in creating user: ", e.getStackTrace());
}
return new ModelAndView("redirect:/");
}
I am getting all the chats by email using requests.getSession.getAttribute as shown
#ResponseBody
#RequestMapping(value = "/get-all-chats", method = RequestMethod.GET)
public List<Chat> getAllChats(HttpServletRequest request,
HttpServletResponse response) {
String email = (String) request.getSession().getAttribute("email");
try {
if (email != null) {
return _chatDao.getAll(email);
}
} catch (Exception e) {
e.printStackTrace();
logger.error("Exception in fetching chats: ", e.getStackTrace());
}
return null;
}
my dao method has a query to retrieve all the chats based on the email session attribute that was set
public List getAll(String email) {
String hql = "from Chat c where c.user.email = :email";
return _sessionFactory.getCurrentSession().createQuery(hql).setParameter("email", email).list();
my challenge/confusion is that when I fetch the chat the user can only see his chat and the admin can only see his chat. the chat is not transferred between the admin and the user. Kindly assist.
Related
I have a class User with:
int id;
String username;
String password;
String token;
Date tokenExpires;
And i have a method like this:
private EntityManager em;
private User authenticate(String username, String password) throws Exception {
// Authenticate against a database, LDAP, file or whatever
// Throw an Exception if the credentials are invalid
Query query = em.createQuery("Select u from User u WHERE u.username = :name and u.password = :password");
query.setParameter("name", username);
query.setParameter("password", password);
return (User) query.getSingleResult();
}
and a method to generate a token:
private String issueToken(String username) {
Random random = new SecureRandom();
String token = new BigInteger(130, random).toString(32);
return token;
}
how to save this token to db, everytime user log in? so when user log in should generate a token, if user log in again it should generate a new token
When a user logs in, simply fetch the user from the database, then set the mentioned fields, the token and its' expiration date:
public User updateUser(String username, String password) {
User user = getUserBy(username, password);
String token = issueToken();
// token expires in 30 mins;
Date tokenExpires = new Date(System.currentTimeMillis() + 1800000);
user.setToken(token);
user.setTokenExpires(tokenExpires);
entityManager.getTransaction().begin();
entityManager.merge(user);
entityManager.getTransaction().commit();
}
Considering you are using Hibernate, then, the User model has to be annotated as well:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
private String token;
#Temporal(TemporalType.TIMESTAMP)
private Date tokenExpires;
// getters and setters, make sure they are present
}
if you use spring, try this guide, for example: https://javadeveloperzone.com/spring-boot/spring-boot-oauth2-jdbc-token-store-example/
I try to make an API call with the post method via postman to my spring boot application.
Here is the input:
{
"username": "name",
"password": "1234",
"age": 12,
"salary": 5000,
"role": 1
}
Here is the code in the controller:
#RequestMapping(value = "/signup", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> saveUser(#RequestBody UserDto user) {
try {
System.out.println(user.getUsername()); // => name
System.out.println(user.getPassword()); // => 1234
System.out.println(user.getSalary()); // => 5000
System.out.println(user.getRoleDto()); // => null
System.out.println(user.getAge()); // => 24
userService.save(user);
return ResponseEntity.ok().body("insert done");
} catch (Exception e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
All properties print their value except the user.getRoleDto(), it always null. But, when I try to use this (below code) in the controller, it print the whole object exactly like the input object.
#RequestMapping(value="/signup", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> saveUser(HttpEntity<String> httpEntity){
try {
String json = httpEntity.getBody();
System.out.println(json);
return ResponseEntity.ok().body("insert done");
} catch (Exception e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
Here is my User.java
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String username;
#Column
#JsonIgnore
private String password;
#Column
private long salary;
#Column
private int age;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "role_id")
private Role role;
// getters and setters
Here is my Role.java
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "role_name", nullable = false)
private String roleName;
// getters and setters
Here is my UserDto.java
private String username;
private String password;
private int age;
private long salary;
private RoleDto roleDto;
Here is my RoleDto.java
private Long id;
private String roleName;
What went wrong here? Any help would be very helpful. Thanks!
UPDATE
Thanks to Burm87, I took the option 1 from his suggestions in the answer. But, somehow the spring still see role_id as null, even the value is printed now. Here is in the userServiceImpl:
#Override
public User save(UserDto user) throws Exception {
User newUser = new User();
BeanUtils.copyProperties(user, newUser, "password");
// above line is refer to [here][1].
newUser.setPassword(bcryptEncoder.encode(user.getPassword()));
try {
userDao.save(newUser);
} catch (Exception e) {
throw new Exception(e);
// this throw "Column role_id cannot be null"
}
return newUser;
}
But, if I use below code, the setRole method is not applicable since I define user.getRole() in the DTO as int but define newUser.setRole() in the User entity as Role. But if I change the setRole in User entity as int, then, how I can tell the spring about the ManyToOne relation between User and Role? Note: I think I just want to make the input parameter for role to be just an integer as provided above.
#Override
public User save(UserDto user) throws Exception {
User newUser = new User();
newUser.setUsername(user.getUsername());
newUser.setPassword(bcryptEncoder.encode(user.getPassword()));
newUser.setAge(user.getAge());
newUser.setSalary(user.getSalary());
newUser.setRole(user.getRole()); // here is the problem
try {
userDao.save(newUser);
} catch (Exception e) {
throw new Exception(e);
}
return newUser;
}
You have two options here:
1) you keep the request you have and you change this field roleDto in your DTO to be an Integer field named role (renaming getter and setter accordingly);
2) you keep your DTO as it is and you change your request sending:
{
"username": "name",
"password": "1234",
"age": 12,
"salary": 5000,
"roleDto": {
"id": 1,
"roleName": "your role name"
}
}
role is null, because In UserDTO you have RoleDto. So you need to rename "role" to "roleDto" as it is a complex object ,it will have its own json. Please replace it with the following Json and see it works. Please follow this tutorial for more understanding.
{
"username": "name",
"password": "1234",
"age": 12,
"salary": 5000,
"roleDto": {
"id":1
}
}
It's because in your json you have "role": 1 and in dto - user.getRoleDto(). There is a mismatch between names, so it cannot be properly mapped. Try changing field name from roleDto in UserDto into role.
I am trying to update some user information by passing List of User-Ids as parameter
i want to update isActive field of User fo which i am passing the user ids.
Below is my controller
#PutMapping
#ResponseStatus(HttpStatus.OK)
#RequestMapping("/UserUpdate")
public ResponseEntity<?> updateUsers(List<Long> userIds) {
**userService.updateUsers(userIds);**
return ResponseEntity.ok(200);
}
updateUsers() is a method in my Service where i have to write the logic
I tried something like below but it's not working
public void updateUsers(List<Long> userIds) {
List<Users> userList= userRepository.findAll();
for (Long i : userIds) {
for ( Users user : userList)
{
if(userRepository.findById(i) != null)
{
user.setIsActive(9L);
user.setUserName("Update Test");
}
my dto
public class UserDto {
private List<Users> userList;
private String appName="Users Project";
// getters and setters removed for brevity
And my Users entity class
#Entity
#Table(name="USERS")
public class Users {
#Id
#Column(name="USER_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
#Column(name="NAME")
private String userName;
#Column(name="ACTIVE")
private Long isActive;
// getters and setters removed for brevity
Alternatively you can use the following code
#Modifying
#Query("update Users u set u.isActive = ?1, u.userName = ?2 where u.userId in ?3")
void updateUsers(Long isActive, String userName, List<Long> userId);
Add this code in your userRepository and use the method.
public void updateUsers(List<Long> userIds) {
for (Long i : userIds) {
User user = userRepository.findById(i);
if(user != null){
user.setIsActive(9L);
user.setUserName("Update Test");
// call your update method here (this is not stated in your code)
}
}
}
I'm using Spring security for the login. I have the User.java which contains user-details.
#Entity(name = "user_table")
//#Table(name = "user_table")
public class User {
#Id
#Column(name = "id")
private String userId;
#Column(name = "email" ,unique = true)
private String userEmail;
#Column(name = "password")
private String userPassword;
//getter and setters
}
I'm getting the whole data of the current user from the table by using spring security. This is the code:
public User findUserByEmail(String email) {
List<User> users = new ArrayList<User>();
try{
users = sessionFactory.getCurrentSession().createQuery("from user_table where email= ?").setParameter(0, email).list();
System.out.println("user is " +users);
}catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
if (users.size() > 0) {
return users.get(0);
} else {
return null;
}
}
#Override
public User getCurrentUser() {
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
User currentUser = new User();
if (!(auth instanceof AnonymousAuthenticationToken)) {
UserDetails userDetails = (UserDetails) auth.getPrincipal();
System.out.println("User has authorities: "
+ userDetails.getAuthorities());
System.out.println("USERNAME:: "+userDetails.getUsername());
currentUser = findUserByEmail(userDetails
.getUsername());
System.out.println("currentUser "+currentUser);
System.out.println("currentUser "+currentUser.getUserId());
return currentUser;
}
return null;
}
What I want is to send the user id which I'm getting from currentUser.getUserId() to some other method. In that method I'm mapping to some other table like user_detail table where id is primary key. By sending id, I will get the other user_details which are not present in the user_table.
This is my UserDetail:
#Entity(name = "user_detail")
#Table(name = "user_detail")
public class UserDetail {
#Id
#GeneratedValue
#Column(name = "id")
private String userId;
//some other details like Address .
//getter and setter.
}
From controller I'm calling the above method like this:
UserService userService = new UserService();
User user=userDao.getCurrentUser();
String userId = user.getUserId();
System.out.println(userId);
UserDetail u=userDao.findUserById(userId);
and this is the method where I pass the current user id :
public UserDetail findUserById(String id) {
// TODO Auto-generated method stub
List<String> users = new ArrayList<String>();
try{
users = sessionFactory.getCurrentSession().createQuery("from user_detail where id= ?").setParameter(0, id).list();
System.out.println("user is " +users);
}catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
if (users.size() > 0) {
return null;
} else {
return null;
}
}
Now the result I'm getting here is null . Like user is null. What I'm doing wrong here?
There are several problems in your code. Just to point out some of them:
UserService userService = new UserService(); - you're manually creating the service object and not letting Spring-MVC injecting it into your controller, i.e. :
#Autowired
private UserService userService ;
UserDAO should be injected in your service, and not called from your controller :
class UserServiceImpl implements UserService{
#Autowired
private UserDAO userDAO;
}
All operations from your controller should call services methods and not DAO's methods. The service should use the DAO for database access. i.e.
UserDetail u=userDao.findUserById(userId);
should become
UserDetail u = userService.findUserById(userId);
and in your service :
class UserServiceImpl implements UserService{
#Autowire
private UserDAO userDAO;
#Override
public UserDetail findUserById(Long userId){
return userDAO.findUserById(userId);
}
}
if (users.size() > 0) {
return null;
} else {
return null;
}
is always returning null. Should be :
if (`users.isEmpty()){
return users.get(0);
}else { return null;}
users = sessionFactory.getCurrentSession().createQuery("from user_detail where id= ?").setParameter(0, id).list();
Your query is wrong. You should use your current bean class name and not the table name in your query, i.e. createQuery("FROM UserDetail WHERE id = ?")
With this search.jsp, it finds matches all words searched by user, then removes duplicate found users and shows a list of found matches.
I can only search for e-mail, firstname, lastname, username of a user, but I also want to search skills, and show the users who match that skill found.
For example I search for username; Admin, it finds the admin and shows
this person in the result. This works now, but I also want this;;; If
I search for Java, Then I want everybody that has the skill Java to
show up in the result.
I know it is easier with SQL query's, but this is different.
I have provided the models and database information below;
database:
**Table name: User**
userId
emailAddress
firstname
lastname
username
**Table name: user_skill**
User_userId
skills_skillId
**Table name: skill**
skillId
name
where it all happens : : : search.jsp:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Hij komt er in");
//get the action
String uri = request.getRequestURI();
String action = uri.substring(uri.lastIndexOf("/") + 1);
if (action.equals("searchUser")) {
Session session = HibernateUtil.getSessionFactory().openSession();
String searchQuery = request.getParameter("searchQuery");
String[] params = searchQuery.split(" ");
// Found users
List<User> usersFound = new ArrayList<User>();
// Exact match
String hqlMatch = this.getSearchHqlQuery(params, "AND");
List<User> exactResult = session.createQuery(hqlMatch).list();
if (exactResult != null && !exactResult.isEmpty()) {
usersFound.addAll(exactResult);
} // Multiple search
else {
String hqlLike = this.getSearchHqlQuery(params, "OR");
List<User> likeResult = session.createQuery(hqlLike).list();
if (likeResult != null && !likeResult.isEmpty()) {
usersFound.addAll(likeResult);
}
}
System.out.println("size:" + usersFound.size());
// set our results on the request and redirect back
request.setAttribute("users", usersFound);
request.setAttribute("usersSize", usersFound.size());
request.setAttribute("usersSizeResults", usersFound.size());
redirect(request, response, "/search.jsp");
session.close();
}
}
private String getSearchHqlQuery(String[] params, String andOrfilter) {
StringBuilder hql = new StringBuilder();
hql.append("from User ");
if (params.length > 0) {
hql.append("where ");
for (int i = 0; i < params.length; i++) {
if (i > 0) {
hql.append(andOrfilter);
}
hql.append(" (username like '%").append(params[i]);
hql.append("%' OR firstname like '%").append(params[i]);
hql.append("%' OR lastname like '%").append(params[i]);
hql.append("%' OR emailAddress like '%").append(params[i]);
hql.append("%') ");
}
}
return hql.toString();
}
model.user.java:
#Entity
public class User implements Serializable{
#Id
#GeneratedValue
private int userId;
private String username, firstname, lastname, emailAddress, position, password;
private String fullName;
private boolean isAdmin;
#ManyToMany
private List<Skill> skills;
public User(){
}
model.skill.java:
#Entity
public class Skill implements Serializable {
#Id
#GeneratedValue
private long skillId;
#Column(columnDefinition = "varchar(25)")
private String name;
#Column(columnDefinition = "varchar(25)")
private String level;
#Column(columnDefinition = "varchar(250)")
private String description;
public Skill() {
}
Add a join to the skills, and an or clause to your query:
select distinct u from User u
left join u.skills skill
where ... (existing or clauses)
or skill.name like :param
Also, your code is opened to SQL injection attacks, and will fail if the param contains a single quote. Use a named parameter as shown above.