i have Three entities User, Institution and Role.
1)one to many between user and institution
2)and many to many between User and Role
-------user-------
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="user_Id")
private int userId;
#Column(name="name")
private String name;
#Column(name="lastname")
private String lastname;
#Column(name="email")
private String email;
#Column(name="password")
private String password;
#Column(name="isActive")
private boolean isActive;
#Column(name="lastActive")
private String lastActive;
#Column(name="createdDate")
private String createdDate;
#Column(name="isBlocked")
private boolean isBlocked;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "institution_id", nullable = false)
#JsonIgnoreProperties(value = {"user"})
private Institution institution;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "user_has_role",
joinColumns = {
#JoinColumn(name = "user_id", referencedColumnName = "user_id",
nullable = false, updatable = true)},
inverseJoinColumns = {
#JoinColumn(name = "role_id", referencedColumnName = "role_id",
nullable = false, updatable = true)})
#JsonIgnoreProperties(value = {"users"})
private Set<Role> roles = new HashSet<>();
}
-------institution-------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "institution")
public class Institution {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="institution_Id")
private int institutionId;
#Column(name="name")
private String name;
#Column(name="type")
private String type;
#Column(name="location")
private String location;
#OneToMany(mappedBy = "institution", fetch = FetchType.LAZY)
#JsonIgnoreProperties(value = {"institution" , "user"})
private Set<User> user;
}
-------role-------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="role_Id")
private int roleId;
#Column(name="name")
private String name;
#Column(name="description")
private String description;
#ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
#JsonIgnoreProperties(value = {"roles"})
private Set<User> users = new HashSet<>();
}
Those are my 3 entities and tables in MySql
i have 7 roles
• Super-User
• Bank-Admin
• Bank-Support
• Bank-Service
• Merchant-Admin
• Merchant-Support
• Merchant-service
The super-User can create a user of any role
#PostMapping("/addUser")
public String addUser(#RequestBody User user) {
String rawpassword = user.getPassword();
String encodedpasswrod = passwordencoder.encode(rawpassword);
user.setPassword(encodedpasswrod);
userrepository.save(user);
return "user saved with name: " + user.getName();
}
this api works and i can set the role to anything in my api json body
But want that if the User is Bank-Admin he can only create Bank-Support and Bank-Service
im trying to create a new API which can only create a user with those 2 specific roles.
and then restrict the bank admin to access the other API that can create users of any kind.
is there any other way to do it and if no how can i do that...
You have to implement your custom implementation of User Entitlement.
Like according to login person, you will get that login person role, and according to your criteria just put validation like check that entity he is trying to add is he eligible to create it.
Map<String, List<String>> roleUserAccessMap = new HashMap<>();
roleUserAccessMap.put("Bank-Admin", Arrays.asList("Bank-Support", "Bank-Service"));
Just check like below
String loginPersonRole="Bank-Admin"; //This value should get from logged-in person context
if(roleUserAccessMap.containsKey(loginPersonRole) && roleUserAccessMap.get(loginPersonRole).contains(newuserrole) ){
//proceed ahead with Add api
}else{
System.out.println("You do not have enough privileage to create Use");
}
This will help you.
Related
I have two tables. A Users table and an Artists table. Users can be associate with many artists, and vice versa. I have an API call that adds an Artist to the User's list. The API seems to work correctly, but when I check the User afterward, my postman return shows an endless list of the artist I added.
The user entity:
#Entity
#Table(name = "users")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Slf4j
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", nullable = false)
Integer id;
#Column(name = "username")
String username;
#Column(name = "picture_link")
String pictureLink;
#ManyToMany
#JoinTable(
name = "user_artist",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "artist_id"))
Set<Artist> artists = new HashSet<>();
The artist entity:
#Entity
#Table(name = "artists")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Slf4j
public class Artist {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", nullable = false)
Integer id;
#Column(name = "name")
String name;
#Column(name = "description")
String description;
#Column(name = "picture_link")
String pictureLink;
#Column(name = "genres")
String genres;
#ManyToMany(mappedBy = "artists")
Set<User> users = new HashSet<>();
#Transient
List<Album> albums = new ArrayList<>();
}
The api call that causes the infinite loop:
#Override
public String addArtistToFaveList(int user_id, int artist_id) {
try{
User foundUser = new User();
Artist foundArtist = new Artist();
Optional<User> resultUser = userRepo.findById(user_id);
Optional<Artist> resultArtist = artistRepo.findById(artist_id);
if(resultUser.isPresent() && resultArtist.isPresent()){
foundUser = resultUser.get();
foundArtist = resultArtist.get();
}
Set<Artist> userFaveSet = foundUser.getArtists();
userFaveSet.add(foundArtist);
userRepo.save(foundUser);
return "THIS WORKED!";
}catch(Exception e){
return "Failed completely.";
}
}
i have 3 tables in mySQL, User, Institution and Role
1)one to many relation from user to institution (one user can work at one institution, and one institution can have many users)
2)many to many relation between role and user
the institutions in my database are already inserted and the user can only work in a specific existing institution.
and also the rolesin my database are already inserted and the user can only have an existing role.
i manually added 7 roles to my DB for user and for institution.
i want to add a user and specify his role in the API request but it wont work.
-------user model-------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="user_Id")
private int userId;
#Column(name="name")
private String name;
#Column(name="lastname")
private String lastname;
#Column(name="email")
private String email;
#Column(name="password")
private String password;
#Column(name="isActive")
private boolean isActive;
#Column(name="lastActive")
private String lastActive;
#Column(name="createdDate")
private String createdDate;
#Column(name="isBlocked")
private boolean isBlocked;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "institution_id", nullable = false)
private Institution institution;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "user_has_role",
joinColumns = {
#JoinColumn(name = "user_id", referencedColumnName = "user_id",
nullable = false, updatable = true)},
inverseJoinColumns = {
#JoinColumn(name = "role_id", referencedColumnName = "role_id",
nullable = false, updatable = true)})
private Set<Role> roles = new HashSet<>();
}
--------role model------------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="role_Id")
private int roleId;
#Column(name="name")
private String name;
#Column(name="description")
private String description;
#ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
private Set<User> users = new HashSet<>();
}
----------institution model------------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "institution")
public class Institution {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="institution_Id")
private int institutionId;
#Column(name="name")
private String name;
#Column(name="type")
private String type;
#Column(name="location")
private String location;
#OneToMany(mappedBy = "institution", fetch = FetchType.LAZY)
private Set<User> user;
}
--------controller-----------
#PostMapping("/addUser")
public String addUser(#RequestBody User user) {
userrepository.save(user);
return "user saved with name: " + user.getName();
}
--------- my api request---------
{
"name": "user1",
"lastname": "lastname",
"email": "user1#hotmail.com",
"password": "user1123",
"lastActive": "02/01/20",
"createdDate": "06/05/19",
"institution": {
"institutionId": 3
},
"roles": [
{
"role_id": 2
}
],
"active": true,
"blocked": false
}
but this is not working properly its creating a new role with empty fields...
i just need it to add into the user_has_role table the correspondent id for user_id and role_id
please help
For example, I have the User class, with looks like the next:
#Entity
#Table(name = "users")
public class User{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#NotBlank
#Size(max = 40)
#Column(name = "name")
private String name;
#NotBlank
#Size(max = 15)
#Column(name = "username")
private String username;
#NaturalId
#NotBlank
#Size(max = 40)
#Email
#Column(name = "email")
private String email;
#NotBlank
#Size(max = 100)
#Column(name = "password")
private String password;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
//Constructor
//Getters and Setters
And I have the Client class:
#Entity
#Table(name = "cliente")
public class Cliente {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "empresa")
private String empresa;
#Column(name = "telefono")
private Integer telefono;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(unique = true)
private Licencia licencia;
#OneToMany(cascade = {
CascadeType.PERSIST,
CascadeType.REMOVE
} ,fetch = FetchType.EAGER)
#JoinTable(name = "user_cliente",
joinColumns = #JoinColumn(name = "cliente_id"),
inverseJoinColumns = #JoinColumn(name = "user_id"))
private Set<User> users = new HashSet<>();
public Cliente(String empresa, Integer telefono) {
this.empresa = empresa;
this.telefono = telefono;
}
//Constructor
//Getters and Setters
Now, what I want to do is the Client class to extends the User class, so I can add a Client with name, username, email, etc. But I want two separate tables in MySQL, one for the users and its attributes, and other for clients only with the information of client, like the telephone or company. The problem is when I extends the User class in Client class, the MySQL databases updates and create the fields of telephone, company, etc. in the User table. How can I avoid this?
Use #MappedSuperclass:
#MappedSuperclass
public class BaseEntity {
// here you can add common fields for your entities
}
and then extend from it:
#Entity
public class User extends BaseEntity {
// user specific fields goes here
}
and Client:
#Entity
#Table(name = "cliente")
public class Cliente extends BaseEntity {
// client specific fields here
}
For more info read How to inherit properties from a base class entity using #MappedSuperclass with JPA and Hibernate
For the current structure of database:
database structure
Users
#Entity
#Table(name = "users")
public class User {
#Id
#Column(name = "username", unique = true, nullable = false, length = 45)
private String username;
#Column(name = "password", nullable = false, length = 60)
private String password;
#Column(name = "enabled", nullable = false)
private boolean enabled;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade=CascadeType.ALL)
private Set<UserRole> userRole = new HashSet<UserRole>(0);
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(
name = "users_product",
joinColumns ={#JoinColumn (name = "users_username", referencedColumnName = "username")},
inverseJoinColumns = {#JoinColumn(name = "Products_idProducts", referencedColumnName = "idProducts")}
)
List<Products> productsList = new ArrayList<Products>();
Products
#Entity
#Table(name = "products")
public class Products implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "idProducts")
private long id;
#Column(name = "description")
private String description;
#Column(name = "price")
private String price;
#Column(name = "image")
private byte [] image;
#ManyToMany(mappedBy = "productsList")
List<User> usersList = new ArrayList<User>();
//setters - getters
I want to implement a shopping basket.
What I have now: A page with products and checkboxes on the view page. I find these products and send them to my controller, and afterwards set them to the current user.
productsList = myService.findManyProducts(toAdd);
user.setProductsList(productsList);
myService.updateUser(user);
#Transactional
public void updateUser(User user){
userDao.update(user);
}
update user function:
#Override
public void update(User user) {
entityManager.merge(user);
}
These actions are entered in the database as different values, depending on the latest additions.
What I want:
User adds some products to cart, browse other items, and add new products to the cart. How do I ensure that duplicate items are not found in the cart? Does JPA have some standard methods? Or do I need to check the product list by myself before adding them to the database?
I solved this by changing the List collection to a Set in the User entity.
I have 2 entitie. User:
#Table(name = "USERS")
#Entity
public class User {
#Column(name = "user_id")
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private String email;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
private Authentication authentication;
}
and Authentication:
#Table(name = "AUTHENTICATIONS")
#Entity
public class Authentication {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "login_id")
private String loginId;//openId login
#JsonIgnore
private String password;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "user_id")
private User user;
}
And I have service which provides registration for new users:
#Override
#Transactional
public User createUser(UserRegistrationForm form) {
Authentication authentication = new Authentication();
authentication.setPassword(form.getPassword());
User user = new User();
user.setAuthentication(authentication);
user.setEmail(form.getEmail());
user.setName(form.getLogin());
authentication.setUser(user);
return userRepository.save(user);
}
And my problem is method userRepository.save() returns infinitely nested objects:
{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"
What am I doing wrong? Help to understand how it should work.
it's json which returns nested objects ... not your repository !
you are using jackson ?
add #JsonManagedReference on one side and #JsonBackReference on the other
Your problem is:
user.setAuthentication(authentication);
...
authentication.setUser(user);
You have a nested reference between user and authentication