melkir
melkir

Reputation: 405

Default value for user role - Spring security

I'm trying to add a default role value when the user register in Spring Security.

I have two models "User" and "Role" linked with a many-to-many relation.

User.java

@NotEmpty
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Role> roles = new HashSet<>();

Role.java

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(length=15, unique=true, nullable=false)
private String role = RoleType.USER.getRole();

data.sql

INSERT INTO ROLE(role) VALUES ('USER');
INSERT INTO USER(email,password) VALUES ('[email protected]','user');
INSERT INTO USER_ROLES(user_id, roles_id) VALUES (1,1);

The idea here is to use the role_id to set the user role, but i would prefer use a String for lisibility. Something like this in one or two lines

INSERT INTO USER_ROLES(user_id, roles) VALUES (1, "ADMIN");
INSERT INTO USER_ROLES(user_id, roles) VALUES (1, "DBA");

Also when I'm trying to create a user from JAVA I need to use the role dao in order to retrieve the corresponding id and I would like to set a new user to "ROLE_USER" by default.

UserDBTest.java

@Before
public void setUp() {
    User user = new User();
    user.setEmail("[email protected]");
    user.setPassword("password");
    user.addRole(roleRepository.findOne(1L)); //detached entity passed to persist
    user = userRepository.save(user);
}

Upvotes: 0

Views: 2201

Answers (2)

holmis83
holmis83

Reputation: 16644

You can write the SQL like this:

INSERT INTO USER_ROLES(user_id, roles)
  VALUES (1, (SELECT id FROM roles WHERE role='ADMIN'));

The JPA error you are experiencing is because you don't run in a transaction. For example, if you use TestNG you can let your test class extend AbstractTransactionalTestNGSpringContextTests, and it will work.

Update: If the extra database lookup is a concern, an option would be to store the role name directly in USER_ROLES table, User.java would then look like:

@ElementCollection
@Enumerated(EnumType.STRING)
private Set<RoleType> roles;

Upvotes: 1

isah
isah

Reputation: 5351

If you want to store Role as a String, then you can represent it as enum in Java and drop the table altogether. Then, you may represent the relationship as @OneToMany between User and UserRole.

In UserRole.java

@ManyToOne
@JoinColumn(name = "user_id")
User user;

@Column(name = "role")
@Enumerated(EnumType.STRING) // this tells JPA to store enum name in db
Role role; //role enum 

Upvotes: 0

Related Questions