Implement custom record searches
Create record overview projection Add today search with scoped principal Add sample data for records
This commit is contained in:
parent
3310062138
commit
9f8fd0af1e
@ -0,0 +1,26 @@
|
||||
package de.hft.geotime.controllers;
|
||||
|
||||
import de.hft.geotime.repositories.RecordRepository;
|
||||
import de.hft.geotime.repositories.TimetrackUserRepository;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class RecordController {
|
||||
|
||||
private final RecordRepository recordRepository;
|
||||
private final TimetrackUserRepository userRepository;
|
||||
private final ProjectionFactory projectionFactory;
|
||||
|
||||
public RecordController(RecordRepository recordRepository, TimetrackUserRepository userRepository, ProjectionFactory projectionFactory) {
|
||||
this.recordRepository = recordRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.projectionFactory = projectionFactory;
|
||||
}
|
||||
|
||||
@GetMapping("/track")
|
||||
public void track() {
|
||||
//"/track?accountid=bla" → start/stop recording for that account
|
||||
}
|
||||
}
|
@ -5,8 +5,8 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.Duration;
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@ -17,11 +17,20 @@ public class TimeRecord {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
|
||||
@ManyToOne
|
||||
private TimetrackAccount account;
|
||||
private Date startdate;
|
||||
private Date enddate;
|
||||
private Duration time;
|
||||
|
||||
@Column(columnDefinition = "TIMESTAMP")
|
||||
private LocalDateTime startdate;
|
||||
|
||||
@Column(columnDefinition = "TIMESTAMP")
|
||||
private LocalDateTime enddate;
|
||||
|
||||
private RecordType type;
|
||||
|
||||
public long getDuration() {
|
||||
return startdate.until(enddate, ChronoUnit.MINUTES);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
package de.hft.geotime.entities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonBackReference;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@ -18,7 +20,12 @@ public class TimetrackAccount {
|
||||
private double revenue;
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
@JsonBackReference
|
||||
@ManyToOne
|
||||
private TimetrackUser user;
|
||||
|
||||
@OneToMany(mappedBy = "account")
|
||||
private List<TimeRecord> records;
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.hft.geotime.entities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonManagedReference;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -28,10 +29,11 @@ public class TimetrackUser {
|
||||
|
||||
private String lastname;
|
||||
|
||||
@OneToOne(fetch = FetchType.EAGER)
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
private Role role;
|
||||
|
||||
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@JsonManagedReference
|
||||
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
|
||||
private List<TimetrackAccount> accounts;
|
||||
|
||||
@ManyToOne
|
||||
|
@ -0,0 +1,27 @@
|
||||
package de.hft.geotime.entities.projections;
|
||||
|
||||
import de.hft.geotime.entities.TimeRecord;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.rest.core.config.Projection;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Projection(name = "overview", types = TimeRecord.class)
|
||||
public interface RecordOverviewProjection {
|
||||
|
||||
LocalDateTime getStartdate();
|
||||
|
||||
LocalDateTime getEnddate();
|
||||
|
||||
long getDuration();
|
||||
|
||||
@Value("#{target.type.name()}")
|
||||
String getType();
|
||||
|
||||
@Value("#{target.account.name}")
|
||||
String getAccount();
|
||||
|
||||
@Value("#{target.account.user.username}")
|
||||
String getUsername();
|
||||
|
||||
}
|
@ -1,11 +1,15 @@
|
||||
package de.hft.geotime.repositories;
|
||||
|
||||
import de.hft.geotime.entities.TimeRecord;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.List;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@RepositoryRestResource(
|
||||
path = "records",
|
||||
@ -14,4 +18,34 @@ import java.util.List;
|
||||
)
|
||||
public interface RecordRepository extends PagingAndSortingRepository<TimeRecord, Long> {
|
||||
|
||||
@RestResource(rel = "allBetween", path = "allBetween")
|
||||
Page<TimeRecord> findAllByStartdateBetween(
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime start,
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime end,
|
||||
Pageable pageable
|
||||
);
|
||||
|
||||
@RestResource(rel = "allBetweenAndUser", path = "allBetweenAndUser")
|
||||
Page<TimeRecord> findAllByStartdateBetweenAndAccount_User_Username(
|
||||
LocalDateTime start,
|
||||
LocalDateTime end,
|
||||
String username,
|
||||
Pageable pageable
|
||||
);
|
||||
|
||||
@RestResource(rel = "allForUser", path = "allForUser")
|
||||
Page<TimeRecord> findAllByAccount_User_Username(String username, Pageable pageable);
|
||||
|
||||
@RestResource(rel = "allForUserAndAccount", path = "allForUserAndAccount")
|
||||
Page<TimeRecord> findAllByAccount_User_UsernameAndAccount_Name(String username, String account, Pageable pageable);
|
||||
|
||||
@RestResource(rel = "allFrom", path = "allFrom")
|
||||
Page<TimeRecord> findAllByStartdateGreaterThanEqual(
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime date,
|
||||
Pageable pageable
|
||||
);
|
||||
|
||||
@Query("SELECT record from TimeRecord record where record.account.user.username = :#{principal} AND record.startdate > (current_date-1)")
|
||||
Page<TimeRecord> today(Pageable pageable);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package de.hft.geotime.security;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.spel.spi.EvaluationContextExtension;
|
||||
|
||||
@Configuration
|
||||
class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
EvaluationContextExtension securityExtension() {
|
||||
return new SecurityEvaluationContextExtension();
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package de.hft.geotime.security;
|
||||
|
||||
import org.springframework.data.spel.spi.EvaluationContextExtension;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
public class SecurityEvaluationContextExtension implements EvaluationContextExtension {
|
||||
|
||||
@Override
|
||||
public String getExtensionId() {
|
||||
return "security";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityExpressionRoot getRootObject() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
return new SecurityExpressionRoot(authentication) {
|
||||
};
|
||||
}
|
||||
}
|
@ -20,8 +20,15 @@ INSERT INTO timetrack_user (id, firstname, lastname, password, username, role_id
|
||||
(3, 'Tim', 'Zieger' ,'$2y$10$pYGHZhoaelceImO7aIN4nOkWJBp.oqNGFYaRAonHkYF4u9ljqPelC', 'ziti', 1, 1),
|
||||
(4, 'Simon', 'Kellner' ,'$2y$10$Puzm/Nr/Dyq3nQxlkXGIfubS5JPtXJSOf2e6mrQ6HhVYQN9YiQQsC', 'kesi', 1, 1);
|
||||
|
||||
INSERT INTO timetrack_account (description, `name`, revenue, user_id) VALUES
|
||||
('Gleitzeit Marcel', 'Primary Marcel', 16.0, 1),
|
||||
('Festgeld Marcel', 'Secondary Marcel', 25.0, 1);
|
||||
INSERT INTO timetrack_account (id, description, `name`, revenue, user_id) VALUES
|
||||
(1, 'Gleitzeit Marcel', 'Primary', 16.0, 1),
|
||||
(2, 'Festgeld Marcel', 'Secondary', 25.0, 1),
|
||||
(3, 'Festgeld Tim', 'Primary', 25.0, 3);
|
||||
|
||||
INSERT INTO time_record (id, enddate, startdate, `type`, account_id) VALUES
|
||||
(1, '2020-05-10 16:00:00', '2020-05-10 12:00:00', 0, 1),
|
||||
(2, '2020-05-09 16:00:00', '2020-05-09 12:00:00', 1, 1),
|
||||
(3, '2020-05-20 16:00:00', '2020-05-20 00:00:00', 1, 2),
|
||||
(4, '2020-05-11 16:00:00', '2020-05-11 12:00:00', 1, 3);
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=1;
|
Loading…
Reference in New Issue
Block a user