Я разработал сервис аутентификации с использованием Spring Cloud Architecture. Мне нужны все права пользователя в классе PrincipleController, и поэтому я реализовал пользовательский метод в классе сущностей пользователей.
Существуют отношения между объектами User-Role, User-Permission и Role-Permission. Я хочу знать, что реализация пользовательского (после getAllPermissions ()) метода в классе сущности (я имею в виду реализацию уровня модели) является плохой практикой или нет?
package x.y.z.backend.auth.controller;
import x.y.z.backend.auth.model.*;
import x.y.z.backend.auth.service.PermissionService;
import x.y.z.backend.auth.service.PrincipalService;
import x.y.z.backend.auth.service.RoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.security.Principal;
import java.util.Set;
@RestController
@RequestMapping("/me")
public class PrincipalController {
public static final Logger LOG = LoggerFactory.getLogger(PrincipalController.class);
private RoleService roleService;
private PermissionService permissionService;
private PrincipalService principalService;
@Autowired
public PrincipalController(RoleService roleService, PermissionService permissionService, PrincipalService principalService) {
this.roleService = roleService;
this.permissionService = permissionService;
this.principalService = principalService;
}
public PrincipalController() {
}
@GetMapping
public CustomPrincipal principal(Principal principal) {
User user = principalService.findByEmail(principal.getName()).get();
Set<Permission> permissions = user.getAllPermissions();
OAuth2Authentication auth = (OAuth2Authentication) principal;
CustomPrincipal customPrincipal = new CustomPrincipal(user.getFirstName(), user.getLastName(), principal.getName(),
auth.getOAuth2Request(), auth.getUserAuthentication(), auth.getAuthorities(), auth.getDetails(), auth.isAuthenticated(),
auth.isClientOnly(), permissions, user.getTenant().getTenantName());
return customPrincipal;
}
@PutMapping
public User update(@Valid @RequestBody User user, BindingResult bindingResult, Principal principal) {
return principalService.update(user, bindingResult, principal);
}
@PutMapping(path = "/change_password")
public User updatePassword(@Valid @RequestBody UserPassword userPassword, BindingResult bindingResult, Principal principal) {
return principalService.updatePassword(userPassword, bindingResult, principal);
}
@GetMapping(path = "/roles")
public Set<Role> getRoles(Principal principal) {
String username = principal.getName();
return roleService.findByEmail(username);
}
@GetMapping(path = "/permissions")
public Set<Permission> getPermissions(Principal principal) {
String username = principal.getName();
return permissionService.findByEmail(username);
}
}
package x.y.z.backend.auth.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import static x.y.z.backend.auth.enums.Parameter.TENANT_SCHEMA_NAME;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(exclude = {"roles", "permissions", "tenant"})
@ToString(exclude = {"roles", "permissions", "tenant"})
@Entity(name = "users")
@Table(schema = TENANT_SCHEMA_NAME)
public class User implements UserDetails {
@Transient
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull(message = "First name could not be empty")
@Size(min = 2, max = 20, message = "First name must be between {min} and {max} characters long")
private String firstName;
@NotNull(message = "Last name could not be empty")
@Size(min = 2, max = 20, message = "Last name must be between {min} and {max} characters long")
private String lastName;
@Email(message = "Invalid e-mail address")
@NotNull(message = "E-mail could not be empty")
@Column(unique = true, nullable = false)
@Size(min = 5, max = 100, message = "E-mail must be between {min} and {max} characters long")
private String email;
@Getter(onMethod = @__(@JsonIgnore))
@Setter(onMethod = @__(@JsonProperty("password")))
@Column(length = 60)
private String password;
@NotNull
private boolean accountNonExpired;
@NotNull
private boolean accountNonLocked;
@NotNull
private boolean credentialsNonExpired;
@NotNull
private boolean enabled;
@Column(nullable = false)
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private LocalDateTime deletedAt;
@Getter(onMethod = @__(@JsonIgnore))
@Setter(onMethod = @__(@JsonProperty("roles")))
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(schema = TENANT_SCHEMA_NAME, name = "user_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<Role> roles = new HashSet<>(0);
@Getter(onMethod = @__(@JsonIgnore))
@Setter(onMethod = @__(@JsonProperty("permissions")))
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(schema = TENANT_SCHEMA_NAME, name = "user_permissions", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
private Set<Permission> permissions = new HashSet<>(0);
@Getter(onMethod = @__(@JsonIgnore))
@Setter(onMethod = @__(@JsonProperty("tenant")))
@ManyToOne(fetch = FetchType.EAGER)
@JoinTable(schema = TENANT_SCHEMA_NAME, name = "tenant_users", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "tenant_id", referencedColumnName = "id"))
private Tenant tenant;
public User(String firstName, String lastName, String email, String password, boolean accountNonExpired,
boolean accountNonLocked, boolean credentialsNonExpired, boolean enabled,
LocalDateTime createdAt, LocalDateTime updatedAt, LocalDateTime deletedAt, Set<Role> roles) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
this.accountNonExpired = accountNonExpired;
this.accountNonLocked = accountNonLocked;
this.credentialsNonExpired = credentialsNonExpired;
this.enabled = enabled;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
this.deletedAt = deletedAt;
this.roles = roles;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
grantedAuthorities.addAll(roles);
grantedAuthorities.addAll(permissions);
return grantedAuthorities;
}
public Set<Permission> getAllPermissions() {
Set<Permission> allPermissions = new HashSet<>();
allPermissions.addAll(this.permissions);
this.roles.forEach(role -> allPermissions.addAll(role.getPermissions()));
return allPermissions;
}
@Override
public String getUsername() {
return this.getEmail();
}
}