У меня проблемы с моим пользовательским классом, точнее с grantedAuthority
, похоже, и я не могу найти решение для него.
Вот мой пользовательский класс, который реализует userdetails
:
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.example.demo.domain.security.Authority;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@Entity
@Table(name="user")
public class User implements UserDetails, Serializable{
private static final long serialVersionUID = 784154L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
@JsonIgnore
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Account> accounts;
@JsonIgnore
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Transaction> transactions;
private String firstName;
private String lastName;
@Column(name="region")
private String region;
private String email;
private String username;
private String password;
private boolean status = true;
@ManyToOne(fetch=FetchType.EAGER,cascade={CascadeType.ALL})
private Role role;
public User() {
}
@JsonCreator
public User( @JsonProperty Long userId, @JsonProperty Set<Account> accounts,
@JsonProperty Set<Transaction> transactions, @JsonProperty String firstname,
@JsonProperty String lastname, @JsonProperty String region,
@JsonProperty String email, @JsonProperty String username, @JsonProperty String password,
@JsonProperty boolean status, @JsonProperty Role role) {
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean getStatus(){
return this.status;
}
public void setStatus(boolean enabled) {
this.status = enabled;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<Account> getAccounts() {
return accounts;
}
public void setAccounts(Set<Account> accounts) {
this.accounts = accounts;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public Set<Transaction> getTransactions() {
return transactions;
}
public void setTransactions(Set<Transaction> transactions) {
this.transactions = transactions;
}
@JsonDeserialize
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
Set<GrantedAuthority> authorities = new HashSet<>();
authorities.add( new Authority(role.getType()));
return authorities;
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isEnabled() {
return status;
}
}
Это мой класс пользовательского контроллера:
package com.example.demo.controller;
import java.security.Principal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.server.PathParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.config.SecurityConfig;
import com.example.demo.config.SecurityUtility;
import com.example.demo.entities.Role;
import com.example.demo.entities.User;
import com.example.demo.enumerates.UserRole;
import com.example.demo.repositories.RoleRepo;
import com.example.demo.services.UserService;
import com.example.demo.utility.MailConstructor;
@RestController
//@CrossOrigin(origins = "*", allowedHeaders = "*")
@CrossOrigin("*")
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userS;
@Autowired
private RoleRepo roleRepository;
@GetMapping("/list")
public List<User> getAllUsers(){
return userS.findAll();
}
@GetMapping("/role/list")
public List<Role> getRoleList(){
return userS.findRoles();
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable(value = "id") Long User_id) {
User User = userS.findOne(User_id);
return ResponseEntity.ok().body(User);
}
@PutMapping("/Users/{id}")
public ResponseEntity<User> updateUser(@PathVariable(value = "id") Long User_id, @RequestBody User UserDetails){
User User = userS.findOne(User_id);
User.setFirstName(UserDetails.getFirstName());
final User updatedUser = userS.save(User);
return ResponseEntity.ok(updatedUser);
}
@DeleteMapping("/Users/{id}")
public Map<String, Boolean> deleteUser(@PathVariable(value = "id") Long User_id){
User User = userS.findOne(User_id);
userS.delete(User);
Map<String, Boolean> response = new HashMap<>();
response.put("deleted", Boolean.TRUE);
return response;
}
@PutMapping("/updateUser/{idR}")
public ResponseEntity userUpdate(
@RequestBody User user,
@PathVariable("idR") Long idR
)throws Exception{
long id = user.getUserId();
System.out.println("je suis ici");
String username = user.getUsername();
String region = null;
boolean status = user.getStatus();
System.out.println(status);
user = userS.findById(id);
if(userS.findByUsername(username) != null){
if(userS.findByUsername(username).getUserId() != user.getUserId()){
return new ResponseEntity("Username not found!", HttpStatus.BAD_REQUEST);
}
}
user.setRegion(region);
if(status==true)
user.setStatus(true);
else
user.setStatus(false);
Optional<Role> Optrole= roleRepository.findById(idR);
Role role = Optrole.get();
System.out.println(idR);
userS.addRoleToUser(username, role.getType());
userS.save(user);
return new ResponseEntity("User updated successfully!", HttpStatus.OK);
}
@PostMapping("/updateUserInfo")
public ResponseEntity profileInfo(
@RequestBody HashMap<String, Object> mapper
)throws Exception{
int id = (Integer) mapper.get("id");
String email = (String) mapper.get("email");
String region = (String) mapper.get("userRegion");
String username = (String) mapper.get("username");
String firstName = (String) mapper.get("firstName");
String lastName = (String) mapper.get("lastName");
String newPassword = (String) mapper.get("newPassword");
String currentPassword = (String) mapper.get("currentPassword");
User currentUser = userS.findById(Long.valueOf(id));
if(currentUser == null){
return new ResponseEntity("User not found!", HttpStatus.BAD_REQUEST);
}
if(userS.findByEmail(email) != null){
if(userS.findByEmail(email).getUserId() != currentUser.getUserId()){
return new ResponseEntity("Email not found!", HttpStatus.BAD_REQUEST);
}
}
if(userS.findByUsername(username) != null){
if(userS.findByUsername(username).getUserId() != currentUser.getUserId()){
return new ResponseEntity("Username not found!", HttpStatus.BAD_REQUEST);
}
}
SecurityConfig securityConfig = new SecurityConfig();
if(newPassword != null && !newPassword.isEmpty() && !newPassword.equals("")){
BCryptPasswordEncoder passwordEncoder = SecurityUtility.passwordEncoder();
String dbPassword = currentUser.getPassword();
if(currentPassword.equals(dbPassword)){
currentUser.setPassword(passwordEncoder.encode(newPassword));
}else{
return new ResponseEntity("Current Password Incorrect!", HttpStatus.BAD_REQUEST);
}
}
currentUser.setFirstName(firstName);
currentUser.setLastName(lastName);
currentUser.setEmail(email);
currentUser.setUsername(username);
currentUser.setRegion(region);
userS.save(currentUser);
//System.out.println("username "+ currentUser.getUsername());
return new ResponseEntity("User updated successfully!", HttpStatus.OK);
}
@GetMapping("/getCurrentUser")
@ResponseBody
public User getCurrentUser(Principal principal){
//String name = SecurityContextHolder.getContext().getAuthentication().getName();
User user = userS.findByUsername(principal.getName());
System.out.println(user.getFirstName());
return user;
}
@Autowired
private MailConstructor mailConstructor;
@Autowired
private JavaMailSender mailSender;
@PostMapping("/newUser/{idR}")
public ResponseEntity newUserPost(
@RequestBody User user,
@PathVariable(name = "idR", required = false) Long idR
)throws Exception{
// long id = user.getUserId();
String username = user.getFirstName()+user.getLastName();
user.setUsername(username);
String userEmail = user.getEmail();
System.out.println("id role is "+idR);
Optional <Role> Optrole= roleRepository.findById(idR);
Role role = Optrole.get();
Role r = role;
user.setRole(r);
UserRole roleName = r.getType();
System.out.println(roleName);
//mapper.forEach((key, value) ->
System.out.println(user.getUsername());
if(userS.findByUsername(username) != null){
return new ResponseEntity("username Exists", HttpStatus.BAD_REQUEST);
}
if(userS.findByEmail(userEmail) != null){
return new ResponseEntity("Email Exists", HttpStatus.BAD_REQUEST);
}
String password = SecurityUtility.randomPassword();
String encryptedPassword = SecurityUtility.passwordEncoder().encode(password);
user.setPassword(encryptedPassword);
userS.save(user);
userS.addRoleToUser(username,roleName);
SimpleMailMessage email = mailConstructor.constructNewUserEmail(user, password);
mailSender.send(email);
return new ResponseEntity("User Added Successfully!", HttpStatus.OK);
}
@PostMapping("/forgetPassword")
public ResponseEntity forgetPasswordPost(
HttpServletRequest request,
@RequestBody HashMap<String, String> mapper) throws Exception{
User user = userS.findByEmail(mapper.get("email"));
if (user == null){
return new ResponseEntity ("Email not found ", HttpStatus.BAD_REQUEST);
}
String password = SecurityUtility.randomPassword();
String encryptedPassword = SecurityUtility.passwordEncoder().encode(password);
user.setPassword(encryptedPassword);
userS.save(user);
SimpleMailMessage newEmail = mailConstructor.constructForgetPasswordEmail(user, password);
mailSender.send(newEmail);
return new ResponseEntity ("Email sent!", HttpStatus.OK);
}
}
Я пытаюсь обновить своего пользователя, чтобы установить новый регион, и получаю эту ошибку:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.security.core.GrantedAuthority` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (PushbackInputStream); line: 1, column: 359] (through reference chain: com.example.demo.entities.Account["user"]->com.example.demo.entities.User["authorities"]->java.util.ArrayList[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1611)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1077)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:285)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:535)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:451)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1310)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:331)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:371)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3487)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:269)
и это мой интерфейс, где я вызываю свои функции из бэкенда
import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import { Observable } from 'rxjs';
import {User} from '../models/user';
@Injectable({
providedIn: 'root'
})
export class UserService {
private baseUrl = 'http://localhost:8888/user';
user : User = new User();
constructor(private http: HttpClient) { }
getUser(id: number): Observable<any> {
const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
return this.http.get(`${this.baseUrl}/${id}`,{headers});
}
// tslint:disable-next-line:ban-types
createUser(user: User,roleid : number): Observable<Object> {
const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
console.log(localStorage.getItem('token'))
return this.http.post(`${this.baseUrl}/newUser/${roleid}`, user,{headers});
}
getUserList(): Observable<any> {
const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
return this.http.get(`${this.baseUrl}/list`,{headers});
}
// tslint:disable-next-line:ban-types
updateUser( user: User, id:number): Observable<Object> {
const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
return this.http.put(`${this.baseUrl}/updateUser/${id}`, user,{headers});
}
deleteUser(id: number): Observable<any> {
const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
return this.http.delete(`${this.baseUrl}/${id}`, { headers});
}
// @ts-ignore
getRoleList(): Observable<any>{
const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
return this.http.get(`${this.baseUrl}/role/list`,{headers});
}
}
, а вот мой component.ts для обновления входа пользователя в систему
import { Component, OnInit } from '@angular/core';
import {UserService} from '../../services/user.service';
import {User} from '../../models/user';
import {LoginService} from '../../services/login.service';
import {Role} from '../../models/role';
import {ActivatedRoute, Router} from '@angular/router';
@Component({
selector: 'app-user-region',
templateUrl: './user-region.component.html',
styleUrls: ['./user-region.component.scss']
})
export class UserRegionComponent implements OnInit {
user : User ;
role : Role;
constructor(private userService : UserService, private loginService : LoginService,
private route: ActivatedRoute,private router: Router) { }
updateUser(){
this.userService.updateUser(this.user,this.user.role.role_id).subscribe(
res => {
console.log('updated');
},
err => {
console.log(err);
}
);
}
goNext(){
this.router.navigate(['/user/pinCode'])
}
ngOnInit(): void {
this.loginService.getCurrentUser().subscribe(
res =>{
this.user = res
console.log(this.user)},
err => {
console.log(err);
}
);
}
}
Как Вы можете видеть в ошибке, что что-то не так в моем заявлении властей. Я думаю, что пробовал пользовательский конструктор пользовательского десериализатора, ничего не получилось. Любая помощь приветствуется.