How to get an Authenticated User's Details in Spring Security OAuth2 - spring

I am unable to extract the current logged in user in Spring Security OAuth2. My goal is to extract the user when the create event on ClientSuggestion entity is triggered and persist it to the database.
Employee.java
#Entity
#Table(name = "er_employee")
public class Employee implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "username", unique = true)
#NotNull
#Size(max = 10)
private String username;
#Column(name = "password_hash")
#NotNull
#Size(min = 8, max = 512)
private String password;
#Column(name = "email_verification_token")
#Size(max = 512)
private String emailVerificationToken;
#Column(name = "password_reset_token")
#Size(max = 512)
private String passwordResetToken;
#Column(name = "active")
#NotNull
private boolean active;
#Column(name = "is_deleted")
#NotNull
private boolean deleted;
#Column(name = "date_of_creation")
#Temporal(TemporalType.TIMESTAMP)
#NotNull
private Date dateOfCreation;
#OneToMany(mappedBy = "employee")
private List<ClientSuggestion> clientSuggestions;
//Constructors
//Getters ans setters
}
ClientSuggestion.java
#Entity
#Table(name = "er_suggestion")
public class ClientSuggestion implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "content", unique = true)
#NotNull
#Size(max = 200)
private String suggestion;
#ManyToOne
#JoinColumn(name = "employee_id")
private Employee employee;
//Constructors
//Getters ans setters
}
EmployeeRepository.java
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
ClientSuggestionRepository .java
public interface ClientSuggestionRepository extends CrudRepository<ClientSuggestion, Long> {
}
The event handler
#Component
#RepositoryEventHandler(ClientSuggestion.class)
public class ClientSuggestionEventHandler {
Employee employee= (Employee ) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
#HandleBeforeCreate
public void handleClientSuggestionBeforeCreate(ClientSuggestion cs) {
cs.setDeleted(false);
cs.setActive(true);
cs.setPasswordResetToken(Encryptor.generateHash(cs.getPassword, 512));
cs.setEmployee(employee);
}
}
The bean, ClientSuggestionEventHandler, is registered in a configuration class. When I tried running the project, NullPointerException exception is thrown. I wish to find out how to get the current logged employee.
I'm new to Spring Security OAuth2. Thanks.

