Ebyrdeu / spring_boot_library

0 stars 0 forks source link

#31 Added Auditable class and config file #32

Closed ajohnsson95 closed 8 months ago

ajohnsson95 commented 8 months ago

Related Issue(s)

31

Changes that still need to be implemented:

Authentication and security still needs to be implemented but waiting with that part until we have that set up.

Description

Auditable Config file and class added, aswell as message and user entity now extends Auditable

https://docs.spring.io/spring-data/jpa/reference/auditing.html https://mayankposts.medium.com/database-auditing-in-spring-boot-with-spring-security-context-and-spring-data-jpa-9215b43744bb

Ebyrdeu commented 8 months ago

It seems you've bricked some tests in MessageRepositoryTest. I refactored them, so for my PR, it's working. I think you need to wait for #33 to be merged with the main branch, and then merge the main branch with yours to see if it's fixed.

ajohnsson95 commented 8 months ago

It seems you've bricked some tests in MessageRepositoryTest. I refactored them, so for my PR, it's working. I think you need to wait for #33 to be merged with the main branch, and then merge the main branch with yours to see if it's fixed.

Great was looking in too it but haven't fixed anything so far we wait and see :)

Ebyrdeu commented 8 months ago

It's seems the main problem how Audit was implemented. I tried change your audit in several ways, but still for me, tests are just can't even compile.

Try this approach instead, maybe this one will work.

Ebyrdeu commented 8 months ago

Also have question regarding Audit why can't it be implemented direct to Entity instead to create separate class ? (Kinda not really sure what benefits it's gives)



@Entity
@Table(name = "messages")
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, name = "message_id")
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String body;

    @Column(name = "is_private", columnDefinition = "BOOLEAN DEFAULT FALSE")
    private boolean isPrivate;

    @CreationTimestamp
    private Instant date;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;

    @CreatedBy
    @Column(name = "created_by", updatable = false)
    private String createdBy;

    @CreatedDate
    @Column(name = "creation_date", updatable = false)
    private Instant creationDate;

    @LastModifiedBy
    @Column(name = "last_modified_by")
    private String lastModifiedBy;

    @LastModifiedDate
    @Column(name = "last_modified_date")
    private Instant lastModifiedDate;

    @Override
    public final boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;
        Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
        Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
        if (thisEffectiveClass != oEffectiveClass) return false;
        Message message = (Message) o;
        return id != null && Objects.equals(id, message.id);
    }

    @Override
    public final int hashCode() {
        return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
    }
}
ajohnsson95 commented 8 months ago

Also have question regarding Audit why can't it be implemented direct to Entity instead to create separate class ? (Kinda not really sure what benefits it's gives)

@Entity
@Table(name = "messages")
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, name = "message_id")
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String body;

    @Column(name = "is_private", columnDefinition = "BOOLEAN DEFAULT FALSE")
    private boolean isPrivate;

    @CreationTimestamp
    private Instant date;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;

    @CreatedBy
    @Column(name = "created_by", updatable = false)
    private String createdBy;

    @CreatedDate
    @Column(name = "creation_date", updatable = false)
    private Instant creationDate;

    @LastModifiedBy
    @Column(name = "last_modified_by")
    private String lastModifiedBy;

    @LastModifiedDate
    @Column(name = "last_modified_date")
    private Instant lastModifiedDate;

    @Override
    public final boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;
        Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
        Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
        if (thisEffectiveClass != oEffectiveClass) return false;
        Message message = (Message) o;
        return id != null && Objects.equals(id, message.id);
    }

    @Override
    public final int hashCode() {
        return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
    }
}

Also have question regarding Audit why can't it be implemented direct to Entity instead to create separate class ? (Kinda not really sure what benefits it's gives)

@Entity
@Table(name = "messages")
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, name = "message_id")
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String body;

    @Column(name = "is_private", columnDefinition = "BOOLEAN DEFAULT FALSE")
    private boolean isPrivate;

    @CreationTimestamp
    private Instant date;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;

    @CreatedBy
    @Column(name = "created_by", updatable = false)
    private String createdBy;

    @CreatedDate
    @Column(name = "creation_date", updatable = false)
    private Instant creationDate;

    @LastModifiedBy
    @Column(name = "last_modified_by")
    private String lastModifiedBy;

    @LastModifiedDate
    @Column(name = "last_modified_date")
    private Instant lastModifiedDate;

    @Override
    public final boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;
        Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
        Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
        if (thisEffectiveClass != oEffectiveClass) return false;
        Message message = (Message) o;
        return id != null && Objects.equals(id, message.id);
    }

    @Override
    public final int hashCode() {
        return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
    }
}

well since this project is not that big i guess putting it directly in entity classes is doable, Couple of reasons we used it in a separate class

Going to take a look at the link you sent see if we can get this to work :)

Ebyrdeu commented 8 months ago

Fixed, But you need still need do some work, such as update test (for example dto test will fail) Integration test also need to be updated in Data Verification, and do real user name implementation.

  1. src/main/java/dev/ebrydeu/spring_boot_library/audit/Auditable.java

    
    @Getter
    @Setter
    @MappedSuperclass
    @EntityListeners(AuditingEntityListener.class)
    public class Auditable {
    
    @CreatedBy
    @Column(name = "created_by", updatable = false)
    protected String  createdBy;
    
    @CreatedDate
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_date", updatable = false)
    protected Date createdDate;
    
    @LastModifiedBy
    @Column(name = "last_modified_by")
    protected String lastModifiedBy;
    
    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "last_modified_date")
    protected Instant lastModifiedDate;
    }
2. `src/main/java/dev/ebrydeu/spring_boot_library/audit/AuditAwareImpl.java`

```Java
public class AuditAwareImpl implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        // To be clear it just dummy data att the moment, you need find a way to implement username for this
        return Optional.of("Need to be username");
    }
}
  1. src/main/java/dev/ebrydeu/spring_boot_library/config/AuditorConfig.java
@Configuration
@EnableJpaAuditing
public class AuditorConfig {
    @Bean
    public AuditorAware<String> auditorProvider() {
        return new AuditAwareImpl();
    }
}
  1. Same for messages
@Entity
@Table(name = "users")
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class User extends Auditable {
ajohnsson95 commented 8 months ago

Implementing a real user will be done when we get our security up with a logged in user and possibly some authentication

sonarcloud[bot] commented 8 months ago

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
90.0% Coverage on New Code
0.0% Duplication on New Code

See analysis details on SonarCloud