In Employee.java implement org.springframework.security.core.userdetails.UserDetails class
Employee.java
#Entity
#Table(name = "er_employee")
public class Employee implements Serializable, UserDetails {
And then use Employee employee= (Employee) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

Related

OneToOne CascadeType in spring data jpa

I use OneToOne in the spring data JPA and I want to delete a record from the Address table without touching the user. But I can't.
If I remove User, in this case Address is removed, that's good.
But how can you delete an Address without touching the User?
https://github.com/myTestPercon/TestCascade
User.Java
#Entity
#Table(name = "user", schema = "testCascade")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private Address address;
// Getter and Setter ...
}
Address.java
#Entity
#Table(name = "address", schema = "testCascade")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
#OneToOne
#MapsId
#JoinColumn(name = "id")
private User user;
// Getter and Setter ...
}
DeleteController.java
#Controller
public class DeleteController {
#Autowired
ServiceJpa serviceJpa;
#GetMapping(value = "/deleteAddressById")
public String deleteAddressById () {
serviceJpa.deleteAddressById(4L);
return "redirect:/home";
}
}
You got your mapping wrong thats all is the problem .
try the below and see
User.java
#Entity
#Table(name = "user", schema = "testCascade")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="foriegn key column in user table for address example.. address_id")
private Address address;
// Getter and Setter ...
}
Address.java
#Entity
#Table(name = "address", schema = "testCascade")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
//name of the address variable in your user class
#OneToOne(mappedBy="address",
cascade={CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
private User user;
// Getter and Setter ...
}
In order to solve this problem, you need to read the hibernate Documentation Hibernate Example 162, Example 163, Example 164.
And also I recommend to look at this is Using #PrimaryKeyJoinColumn annotation in spring data jpa
This helped me in solving this problem.
And also you need to specify the parameter orphanRemoval = true
User.java
#Entity(name = "User")
#Table(name = "user", schema = "testother")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private Address address;
public void addAddress(Address address) {
address.setUser( this );
this.address = address;
}
public void removeAddress() {
if ( address != null ) {
address.setUser( null );
this.address = null;
}
}
// Getter and Setter
}
Address.java
#Entity(name = "Address")
#Table(name = "address", schema = "testother")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
#OneToOne
#MapsId
#JoinColumn(name = "id")
private User user;
// Getter and Setter
}
DeleteController .java
#Controller
public class DeleteController {
#Autowired
ServiceJpa serviceJpa;
#GetMapping(value = "/deleteUser")
public String deleteUser () {
User user = serviceJpa.findUserById(2L).get();
user.removeAddress();
serviceJpa.saveUser(user);
return "/deleteUser";
}
}
Or make a custom SQL query.
#Repository
public interface DeleteAddress extends JpaRepository<Address, Long> {
#Modifying
#Query("delete from Address b where b.id=:id")
void deleteBooks(#Param("id") Long id);
}
public class Address {
#Id
private Long id;
#MapsId
#JoinColumn(name = "id")
private User user;
}
Rename #JoinColumn(name = "id") to #JoinColumn(name = "user_id")
You can't say that the column that will point to user will be the id of the Address

Spring data jpa CRUDRepository/ JPArepository saveall can not get id (non primary key)

I am fetching data from FB marketing API and trying to save in DB. I am able to save data in the DB using CrudRepository or JpaRepository -> saveall method, but when trying to fetch the id in response of saveall, I am getting id as null. When I see in the h2-console, able to see the auto increment value after the completion of transaction.
Note: id is not used as primary key #Id. accountId is used as primary key.
Model:
#Entity
#Table(name = "accounts")
#Data
#ToString(onlyExplicitlyIncluded = true)
public class Account implements Serializable{
#JsonIgnore
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(columnDefinition = "integer auto_increment",insertable = false)
private Long id;
#JsonProperty("account_id")
#Column(name = "account_id")
#Id
private String accountId;
#Column(name = "account_status")
private int accountStatus;
#JsonProperty("timezone_id")
#Column(name = "timezone_id")
private int timezoneId;
private int timezoneOffsetUtc;
private String currency;
#Column(name = "timezone_name")
#JsonProperty("timezone_name")
private String timezoneName;
private String name;
#Column(name = "created_on",nullable = false, updatable = false)
#CreationTimestamp
private LocalDateTime createdOn;
#Column(name = "updated_on")
#UpdateTimestamp
private LocalDateTime updatedOn;
}
Repository:
#Repository()
public interface AccountRepository extends CrudRepository<Account, String> {
}
Tried with JpaRepository<Account, Long> too and flush after saving..but still getting id null in return list response of saveall()
Service:
#Service
public class AccountsService {
#Autowired
private AccountRepository repository;
#Override
#Transactional
public List<Account> saveAll(List<Account> accounts) {
//in case of JpaRepository
List<Account> savedAccounts= repository.saveAll(accounts);
repository.flush();
return savedAccounts;
//in case of CrudRepository
return (List<Account>)repository.saveAll(accounts);
}
}
when executing this
//accountsList received from FB API
List<Account> savedList=iAccountsService.saveAll(accountsList);
savedList.get(0).getId() **//this is coming as null**
Any sort of help is appreciated.
In your entity class :
Use this #GeneratedValue(strategy = GenerationType.IDENTITY)
public class Account implements Serializable{
#JsonIgnore
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false, insertable = false, updatable = false)
private Long id;
}

Auto populate created_date, last_modified_date, created_by and last_modified_by in entity : Hibernate with JPA

I am new to Hibernate and JPA. I have several entities, each of which contains following four columns:
1. created_by
2. last_modified_by
3. created_date
4. last_modified_date
I would like these columns to get auto-populated while saving the associated entity.
Two sample entities are as follows:
Entity 1:
#Entity
#Table(name = "my_entity1")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity1 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
Entity 2:
#Entity
#Table(name = "my_entity2")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity2 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "description")
private String description;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
In this context, I have gone through following posts: How to autogenerate created or modified timestamp field?, How can you make a created_at column generate the creation date-time automatically like an ID automatically gets created?.
I am getting how to capture the dates fields but I cannot understand how to capture created_by and last_modified_by.
Auditing Author using AuditorAware and Spring Security...
To tell JPA about currently logged in user we will need to provide an
implementation of AuditorAware and override getCurrentAuditor()
method. And inside getCurrentAuditor() we will need to fetch currently
logged in user.
Like this:
public class AuditorAwareImpl implements AuditorAware<String> {
#Override
public String getCurrentAuditor() {
return "TestUser";
// Can use Spring Security to return currently logged in user
// return ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()
}
}
Now enable jpa auditing by using #EnableJpaAuditing
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class JpaConfig {
#Bean
public AuditorAware<String> auditorAware() {
return new AuditorAwareImpl();
}
}
Look at this to get more details....

Spring JPA: How to insert data to join many tables with #ManytoMany relationship

I'm starting to learn Spring Java Framework . I created some Enity to join 2 Model like my Database. And now I want to insert to Join Table by JpaRepository. What i have to do?
This is my Code (Please fix help me me if something is not right)
Model Users_RoomId to define Composite Primary Key
#Embeddable
public class Users_RoomId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "ID_room", nullable = false)
private String idRoom;
#Column(name = "user_id", nullable = false)
private int idUser;
}
Model Users_Room to join 2 Model Users and Room
#Entity
#Table(name ="bookroom")
public class Users_Room {
#EmbeddedId
private Users_RoomId usersroomId;
#ManyToOne
#MapsId("idRoom")
private Room room;
#ManyToOne
#MapsId("idUser")
private Users users;
#Column(name = "Bookday")
private String bookday;
Model Users and Room I used annotation #OneToMany
Model Users
#Entity
#Table(name = "users")
public class Users implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id", nullable = false)
private int id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "email")
private String email;
#Column(name = "pass")
private String pass;
#Column(name = "role")
private int role;
#OneToMany(mappedBy = "users")
private List<Users_Room> user;
Model Room
#Entity
#Table(name ="room")
public class Room implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID_room", nullable = false)
private String id;
#Column(name = "name_room", nullable = false)
private String name;
#Column(name = "Description")
private String describe;
#ManyToOne
#JoinColumn(name = "ID_status")
private Status status;
#Column(name = "room_image")
private String image;
public Room() {
super();
}
#ManyToOne
#JoinColumn(name = "ID_kind")
private KindRoom kind;
#OneToMany(mappedBy = "room")
private List<Users_Room> rooms;
This is my database
So I don't know how to insert a new bookroom with iduser,idroom and bookday with JPA repository.. It'necessary to write Query in JPARepository or We just need to use method save() to insert data
Thanks everyone
I had same problem and solved with following code. I used method save() to insert data. Following code is 'createRoom' method in 'RoomService.java'.
RoomService.java
private final RoomRepository roomRepository;
private final UserRoomRepository userRoomRepository;
private final UserRepository userRepository;
public RoomService(RoomRepository roomRepository, UserRoomRepository userRoomRepository, UserRepository userRepository) {
this.roomRepository = roomRepository;
this.userRoomRepository = userRoomRepository;
this.userRepository = userRepository;
}
#Transactional
public RoomDto createRoom(Long userId, Long chattingUserId) {
Room room = roomRepository.save(new Room());
room.addUserRoom(userRepository.findById(userId).orElseThrow(()->new NoSuchElementException("No User")));
room.addUserRoom(userRepository.findById(chattingUserId).orElseThrow(()->new NoSuchElementException("No User")));
userRoomRepository.save(new UserRoom(userRepository.findById(userId).orElseThrow(()->new NoSuchElementException("No User")),room));
userRoomRepository.save(new UserRoom(userRepository.findById(chattingUserId).orElseThrow(()->new NoSuchElementException("No User")),room));
RoomDto roomDto = RoomDto.of(room);
return roomDto;
}

How to get specific inheritant entity using generic dao and service layer

Working on my spring mvc project I face following issu:
I have UnitAppUser, VStanAppUser and RjuAppUser entity classes which extend User entity. User entity stores some general informations. Rest of inheritant entities stores the references to the particular entities (UnitAppUser has a field Unit type, VStanAppUser has a VStan type so on).
Here is my parent User entity
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#Table(name="app_user")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6628717324563396999L;
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#NotEmpty
#Column(name="SSO_ID", unique=true, nullable=false)
private String ssoId;
#NotEmpty
#Column(name="PASSWORD", nullable=false)
private String password;
#NotEmpty
#Column(name="FIRST_NAME", nullable=false)
private String firstName;
#NotEmpty
#Column(name="LAST_NAME", nullable=false)
private String lastName;
#NotEmpty
#Column(name="EMAIL", nullable=false)
private String email;
}
Here's my child classes:
#Entity
#Table(name = "unit_app_user")
public class UnitAppUser extends User implements Serializable {
#JoinColumn(name = "UNITWORK", referencedColumnName = "ID")
#ManyToOne(optional = false)
private UnitDepart unitdepart;
public UnitDepart getWorkat() {
return unitdepart;
}
public void setWorkat(UnitDepart unitdepart) {
this.unitdepart = unitdepart;
}
}
#Entity
#Table(name="rju_app_user")
public class RjuAppUser extends User implements Serializable{
#JoinColumn(name = "workrju", referencedColumnName = "id")
#ManyToOne(optional = false)
private Rju rju;
public Rju getWorkat() {
return rju;
}
public void setWorkat(Rju rju) {
this.rju = rju;
}
}
and finally my VStan entity:
#Entity
#Table(name="vstan_app_user")
public class VstanAppUser extends User implements Serializable{
#JoinColumn(name = "WORKSTATION", referencedColumnName = "kod")
#ManyToOne(optional = false)
private Vstan vstan;
public Vstan getWorkat() {
return vstan;
}
public void setWorkat(Vstan vstan) {
this.vstan = vstan;
}
}
How to write generic dao and service to get specific entity?
As a result I should have something like this
userService.findBySSOId("somessoId").getWorkat() //should return UnitDepart, Rju or VStan

Resources