Compare commits
2 Commits
d298a5f1f4
...
615c1c761c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
615c1c761c | ||
|
|
3a25996280 |
@ -10,15 +10,14 @@
|
|||||||
<version>0.0.1</version>
|
<version>0.0.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>ru.mskobaro</groupId>
|
|
||||||
<artifactId>server</artifactId>
|
<artifactId>server</artifactId>
|
||||||
<version>0.0.1</version>
|
<version>0.0.1</version>
|
||||||
|
|
||||||
<name>TDMS::SERVER</name>
|
<name>TDMS::SERVER</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>23</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<maven.compiler.target>23</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<lombok.version>1.18.34</lombok.version>
|
<lombok.version>1.18.34</lombok.version>
|
||||||
</properties>
|
</properties>
|
||||||
@ -127,6 +126,8 @@
|
|||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
</path>
|
</path>
|
||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
|
<source>23</source>
|
||||||
|
<target>23</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@ -15,7 +15,7 @@ public class TdmsApplication {
|
|||||||
Thread.currentThread().setName("spring-bootstrapper");
|
Thread.currentThread().setName("spring-bootstrapper");
|
||||||
ConfigurableApplicationContext ctx = SpringApplication.run(TdmsApplication.class, args);
|
ConfigurableApplicationContext ctx = SpringApplication.run(TdmsApplication.class, args);
|
||||||
Environment environment = ctx.getEnvironment();
|
Environment environment = ctx.getEnvironment();
|
||||||
log.info("Static files location: {}", environment.getProperty("spring.web.resources.static-locations"));
|
log.info("Server listening on port: {}", environment.getProperty("server.port"));
|
||||||
ctx.start();
|
ctx.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
import org.hibernate.annotations.UpdateTimestamp;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
@Getter
|
||||||
|
public class AuditInfo {
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(name = "created_at")
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
@UpdateTimestamp
|
||||||
|
@Column(name = "updated_at")
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "commission_member_data")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class CommissionMemberData {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
@JoinColumn(name = "partic_id", referencedColumnName = "id")
|
||||||
|
private Participant participant;
|
||||||
|
|
||||||
|
private String workPlace;
|
||||||
|
private String workPosition;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "defense")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Defense {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
@JoinTable(
|
||||||
|
name = "defense_commission",
|
||||||
|
joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"),
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "commission_member_data_id", referencedColumnName = "id"))
|
||||||
|
private List<CommissionMemberData> commissionMembers;
|
||||||
|
|
||||||
|
private LocalDate defenseDate;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "defense")
|
||||||
|
private List<Group> groups;
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
@JoinTable(
|
||||||
|
name = "defense_best_student_works",
|
||||||
|
joinColumns = @JoinColumn(name = "defense_id", referencedColumnName = "id"),
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "student_data_id", referencedColumnName = "id"))
|
||||||
|
private List<StudentData> bestWorks;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "diploma_topic")
|
||||||
|
public class DiplomaTopic {
|
||||||
|
@Id
|
||||||
|
@Column(name = "id")
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "teacher_id")
|
||||||
|
private TeacherData teacher;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "direction_of_preparation_id")
|
||||||
|
private DirectionOfPreparation directionOfPreparation;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "direction_of_preparation")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class DirectionOfPreparation {
|
||||||
|
@Id
|
||||||
|
@Column(name = "id")
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "directionOfPreparation")
|
||||||
|
private List<DiplomaTopic> diplomaTopic;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "`group`")
|
||||||
|
public class Group {
|
||||||
|
@Id
|
||||||
|
@Column(name = "id")
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "group")
|
||||||
|
private List<StudentData> students = new ArrayList<>();
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "direction_of_preparation_id")
|
||||||
|
private DirectionOfPreparation directionOfPreparation;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "defense_id")
|
||||||
|
private Defense defense;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
import io.micrometer.common.util.StringUtils;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "participant")
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Participant {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
private String middleName;
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
private String numberPhone;
|
||||||
|
|
||||||
|
@OneToOne(mappedBy = "participant")
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
private boolean deleted;
|
||||||
|
|
||||||
|
@ManyToMany(fetch = FetchType.EAGER)
|
||||||
|
@JoinTable(
|
||||||
|
name = "participant_role",
|
||||||
|
joinColumns = @JoinColumn(name = "partic_id", referencedColumnName = "id"),
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
|
||||||
|
private List<Role> roles;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
public String getFullName() {
|
||||||
|
return Stream.of(lastName, firstName, middleName)
|
||||||
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.collect(Collectors.joining(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
public String getShortName() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
if (StringUtils.isNotBlank(lastName)) {
|
||||||
|
builder.append(lastName);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(firstName)) {
|
||||||
|
builder.append(" ").append(firstName.charAt(0)).append(".");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(middleName)) {
|
||||||
|
builder.append(" ").append(middleName.charAt(0)).append(".");
|
||||||
|
}
|
||||||
|
return builder.toString().trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,11 @@
|
|||||||
package ru.mskobaro.tdms.domain.entity;
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.*;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
|
|
||||||
@ -18,6 +15,7 @@ import org.springframework.security.core.GrantedAuthority;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Table(name = "`role`")
|
@Table(name = "`role`")
|
||||||
|
@EqualsAndHashCode(of = "id")
|
||||||
public class Role implements GrantedAuthority {
|
public class Role implements GrantedAuthority {
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "id")
|
@Column(name = "id")
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
||||||
|
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString(exclude = "group")
|
||||||
|
@Entity
|
||||||
|
@Table(name = "student_data")
|
||||||
|
public class StudentData {
|
||||||
|
@Id
|
||||||
|
@Column(name = "id")
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
@JoinColumn(name = "partic_id")
|
||||||
|
private Participant participant;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "group_id")
|
||||||
|
private Group group;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "study_form_id")
|
||||||
|
private StudyForm form;
|
||||||
|
|
||||||
|
private Integer protectionOrder;
|
||||||
|
private Integer protectionDay;
|
||||||
|
|
||||||
|
private Integer markComment;
|
||||||
|
private Integer markPractice;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "curator_id")
|
||||||
|
private TeacherData curator;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "diploma_topic_id")
|
||||||
|
private DiplomaTopic diplomaTopic;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
@ -1,23 +1,21 @@
|
|||||||
package ru.mskobaro.tdms.domain.entity;
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "study_form")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@ToString
|
public class StudyForm {
|
||||||
@Entity
|
|
||||||
@Table(name = "diploma_topic")
|
|
||||||
public class DiplomaTopic {
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "id")
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(name = "name")
|
@Column(name = "name")
|
||||||
private String name;
|
private String name;
|
||||||
}
|
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.JdbcTypeCode;
|
||||||
|
import org.hibernate.type.SqlTypes;
|
||||||
|
import ru.mskobaro.tdms.business.taskfields.TaskFields;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "task")
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Task {
|
||||||
|
public enum Type {
|
||||||
|
DIPLOMA_TOPIC_AGREEMENT,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Status {
|
||||||
|
WAIT_FOR_TOPIC_AGREEMENT,
|
||||||
|
DONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
@JdbcTypeCode(SqlTypes.JSON)
|
||||||
|
private TaskFields fields;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "teacher_data")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TeacherData {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
@JoinColumn(name = "participant_id", referencedColumnName = "id")
|
||||||
|
private Participant participant;
|
||||||
|
|
||||||
|
private String degree;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.domain.entity;
|
package ru.mskobaro.tdms.business.entity;
|
||||||
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
@ -6,13 +6,10 @@ import lombok.EqualsAndHashCode;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.hibernate.annotations.CreationTimestamp;
|
|
||||||
import org.hibernate.annotations.UpdateTimestamp;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -32,33 +29,26 @@ public class User implements UserDetails {
|
|||||||
private String login;
|
private String login;
|
||||||
@Column(name = "password")
|
@Column(name = "password")
|
||||||
private String password;
|
private String password;
|
||||||
@Column(name = "full_name")
|
@OneToOne
|
||||||
private String fullName;
|
@JoinColumn(name = "partic_id")
|
||||||
@Column(name = "email")
|
private Participant participant;
|
||||||
private String email;
|
|
||||||
@Column(name = "number_phone")
|
@Embedded
|
||||||
private String numberPhone;
|
private AuditInfo auditInfo;
|
||||||
@Column(name = "created_at")
|
|
||||||
@CreationTimestamp
|
|
||||||
private ZonedDateTime createdAt;
|
|
||||||
@Column(name = "updated_at")
|
|
||||||
@UpdateTimestamp
|
|
||||||
private ZonedDateTime updatedAt;
|
|
||||||
@ManyToMany
|
|
||||||
@JoinTable(
|
|
||||||
name = "user_role",
|
|
||||||
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
|
|
||||||
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
|
|
||||||
private List<Role> roles;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
return roles.stream()
|
return participant.getRoles().stream()
|
||||||
.map(Role::getAuthority)
|
.map(Role::getAuthority)
|
||||||
.map(SimpleGrantedAuthority::new)
|
.map(SimpleGrantedAuthority::new)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return !participant.isDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return login;
|
return login;
|
||||||
@ -1,12 +1,16 @@
|
|||||||
package ru.mskobaro.tdms.domain.exception;
|
package ru.mskobaro.tdms.business.exception;
|
||||||
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.ErrorDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||||
|
|
||||||
public class AccessDeniedException extends BusinessException {
|
public class AccessDeniedException extends BusinessException {
|
||||||
public AccessDeniedException() {
|
public AccessDeniedException() {
|
||||||
super("Access denied");
|
super("Access denied");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AccessDeniedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ErrorDTO.ErrorCode getErrorCode() {
|
public ErrorDTO.ErrorCode getErrorCode() {
|
||||||
return ErrorDTO.ErrorCode.ACCESS_DENIED;
|
return ErrorDTO.ErrorCode.ACCESS_DENIED;
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package ru.mskobaro.tdms.domain.exception;
|
package ru.mskobaro.tdms.business.exception;
|
||||||
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.ErrorDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||||
|
|
||||||
public class BusinessException extends RuntimeException {
|
public class BusinessException extends RuntimeException {
|
||||||
public BusinessException(String message) {
|
public BusinessException(String message) {
|
||||||
@ -1,18 +1,18 @@
|
|||||||
package ru.mskobaro.tdms.domain.exception;
|
package ru.mskobaro.tdms.business.exception;
|
||||||
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.ErrorDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||||
|
|
||||||
public class NotFoundException extends BusinessException {
|
public class NotFoundException extends BusinessException {
|
||||||
public NotFoundException(Class<?> entityClass, Object id) {
|
public NotFoundException(Class<?> entityClass, Object id) {
|
||||||
super(entityClass.getSimpleName() + " с идентификатором " + id + " не наеден");
|
super(entityClass.getSimpleName() + " с идентификатором " + id + " не существует");
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotFoundException(Class<?> entityClass) {
|
public NotFoundException(Class<?> entityClass) {
|
||||||
super(entityClass.getSimpleName() + " не найден");
|
super(entityClass.getSimpleName() + " не существует");
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotFoundException() {
|
public NotFoundException() {
|
||||||
super("Не найдено");
|
super("Не существует");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void throwIfNull(Object object) {
|
public static void throwIfNull(Object object) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.domain.service;
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
@ -6,10 +6,14 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.session.SessionRegistry;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import static org.springframework.security.web.context.HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AuthenticationService {
|
public class AuthenticationService {
|
||||||
@ -17,25 +21,41 @@ public class AuthenticationService {
|
|||||||
private HttpServletRequest request;
|
private HttpServletRequest request;
|
||||||
@Autowired
|
@Autowired
|
||||||
private AuthenticationManager authenticationManager;
|
private AuthenticationManager authenticationManager;
|
||||||
|
@Autowired
|
||||||
|
private SessionRegistry sessionRegistry;
|
||||||
|
|
||||||
public void logout() {
|
public void logout() {
|
||||||
log.info("Logging out user: {}", SecurityContextHolder.getContext().getAuthentication().getName());
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
if (authentication == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String username = authentication.getName();
|
||||||
|
|
||||||
HttpSession session = request.getSession(false);
|
HttpSession session = request.getSession(false);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
session.invalidate();
|
session.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
log.info("User logged out");
|
|
||||||
|
log.info("User {} logged out", username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logout(String username) {
|
||||||
|
sessionRegistry.getAllSessions(username, false).forEach(session -> {
|
||||||
|
log.info("Invalidating session for user {}: {}", username, session.getSessionId());
|
||||||
|
session.expireNow();
|
||||||
|
sessionRegistry.removeSessionInformation(session.getSessionId());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void login(String username, String password) {
|
public void login(String username, String password) {
|
||||||
log.info("Logging in user: {}, ip: {}", username, request.getRemoteAddr());
|
|
||||||
|
|
||||||
var token = new UsernamePasswordAuthenticationToken(username, password);
|
var token = new UsernamePasswordAuthenticationToken(username, password);
|
||||||
var authenticated = authenticationManager.authenticate(token);
|
var authenticated = authenticationManager.authenticate(token);
|
||||||
SecurityContextHolder.getContext().setAuthentication(authenticated);
|
SecurityContextHolder.getContext().setAuthentication(authenticated);
|
||||||
|
request.getSession().setAttribute(SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
|
||||||
log.info("User {} logged in", username);
|
log.info("User {} logged in, ip: {}", username, request.getRemoteAddr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import ru.mskobaro.tdms.integration.database.DefenceRepository;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.DefenceDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class DefenceService {
|
||||||
|
@Autowired
|
||||||
|
private DefenceRepository defenceRepository;
|
||||||
|
|
||||||
|
public List<DefenceDTO> getAllDefences() {
|
||||||
|
return defenceRepository.findAll().stream().map(DefenceDTO::from).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||||
|
import ru.mskobaro.tdms.business.entity.TeacherData;
|
||||||
|
import ru.mskobaro.tdms.integration.database.DiplomaTopicRepository;
|
||||||
|
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
||||||
|
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.DiplomaTopicDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class DiplomaTopicService {
|
||||||
|
@Autowired
|
||||||
|
private DiplomaTopicRepository diplomaTopicRepository;
|
||||||
|
@Autowired
|
||||||
|
private TeacherDataRepository teacherDataRepository;
|
||||||
|
@Autowired
|
||||||
|
private PreparationDirectionRepository preparationDirectionRepository;
|
||||||
|
|
||||||
|
public List<DiplomaTopic> findAll() {
|
||||||
|
return diplomaTopicRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(DiplomaTopicDTO diplomaTopicDTO) {
|
||||||
|
boolean isEdit = diplomaTopicDTO.getId() != null;
|
||||||
|
DiplomaTopic diplomaTopic;
|
||||||
|
if (isEdit) {
|
||||||
|
diplomaTopic = diplomaTopicRepository.findByIdThrow(diplomaTopicDTO.getId());
|
||||||
|
} else {
|
||||||
|
diplomaTopic = new DiplomaTopic();
|
||||||
|
}
|
||||||
|
|
||||||
|
diplomaTopic.setName(diplomaTopicDTO.getName());
|
||||||
|
if (diplomaTopicDTO.getTeacher() != null) {
|
||||||
|
TeacherData teacherData = teacherDataRepository.findByIdThrow(diplomaTopicDTO.getTeacher().getId());
|
||||||
|
diplomaTopic.setTeacher(teacherData);
|
||||||
|
}
|
||||||
|
if (diplomaTopicDTO.getPreparationDirection() != null) {
|
||||||
|
DirectionOfPreparation directionOfPreparation = preparationDirectionRepository.findByIdThrow(diplomaTopicDTO.getPreparationDirection().getId());
|
||||||
|
diplomaTopic.setDirectionOfPreparation(directionOfPreparation);
|
||||||
|
}
|
||||||
|
|
||||||
|
diplomaTopicRepository.save(diplomaTopic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DiplomaTopic> findAllForStudent(Long studentId) {
|
||||||
|
return diplomaTopicRepository.findAllForStudentId(studentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Group;
|
||||||
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
|
import ru.mskobaro.tdms.business.exception.BusinessException;
|
||||||
|
import ru.mskobaro.tdms.integration.database.GroupRepository;
|
||||||
|
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
||||||
|
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.StudentDataDTO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
@Slf4j
|
||||||
|
public class GroupService {
|
||||||
|
@Autowired
|
||||||
|
private GroupRepository groupRepository;
|
||||||
|
@Autowired
|
||||||
|
private RoleService roleService;
|
||||||
|
@Autowired
|
||||||
|
private StudentDataRepository studentDataRepository;
|
||||||
|
@Autowired
|
||||||
|
private PreparationDirectionRepository preparationDirectionRepository;
|
||||||
|
|
||||||
|
public Collection<GroupDTO> getAllGroups() {
|
||||||
|
List<Group> groups = groupRepository.findAll();
|
||||||
|
return groups.stream().map(g -> GroupDTO.from(g, true)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(@Valid GroupDTO groupDTO) {
|
||||||
|
boolean editMode = groupDTO.getId() != null;
|
||||||
|
log.info("Saving group: {}. Edit?: {}", groupDTO, editMode);
|
||||||
|
if (!editMode && groupRepository.existsByName(groupDTO.getName())) {
|
||||||
|
throw new BusinessException("Группа с именем " + groupDTO.getName() + " уже существует");
|
||||||
|
}
|
||||||
|
|
||||||
|
Group group = editMode ? groupRepository.findByIdThrow(groupDTO.getId()) : new Group();
|
||||||
|
group.setName(groupDTO.getName());
|
||||||
|
|
||||||
|
studentDataRepository.findAllByGroup_Id(group.getId()).forEach(s -> {
|
||||||
|
s.setGroup(null);
|
||||||
|
studentDataRepository.save(s);
|
||||||
|
});
|
||||||
|
group.getStudents().clear();
|
||||||
|
|
||||||
|
List<Long> studentIds = groupDTO.getStudents().stream().map(StudentDataDTO::getId).toList();
|
||||||
|
if (!CollectionUtils.isEmpty(studentIds)) {
|
||||||
|
List<StudentData> students = studentDataRepository.findAllById(studentIds);
|
||||||
|
students.stream()
|
||||||
|
.filter(s -> roleService.isParticInAuthority(s.getParticipant(), RoleService.Authority.STUDENT))
|
||||||
|
.forEach(s -> {
|
||||||
|
group.getStudents().add(s);
|
||||||
|
s.setGroup(group);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupDTO.getPreparationDirection() != null) {
|
||||||
|
DirectionOfPreparation directionOfPreparation = preparationDirectionRepository.findByIdThrow(groupDTO.getPreparationDirection().getId());
|
||||||
|
group.setDirectionOfPreparation(directionOfPreparation);
|
||||||
|
}
|
||||||
|
|
||||||
|
groupRepository.save(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteGroup(Long groupId) {
|
||||||
|
groupRepository.deleteById(groupId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,220 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import io.micrometer.common.util.StringUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.collections4.ListUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import ru.mskobaro.tdms.business.entity.*;
|
||||||
|
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
||||||
|
import ru.mskobaro.tdms.business.exception.BusinessException;
|
||||||
|
import ru.mskobaro.tdms.integration.database.*;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantSaveDTO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
@Slf4j
|
||||||
|
public class ParticipantService {
|
||||||
|
@Autowired
|
||||||
|
private ParticipantRepository participantRepository;
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
@Autowired
|
||||||
|
private RoleService roleService;
|
||||||
|
@Autowired
|
||||||
|
private PasswordEncoder passwordEncoder;
|
||||||
|
@Autowired
|
||||||
|
private UserRepository userRepository;
|
||||||
|
@Autowired
|
||||||
|
private GroupRepository groupRepository;
|
||||||
|
@Autowired
|
||||||
|
private StudentDataRepository studentDataRepository;
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationService authenticationService;
|
||||||
|
@Autowired
|
||||||
|
private TeacherDataRepository teacherDataRepository;
|
||||||
|
|
||||||
|
public ParticipantService(ParticipantRepository participantRepository) {
|
||||||
|
this.participantRepository = participantRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Participant> getAllParticipants() {
|
||||||
|
return participantRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveParticipant(ParticipantSaveDTO participantSaveDTO) {
|
||||||
|
boolean editMode = participantSaveDTO.getId() != null;
|
||||||
|
log.info("Saving participant: {}. Edit: {}", participantSaveDTO, editMode);
|
||||||
|
Participant existingParticipant = null;
|
||||||
|
if (editMode)
|
||||||
|
existingParticipant = participantRepository.findByIdThrow(participantSaveDTO.getId());
|
||||||
|
persistParticipant(participantSaveDTO, existingParticipant, editMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistParticipant(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode) {
|
||||||
|
Participant participant = !editMode ? new Participant() : existingParticipant;
|
||||||
|
User callerUser = userService.getCallerUser();
|
||||||
|
if (callerUser == null)
|
||||||
|
throw new AccessDeniedException();
|
||||||
|
|
||||||
|
participant.setFirstName(participantSaveDTO.getFirstName());
|
||||||
|
participant.setLastName(participantSaveDTO.getLastName());
|
||||||
|
participant.setMiddleName(participantSaveDTO.getMiddleName());
|
||||||
|
participant.setNumberPhone(participantSaveDTO.getNumberPhone());
|
||||||
|
participant.setEmail(participantSaveDTO.getEmail());
|
||||||
|
|
||||||
|
List<Role> roles = persistRoles(participantSaveDTO, existingParticipant, editMode, callerUser, participant);
|
||||||
|
boolean credentialsChanged = persistUserData(participantSaveDTO, existingParticipant, editMode, participant);
|
||||||
|
persistStudentData(participantSaveDTO, existingParticipant, editMode, roles, participant);
|
||||||
|
persistTeacherData(participantSaveDTO, existingParticipant, editMode, roles, participant);
|
||||||
|
|
||||||
|
// TODO: notification task
|
||||||
|
Participant saved = participantRepository.save(participant);
|
||||||
|
log.info("Participant saved: {}", saved.getFullName());
|
||||||
|
|
||||||
|
if (credentialsChanged) {
|
||||||
|
log.info("User {} changed credentials, logging out", saved.getUser().getUsername());
|
||||||
|
authenticationService.logout(saved.getUser().getUsername());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Role> persistRoles(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, User callerUser, Participant participant) {
|
||||||
|
boolean isAdmin = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.ADMIN);
|
||||||
|
boolean isSecretary = roleService.isParticInAuthority(callerUser.getParticipant(), RoleService.Authority.SECRETARY);
|
||||||
|
boolean isOwner = existingParticipant != null && existingParticipant.getUser() != null
|
||||||
|
&& existingParticipant.getUser().getId().equals(callerUser.getId());
|
||||||
|
if (!isAdmin && !isSecretary && !isOwner)
|
||||||
|
throw new AccessDeniedException();
|
||||||
|
if (participantSaveDTO.getAuthorities() != null && participantSaveDTO.getAuthorities().contains(RoleService.Authority.ADMIN) && !isAdmin)
|
||||||
|
throw new AccessDeniedException("Недостаточно прав для назначения роли администратора");
|
||||||
|
|
||||||
|
List<Role> roles = participantSaveDTO.getAuthorities() != null
|
||||||
|
? participantSaveDTO.getAuthorities()
|
||||||
|
.stream()
|
||||||
|
.map(roleService::getRoleByAuthority)
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (editMode && isOwner && !isAdmin && roles != null && !ListUtils.isEqualList(roles, existingParticipant.getRoles())) {
|
||||||
|
throw new AccessDeniedException("Вы не можете изменять свои роли");
|
||||||
|
} else if (roles != null) {
|
||||||
|
participant.setRoles(roles);
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean persistUserData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, Participant participant) {
|
||||||
|
boolean credentialsChanged = false;
|
||||||
|
if (participantSaveDTO.getUserData() == null) {
|
||||||
|
return credentialsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
User user;
|
||||||
|
boolean wasBefore = false;
|
||||||
|
if (editMode && existingParticipant.getUser() != null) {
|
||||||
|
user = existingParticipant.getUser();
|
||||||
|
wasBefore = true;
|
||||||
|
} else {
|
||||||
|
user = new User();
|
||||||
|
}
|
||||||
|
|
||||||
|
String login = participantSaveDTO.getUserData().getLogin();
|
||||||
|
if (StringUtils.isNotBlank(login)) {
|
||||||
|
user.setLogin(login);
|
||||||
|
credentialsChanged = true;
|
||||||
|
} else if (!wasBefore) {
|
||||||
|
throw new BusinessException("Логин не может быть пустым");
|
||||||
|
}
|
||||||
|
|
||||||
|
String password = participantSaveDTO.getUserData().getPassword();
|
||||||
|
if (StringUtils.isNotBlank(password)) {
|
||||||
|
user.setPassword(passwordEncoder.encode(password));
|
||||||
|
credentialsChanged = true;
|
||||||
|
} else if (!wasBefore) {
|
||||||
|
throw new BusinessException("Пароль не может быть пустым");
|
||||||
|
}
|
||||||
|
|
||||||
|
user = userRepository.save(user);
|
||||||
|
participant.setUser(user);
|
||||||
|
user.setParticipant(participant);
|
||||||
|
return credentialsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistTeacherData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
|
||||||
|
boolean shouldPersistTeacherData = participantSaveDTO.getTeacherData() != null && roles != null
|
||||||
|
&& CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.TEACHER));
|
||||||
|
if (!shouldPersistTeacherData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean alreadyExists = editMode && teacherDataRepository.existsByParticipant_IdAndParticipant_DeletedFalse(existingParticipant.getId());
|
||||||
|
TeacherData teacherData;
|
||||||
|
if (alreadyExists) {
|
||||||
|
teacherData = teacherDataRepository.findByParticipant_Id(existingParticipant.getId());
|
||||||
|
} else {
|
||||||
|
teacherData = new TeacherData();
|
||||||
|
}
|
||||||
|
|
||||||
|
teacherData.setDegree(participantSaveDTO.getTeacherData().getDegree());
|
||||||
|
|
||||||
|
teacherData = teacherDataRepository.save(teacherData);
|
||||||
|
teacherData.setParticipant(participant);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persistStudentData(ParticipantSaveDTO participantSaveDTO, Participant existingParticipant, boolean editMode, List<Role> roles, Participant participant) {
|
||||||
|
boolean shouldPersistStudentData = participantSaveDTO.getStudentData() != null && roles != null
|
||||||
|
&& CollectionUtils.containsAny(roles, roleService.getRoleByAuthority(RoleService.Authority.STUDENT));
|
||||||
|
if (!shouldPersistStudentData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean alreadyExists = editMode && studentDataRepository.existsByParticipant_IdAndParticipant_DeletedFalse(existingParticipant.getId());
|
||||||
|
StudentData studentData;
|
||||||
|
if (alreadyExists) {
|
||||||
|
studentData = studentDataRepository.findStudentDataByParticipant_Id(existingParticipant.getId());
|
||||||
|
} else {
|
||||||
|
studentData = new StudentData();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (participantSaveDTO.getStudentData().getGroupId() != null) {
|
||||||
|
Group group = groupRepository.findByIdThrow(participantSaveDTO.getStudentData().getGroupId());
|
||||||
|
studentData.setGroup(group);
|
||||||
|
if (!group.getStudents().contains(studentData))
|
||||||
|
group.getStudents().add(studentData);
|
||||||
|
} else {
|
||||||
|
if (editMode) {
|
||||||
|
Group group = groupRepository.findByStudentsContaining(Collections.singletonList(studentData));
|
||||||
|
if (group != null)
|
||||||
|
group.getStudents().remove(studentData);
|
||||||
|
}
|
||||||
|
studentData.setGroup(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (participantSaveDTO.getStudentData().getCuratorId() != null) {
|
||||||
|
TeacherData teacherData = teacherDataRepository.findByIdThrow(participantSaveDTO.getStudentData().getCuratorId());
|
||||||
|
studentData.setCurator(teacherData);
|
||||||
|
} else {
|
||||||
|
studentData.setCurator(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
studentData = studentDataRepository.save(studentData);
|
||||||
|
studentData.setParticipant(participant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteParticipant(Long id) {
|
||||||
|
if (id == 1) {
|
||||||
|
throw new AccessDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Participant partic = participantRepository.findByIdThrow(id);
|
||||||
|
partic.setDeleted(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||||
|
import ru.mskobaro.tdms.integration.database.PreparationDirectionRepository;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.PreparationDirectionDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class PreparationDirectionService {
|
||||||
|
@Autowired
|
||||||
|
private PreparationDirectionRepository preparationDirectionRepository;
|
||||||
|
|
||||||
|
public List<DirectionOfPreparation> getAll() {
|
||||||
|
return preparationDirectionRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(PreparationDirectionDTO preparationDirectionDTO) {
|
||||||
|
boolean editMode = preparationDirectionDTO.getId() != null;
|
||||||
|
DirectionOfPreparation preparationDirection;
|
||||||
|
if (editMode) {
|
||||||
|
preparationDirection = preparationDirectionRepository.findByIdThrow(preparationDirectionDTO.getId());
|
||||||
|
} else {
|
||||||
|
preparationDirection = new DirectionOfPreparation();
|
||||||
|
}
|
||||||
|
preparationDirection.setName(preparationDirectionDTO.getName());
|
||||||
|
preparationDirection.setCode(preparationDirectionDTO.getCode());
|
||||||
|
preparationDirectionRepository.save(preparationDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
package ru.mskobaro.tdms.domain.service;
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -7,7 +9,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import ru.mskobaro.tdms.domain.entity.Role;
|
import ru.mskobaro.tdms.business.entity.Participant;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Role;
|
||||||
import ru.mskobaro.tdms.integration.database.RoleRepository;
|
import ru.mskobaro.tdms.integration.database.RoleRepository;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -17,17 +20,23 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class RoleService {
|
public class RoleService {
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Getter
|
|
||||||
public enum Authority {
|
public enum Authority {
|
||||||
ADMIN("ROLE_ADMINISTRATOR"),
|
ADMIN("ROLE_ADMINISTRATOR"),
|
||||||
COMM_MEMBER("ROLE_COMMISSION_MEMBER"),
|
COMM_MEMBER("ROLE_COMMISSION_MEMBER"),
|
||||||
TEACHER("ROLE_TEACHER"),
|
TEACHER("ROLE_TEACHER"),
|
||||||
|
PLAGIARISM_CHECKER("ROLE_PLAGIARISM_CHECKER"),
|
||||||
SECRETARY("ROLE_SECRETARY"),
|
SECRETARY("ROLE_SECRETARY"),
|
||||||
STUDENT("ROLE_STUDENT"),
|
STUDENT("ROLE_STUDENT"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String authority;
|
private final String authority;
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
public String getAuthority() {
|
||||||
|
return authority;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
public static Authority from(String authority) {
|
public static Authority from(String authority) {
|
||||||
for (Authority value : values()) {
|
for (Authority value : values()) {
|
||||||
if (value.getAuthority().equals(authority)) {
|
if (value.getAuthority().equals(authority)) {
|
||||||
@ -37,7 +46,8 @@ public class RoleService {
|
|||||||
throw new IllegalArgumentException("No such authority: " + authority);
|
throw new IllegalArgumentException("No such authority: " + authority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public transient Map<String, Role> roles;
|
|
||||||
|
private final Map<String, Role> roles = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RoleRepository roleRepository;
|
private RoleRepository roleRepository;
|
||||||
@ -45,7 +55,6 @@ public class RoleService {
|
|||||||
@PostConstruct
|
@PostConstruct
|
||||||
@Transactional
|
@Transactional
|
||||||
public void bootstrapRolesCache() {
|
public void bootstrapRolesCache() {
|
||||||
roles = new ConcurrentHashMap<>();
|
|
||||||
roleRepository.findAll().forEach(role -> roles.put(role.getAuthority(), role));
|
roleRepository.findAll().forEach(role -> roles.put(role.getAuthority(), role));
|
||||||
log.info("Roles initialized: {}", roles);
|
log.info("Roles initialized: {}", roles);
|
||||||
}
|
}
|
||||||
@ -53,4 +62,21 @@ public class RoleService {
|
|||||||
public Role getRoleByAuthority(Authority authority) {
|
public Role getRoleByAuthority(Authority authority) {
|
||||||
return roles.get(authority.getAuthority());
|
return roles.get(authority.getAuthority());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isParticInAuthority(Participant participant, Authority authority) {
|
||||||
|
return participant.getRoles().stream()
|
||||||
|
.anyMatch(role -> role.getAuthority().equals(authority.getAuthority()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isParticInAnyAuthority(Participant participant, Authority... authority) {
|
||||||
|
return participant.getRoles().stream()
|
||||||
|
.anyMatch(role -> {
|
||||||
|
for (Authority auth : authority) {
|
||||||
|
if (role.getAuthority().equals(auth.getAuthority())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Participant;
|
||||||
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
|
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||||
|
import ru.mskobaro.tdms.integration.database.UserRepository;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
@Slf4j
|
||||||
|
public class StudentDataService {
|
||||||
|
@Autowired
|
||||||
|
private StudentDataRepository studentDataRepository;
|
||||||
|
|
||||||
|
public StudentData getStudentByParticIdThrow(Long particId) {
|
||||||
|
return studentDataRepository.findStudentDataByParticipant_Id(particId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<StudentData> getAllStudentsWithoutGroup() {
|
||||||
|
return studentDataRepository.findByGroupIsNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.domain.service;
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Task;
|
||||||
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
|
import ru.mskobaro.tdms.business.taskfields.DiplomaTopicAgreementTaskFields;
|
||||||
|
import ru.mskobaro.tdms.business.taskfields.TaskFields;
|
||||||
|
import ru.mskobaro.tdms.integration.database.StudentDataRepository;
|
||||||
|
import ru.mskobaro.tdms.integration.database.TaskRepository;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.TaskController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class TaskService {
|
||||||
|
@Autowired
|
||||||
|
private TaskRepository taskRepository;
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
@Autowired
|
||||||
|
private StudentDataRepository studentDataRepository;
|
||||||
|
|
||||||
|
public void createTask(Task.Type type, Task.Status status, TaskFields taskFields) {
|
||||||
|
Task task = new Task();
|
||||||
|
task.setType(type);
|
||||||
|
task.setStatus(status);
|
||||||
|
task.setFields(taskFields);
|
||||||
|
taskRepository.save(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task findDiplomaTopicAgreementTaskCallerMaker() {
|
||||||
|
User user = userService.getCallerUser();
|
||||||
|
List<Task> diplomaTopicAgreementTaskByMakerId = taskRepository.findDiplomaTopicAgreementTaskByMakerId(
|
||||||
|
user.getParticipant().getId(), Task.Type.DIPLOMA_TOPIC_AGREEMENT
|
||||||
|
);
|
||||||
|
if (diplomaTopicAgreementTaskByMakerId.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diplomaTopicAgreementTaskByMakerId.size() > 1) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return diplomaTopicAgreementTaskByMakerId.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createDiplomaAgreementTask(TaskController.DiplomaTopicAgreementDTO diplomaTopicAgreementDTO) {
|
||||||
|
DiplomaTopicAgreementTaskFields taskFields = new DiplomaTopicAgreementTaskFields();
|
||||||
|
User user = userService.getCallerUser();
|
||||||
|
StudentData studentData = studentDataRepository.findStudentDataByParticipant_Id(user.getParticipant().getId());
|
||||||
|
|
||||||
|
taskFields.setCheckerParticipantId(user.getParticipant().getId());
|
||||||
|
taskFields.setDiplomaTopicId(diplomaTopicAgreementDTO.getDiplomaTopicId());
|
||||||
|
taskFields.setDiplomaTopicName(diplomaTopicAgreementDTO.getDiplomaTopicName());
|
||||||
|
taskFields.setCheckerParticipantId(studentData.getCurator().getId());
|
||||||
|
|
||||||
|
createTask(Task.Type.DIPLOMA_TOPIC_AGREEMENT, Task.Status.WAIT_FOR_TOPIC_AGREEMENT, taskFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import ru.mskobaro.tdms.business.entity.TeacherData;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
import ru.mskobaro.tdms.integration.database.TeacherDataRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class TeacherDataService {
|
||||||
|
@Autowired
|
||||||
|
private TeacherDataRepository teacherDataRepository;
|
||||||
|
|
||||||
|
public List<TeacherData> findAll() {
|
||||||
|
return teacherDataRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TeacherData getTeacherDataByParticipantId(Long participantId) {
|
||||||
|
TeacherData teacher = teacherDataRepository.findByParticipant_Id(participantId);
|
||||||
|
if (teacher == null) {
|
||||||
|
throw new NotFoundException(TeacherData.class, participantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return teacher;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package ru.mskobaro.tdms.business.service;
|
||||||
|
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
|
import ru.mskobaro.tdms.integration.database.UserRepository;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
@Slf4j
|
||||||
|
public class UserService implements UserDetailsService {
|
||||||
|
@Autowired
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||||
|
log.debug("Loading user with username: {}", username);
|
||||||
|
User user = userRepository.findUserByLogin(username).orElseThrow(
|
||||||
|
() -> new UsernameNotFoundException("User with login " + username + " not found"));
|
||||||
|
log.debug("User with login {} loaded", username);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<UserDTO> getAllUsers() {
|
||||||
|
log.debug("Loading all users");
|
||||||
|
List<UserDTO> users = userRepository.findAll().stream()
|
||||||
|
.map(UserDTO::fromEntity)
|
||||||
|
.toList();
|
||||||
|
log.info("{} users loaded", users.size());
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getCallerUser() {
|
||||||
|
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
if (!(principal instanceof User)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (User) principal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package ru.mskobaro.tdms.business.taskfields;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class DiplomaTopicAgreementTaskFields extends MakerCheckerTaskFields {
|
||||||
|
private String diplomaTopicName;
|
||||||
|
private Long diplomaTopicId;
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package ru.mskobaro.tdms.business.taskfields;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MakerCheckerTaskFields extends MakerTaskFields {
|
||||||
|
private Long checkerParticipantId;
|
||||||
|
private LocalDateTime approvedAt;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package ru.mskobaro.tdms.business.taskfields;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MakerTaskFields extends TaskFields {
|
||||||
|
private Long makerParticipantId;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package ru.mskobaro.tdms.business.taskfields;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class TaskFields {
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
}
|
||||||
@ -1,35 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.domain.entity;
|
|
||||||
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.hibernate.annotations.CreationTimestamp;
|
|
||||||
import org.hibernate.annotations.UpdateTimestamp;
|
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@Entity
|
|
||||||
@Table(name = "`group`")
|
|
||||||
public class Group {
|
|
||||||
@Id
|
|
||||||
@Column(name = "id")
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
@Column(name = "name")
|
|
||||||
private String name;
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "curator_teacher_id")
|
|
||||||
private Teacher groupCurator;
|
|
||||||
@Column(name = "created_at")
|
|
||||||
@CreationTimestamp
|
|
||||||
private ZonedDateTime createdAt;
|
|
||||||
@Column(name = "updated_at")
|
|
||||||
@UpdateTimestamp
|
|
||||||
private ZonedDateTime updatedAt;
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.domain.entity;
|
|
||||||
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.hibernate.annotations.CreationTimestamp;
|
|
||||||
import org.hibernate.annotations.UpdateTimestamp;
|
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@Entity
|
|
||||||
@Table(name = "student")
|
|
||||||
public class Student {
|
|
||||||
@Id
|
|
||||||
@Column(name = "id")
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
@Column(name = "form")
|
|
||||||
private Boolean form;
|
|
||||||
@Column(name = "protection_order")
|
|
||||||
private Integer protectionOrder;
|
|
||||||
@Column(name = "magistracy")
|
|
||||||
private String magistracy;
|
|
||||||
@Column(name = "digital_format_present")
|
|
||||||
private Boolean digitalFormatPresent;
|
|
||||||
@Column(name = "mark_comment")
|
|
||||||
private Integer markComment;
|
|
||||||
@Column(name = "mark_practice")
|
|
||||||
private Integer markPractice;
|
|
||||||
@Column(name = "predefence_comment")
|
|
||||||
private String predefenceComment;
|
|
||||||
@Column(name = "normal_control")
|
|
||||||
private String normalControl;
|
|
||||||
@Column(name = "anti_plagiarism")
|
|
||||||
private Integer antiPlagiarism;
|
|
||||||
@Column(name = "note")
|
|
||||||
private String note;
|
|
||||||
@Column(name = "record_book_returned")
|
|
||||||
private Boolean recordBookReturned;
|
|
||||||
@Column(name = "work")
|
|
||||||
private String work;
|
|
||||||
@OneToOne
|
|
||||||
@JoinColumn(name = "user_id")
|
|
||||||
private User user;
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "diploma_topic_id")
|
|
||||||
private DiplomaTopic diplomaTopic;
|
|
||||||
// Научный руководитель
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "adviser_teacher_id")
|
|
||||||
private Teacher adviser;
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "group_id")
|
|
||||||
private Group group;
|
|
||||||
|
|
||||||
@Column(name = "created_at")
|
|
||||||
@CreationTimestamp
|
|
||||||
private ZonedDateTime createdAt;
|
|
||||||
@Column(name = "updated_at")
|
|
||||||
@UpdateTimestamp
|
|
||||||
private ZonedDateTime updatedAt;
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.domain.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.hibernate.annotations.CreationTimestamp;
|
|
||||||
import org.hibernate.annotations.UpdateTimestamp;
|
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@Entity
|
|
||||||
@Table(name = "teacher")
|
|
||||||
public class Teacher {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
@OneToOne
|
|
||||||
@JoinColumn(name = "user_id")
|
|
||||||
private User user;
|
|
||||||
@OneToMany(mappedBy = "groupCurator")
|
|
||||||
private List<Group> curatingGroups;
|
|
||||||
@OneToMany(mappedBy = "adviser")
|
|
||||||
private List<Student> advisingStudents;
|
|
||||||
|
|
||||||
@Column(name = "created_at")
|
|
||||||
@CreationTimestamp
|
|
||||||
private ZonedDateTime createdAt;
|
|
||||||
@Column(name = "updated_at")
|
|
||||||
@UpdateTimestamp
|
|
||||||
private ZonedDateTime updatedAt;
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.domain.service;
|
|
||||||
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional
|
|
||||||
public class DiplomaTopicService {
|
|
||||||
}
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.domain.service;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.Group;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.User;
|
|
||||||
import ru.mskobaro.tdms.domain.exception.BusinessException;
|
|
||||||
import ru.mskobaro.tdms.integration.database.GroupRepository;
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.GroupDTO;
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.GroupEditDTO;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional
|
|
||||||
@Slf4j
|
|
||||||
public class GroupService {
|
|
||||||
@Autowired
|
|
||||||
private GroupRepository groupRepository;
|
|
||||||
@Autowired
|
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
public Collection<GroupDTO> getAllGroups() {
|
|
||||||
log.info("Getting all groups");
|
|
||||||
List<Group> groups = groupRepository.findAll();
|
|
||||||
User callerUser = userService.getCallerUser();
|
|
||||||
|
|
||||||
List<GroupDTO> result = groups.stream().map(group -> {
|
|
||||||
GroupDTO groupDTO = new GroupDTO();
|
|
||||||
groupDTO.setName(group.getName());
|
|
||||||
groupDTO.setId(group.getId());
|
|
||||||
|
|
||||||
if (group.getGroupCurator() != null) {
|
|
||||||
groupDTO.setCuratorName(group.getGroupCurator().getUser().getFullName());
|
|
||||||
if (callerUser != null) {
|
|
||||||
groupDTO.setIAmCurator(group.getGroupCurator().getUser().equals(callerUser));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return groupDTO;
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
log.info("Found {} groups", result.size());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createGroup(String groupName) {
|
|
||||||
log.info("Creating group with name {}", groupName);
|
|
||||||
if (groupRepository.existsByName(groupName)) {
|
|
||||||
throw new BusinessException("Группа с именем " + groupName + " уже существует");
|
|
||||||
}
|
|
||||||
|
|
||||||
Group group = new Group();
|
|
||||||
group.setName(groupName);
|
|
||||||
Group saved = groupRepository.save(group);
|
|
||||||
log.info("Group saved: {}", saved);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void editGroup(GroupEditDTO groupEditDTO) {
|
|
||||||
log.info("Updating group with dto: {}", groupEditDTO);
|
|
||||||
Group group = groupRepository.findByIdThrow(groupEditDTO.getId());
|
|
||||||
group.setName(groupEditDTO.getName());
|
|
||||||
log.info("Group updated: {}", group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.domain.service;
|
|
||||||
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.Student;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.User;
|
|
||||||
import ru.mskobaro.tdms.domain.exception.BusinessException;
|
|
||||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
|
||||||
import ru.mskobaro.tdms.integration.database.StudentRepository;
|
|
||||||
import ru.mskobaro.tdms.integration.database.UserRepository;
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.StudentDTO;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional
|
|
||||||
@Slf4j
|
|
||||||
public class StudentService {
|
|
||||||
@Autowired
|
|
||||||
private StudentRepository studentRepository;
|
|
||||||
@Autowired
|
|
||||||
private UserService userService;
|
|
||||||
@Autowired
|
|
||||||
private UserRepository userRepository;
|
|
||||||
|
|
||||||
public Student getCallerStudentThrow() {
|
|
||||||
userService.sureCallerInAnyRole(RoleService.Authority.STUDENT);
|
|
||||||
return studentRepository.findByUser(userService.getCallerUser());
|
|
||||||
}
|
|
||||||
|
|
||||||
public StudentDTO getCallerStudentDtoThrow() {
|
|
||||||
Student callerStudent = getCallerStudentThrow();
|
|
||||||
if (callerStudent == null) {
|
|
||||||
throw new BusinessException("Вызывающий пользователь является студентом, но ассоциированный с ним студент не найден");
|
|
||||||
}
|
|
||||||
|
|
||||||
return StudentDTO.from(callerStudent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StudentDTO getStudentByUserIdThrow(Long id) {
|
|
||||||
User callerUser = userService.getCallerUser();
|
|
||||||
if (callerUser == null) {
|
|
||||||
throw new NotFoundException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callerUser.getId().equals(id)) {
|
|
||||||
return getCallerStudentDtoThrow();
|
|
||||||
} else if (userService.isCallerInRole(RoleService.Authority.ADMIN, RoleService.Authority.TEACHER, RoleService.Authority.SECRETARY)) {
|
|
||||||
User user = userRepository.findByIdThrow(id);
|
|
||||||
Student student = studentRepository.findByUser(user);
|
|
||||||
NotFoundException.throwIfNull(student, Student.class, user.getId());
|
|
||||||
return StudentDTO.from(student);
|
|
||||||
} else {
|
|
||||||
throw new NotFoundException(Student.class, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,181 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.domain.service;
|
|
||||||
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.*;
|
|
||||||
import ru.mskobaro.tdms.domain.exception.AccessDeniedException;
|
|
||||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
|
||||||
import ru.mskobaro.tdms.integration.database.GroupRepository;
|
|
||||||
import ru.mskobaro.tdms.integration.database.StudentRepository;
|
|
||||||
import ru.mskobaro.tdms.integration.database.TeacherRepository;
|
|
||||||
import ru.mskobaro.tdms.integration.database.UserRepository;
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.RegistrationDTO;
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.UserDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional
|
|
||||||
@Slf4j
|
|
||||||
public class UserService implements UserDetailsService {
|
|
||||||
@Autowired
|
|
||||||
private UserRepository userRepository;
|
|
||||||
@Autowired
|
|
||||||
private GroupRepository groupRepository;
|
|
||||||
@Autowired
|
|
||||||
private StudentRepository studentRepository;
|
|
||||||
@Autowired
|
|
||||||
private RoleService roleService;
|
|
||||||
@Autowired
|
|
||||||
private PasswordEncoder passwordEncoder;
|
|
||||||
@Autowired
|
|
||||||
private TeacherRepository teacherRepository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User loadUserByUsername(String username) throws UsernameNotFoundException {
|
|
||||||
log.debug("Loading user with username: {}", username);
|
|
||||||
User user = userRepository.findUserByLogin(username).orElseThrow(
|
|
||||||
() -> new UsernameNotFoundException("User with login " + username + " not found"));
|
|
||||||
log.debug("User with login {} loaded", username);
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<UserDTO> getAllUsers() {
|
|
||||||
log.debug("Loading all users");
|
|
||||||
List<UserDTO> users = userRepository.findAll().stream()
|
|
||||||
.map(UserDTO::from)
|
|
||||||
.toList();
|
|
||||||
log.info("{} users loaded", users.size());
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerUser(RegistrationDTO registrationDTO) {
|
|
||||||
log.info("Registering user: {}", registrationDTO);
|
|
||||||
|
|
||||||
User user = transientUser(registrationDTO);
|
|
||||||
fillRoles(user, registrationDTO);
|
|
||||||
userRepository.save(user);
|
|
||||||
|
|
||||||
if (userInAnyRole(user, RoleService.Authority.STUDENT)) {
|
|
||||||
sureCallerInAnyRole(RoleService.Authority.ADMIN, RoleService.Authority.SECRETARY);
|
|
||||||
Student student = transientStudent(registrationDTO.getStudentData());
|
|
||||||
student.setUser(user);
|
|
||||||
student = studentRepository.save(student);
|
|
||||||
log.info("New user is student: {}", student);
|
|
||||||
} else if (userInAnyRole(user, RoleService.Authority.TEACHER)) {
|
|
||||||
sureCallerInAnyRole(RoleService.Authority.ADMIN, RoleService.Authority.SECRETARY);
|
|
||||||
Teacher teacher = transientTeacher(registrationDTO.getTeacherData());
|
|
||||||
teacher.setUser(user);
|
|
||||||
teacher = teacherRepository.save(teacher);
|
|
||||||
log.info("New user is teacher: {}", teacher);
|
|
||||||
} else if (userInAnyRole(user, RoleService.Authority.ADMIN)) {
|
|
||||||
sureCallerInAnyRole(RoleService.Authority.ADMIN);
|
|
||||||
log.info("New user is administrator");
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedOperationException("Role not supported: " + user.getAuthorities());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Teacher transientTeacher(RegistrationDTO.TeacherRegistrationDTO teacherData) {
|
|
||||||
if (teacherData == null)
|
|
||||||
throw new NullPointerException("Teacher data is null");
|
|
||||||
if (teacherData.getCuratingGroups() == null)
|
|
||||||
teacherData.setCuratingGroups(List.of());
|
|
||||||
if (teacherData.getAdvisingStudents() == null)
|
|
||||||
teacherData.setAdvisingStudents(List.of());
|
|
||||||
|
|
||||||
Teacher teacher = new Teacher();
|
|
||||||
|
|
||||||
List<Group> groups = groupRepository.findAllById(teacherData.getCuratingGroups());
|
|
||||||
if (groups.size() != teacherData.getCuratingGroups().size()) {
|
|
||||||
throw new NotFoundException(Teacher.class);
|
|
||||||
}
|
|
||||||
List<Student> students = studentRepository.findAllById(teacherData.getAdvisingStudents());
|
|
||||||
if (students.size() != teacherData.getAdvisingStudents().size()) {
|
|
||||||
throw new NotFoundException(Student.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
teacher.setCuratingGroups(groups);
|
|
||||||
teacher.setAdvisingStudents(students);
|
|
||||||
return teacher;
|
|
||||||
}
|
|
||||||
|
|
||||||
private User transientUser(RegistrationDTO registrationDTO) {
|
|
||||||
User user = new User();
|
|
||||||
user.setLogin(registrationDTO.getLogin());
|
|
||||||
user.setPassword(passwordEncoder.encode(registrationDTO.getPassword()));
|
|
||||||
user.setFullName(registrationDTO.getFullName());
|
|
||||||
user.setEmail(registrationDTO.getEmail());
|
|
||||||
user.setNumberPhone(registrationDTO.getNumberPhone());
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Student transientStudent(RegistrationDTO.StudentRegistrationDTO studentData) {
|
|
||||||
if (studentData == null)
|
|
||||||
throw new NullPointerException("Student data is null");
|
|
||||||
|
|
||||||
Student student = new Student();
|
|
||||||
if (studentData.getGroupId() != null) {
|
|
||||||
student.setGroup(groupRepository.findByIdThrow(studentData.getGroupId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return student;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillRoles(User user, RegistrationDTO registrationDTO) {
|
|
||||||
RoleService.Authority accountType = registrationDTO.getAccountType();
|
|
||||||
Role role = roleService.getRoleByAuthority(accountType);
|
|
||||||
if (role == null) {
|
|
||||||
throw new IllegalArgumentException("Role not found for authority: " + accountType);
|
|
||||||
}
|
|
||||||
user.setRoles(List.of(role));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean userInAnyRole(User user, RoleService.Authority... authority) {
|
|
||||||
if (user == null || authority == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<RoleService.Authority> toCheckAuthorities = List.of(authority);
|
|
||||||
return user.getAuthorities().stream()
|
|
||||||
.map(GrantedAuthority::getAuthority)
|
|
||||||
.map(RoleService.Authority::from)
|
|
||||||
.anyMatch(toCheckAuthorities::contains);
|
|
||||||
}
|
|
||||||
|
|
||||||
public User getCallerUser() {
|
|
||||||
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
|
||||||
if (!(principal instanceof User)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (User) principal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<User> getCallerOptional() {
|
|
||||||
return Optional.ofNullable(getCallerUser());
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserDTO getCallerUserDTO() {
|
|
||||||
return getCallerOptional().map(UserDTO::from).orElse(UserDTO.unauthenticated());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCallerInRole(RoleService.Authority... authorities) {
|
|
||||||
return userInAnyRole(getCallerUser(), authorities);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sureCallerInAnyRole(RoleService.Authority... authority) {
|
|
||||||
if (!isCallerInRole(authority)) {
|
|
||||||
throw new AccessDeniedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,4 +1,25 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
public interface DefenceRepository {
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Defense;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface DefenceRepository extends JpaRepository<Defense, Long> {
|
||||||
|
default Defense findByIdThrow(Long id) {
|
||||||
|
return this.findById(id).orElseThrow(() -> new NotFoundException(Defense.class, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT d from Defense d " +
|
||||||
|
"left join fetch d.bestWorks bw " +
|
||||||
|
"left join fetch d.commissionMembers cm " +
|
||||||
|
"where d.id = :id " +
|
||||||
|
"and bw.participant.deleted = false " +
|
||||||
|
"and cm.participant.deleted = false")
|
||||||
|
Optional<Defense> findById(Long id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,29 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import ru.mskobaro.tdms.domain.entity.DiplomaTopic;
|
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
|
||||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||||
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface DiplomaTopicRepository extends JpaRepository<DiplomaTopic, Integer> {
|
public interface DiplomaTopicRepository extends JpaRepository<DiplomaTopic, Long> {
|
||||||
default DiplomaTopic findByIdThrow(Integer id) {
|
default DiplomaTopic findByIdThrow(Long id) {
|
||||||
return this.findById(id).orElseThrow(() -> new NotFoundException(DiplomaTopic.class, id));
|
return this.findById(id).orElseThrow(() -> new NotFoundException(DiplomaTopic.class, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT d FROM DiplomaTopic d WHERE d.id = :id AND d.teacher.participant.deleted = false")
|
||||||
|
Optional<DiplomaTopic> findById(Long id);
|
||||||
|
|
||||||
|
@Query("SELECT d FROM DiplomaTopic d " +
|
||||||
|
"inner join d.directionOfPreparation dp " +
|
||||||
|
"inner join StudentData sd on sd.id = :studentIdwhere " +
|
||||||
|
"where dp = sd.group.directionOfPreparation")
|
||||||
|
List<DiplomaTopic> findAllForStudentId(Long studentId);
|
||||||
}
|
}
|
||||||
@ -1,9 +1,14 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import ru.mskobaro.tdms.domain.entity.Group;
|
import ru.mskobaro.tdms.business.entity.Group;
|
||||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface GroupRepository extends JpaRepository<Group, Long> {
|
public interface GroupRepository extends JpaRepository<Group, Long> {
|
||||||
@ -11,5 +16,12 @@ public interface GroupRepository extends JpaRepository<Group, Long> {
|
|||||||
return this.findById(id).orElseThrow(() -> new NotFoundException(Group.class, id));
|
return this.findById(id).orElseThrow(() -> new NotFoundException(Group.class, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT g FROM Group g left join fetch g.students sd WHERE g.id = :id")
|
||||||
|
Optional<Group> findById(Long id);
|
||||||
|
|
||||||
boolean existsByName(String name);
|
boolean existsByName(String name);
|
||||||
|
|
||||||
|
@Query("SELECT g FROM Group g left join fetch g.students sd WHERE sd IN :students")
|
||||||
|
Group findByStudentsContaining(List<StudentData> students);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Participant;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ParticipantRepository extends JpaRepository<Participant, Long> {
|
||||||
|
|
||||||
|
default Participant findByIdThrow(Long id) {
|
||||||
|
return this.findById(id).orElseThrow(() -> new NotFoundException(DiplomaTopic.class, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT p FROM Participant p WHERE p.id = :id AND p.deleted = false")
|
||||||
|
Optional<Participant> findById(Long id);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT p from Participant p where p.deleted = false")
|
||||||
|
List<Participant> findAll();
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface PreparationDirectionRepository extends JpaRepository<DirectionOfPreparation, Long> {
|
||||||
|
default DirectionOfPreparation findByIdThrow(Long id) {
|
||||||
|
return this.findById(id).orElseThrow(() -> new NotFoundException(DirectionOfPreparation.class, id));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@ package ru.mskobaro.tdms.integration.database;
|
|||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import ru.mskobaro.tdms.domain.entity.Role;
|
import ru.mskobaro.tdms.business.entity.Role;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface RoleRepository extends JpaRepository<Role, Long> {
|
public interface RoleRepository extends JpaRepository<Role, Long> {
|
||||||
|
|||||||
@ -0,0 +1,39 @@
|
|||||||
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.EntityGraph;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface StudentDataRepository extends JpaRepository<StudentData, Long> {
|
||||||
|
default StudentData findByIdThrow(Long id) {
|
||||||
|
return this.findById(id).orElseThrow(() -> new NotFoundException(StudentData.class, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EntityGraph(type = EntityGraph.EntityGraphType.LOAD, attributePaths = {"group.students"})
|
||||||
|
@Query("SELECT s FROM StudentData s join fetch s.participant p WHERE p.id = :id AND p.deleted = false")
|
||||||
|
StudentData findStudentDataByParticipant_Id(Long id);
|
||||||
|
|
||||||
|
boolean existsByParticipant_IdAndParticipant_DeletedFalse(Long id);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@EntityGraph(type = EntityGraph.EntityGraphType.LOAD, attributePaths = {"participant.roles"})
|
||||||
|
@Query("SELECT s FROM StudentData s join fetch s.participant p WHERE s.id in :ids AND p.deleted = false")
|
||||||
|
List<StudentData> findAllById(Iterable<Long> ids);
|
||||||
|
|
||||||
|
@Query("SELECT s FROM StudentData s join fetch s.participant p WHERE s.group is null and p.deleted = false")
|
||||||
|
List<StudentData> findByGroupIsNull();
|
||||||
|
|
||||||
|
@Query("SELECT s FROM StudentData s join fetch s.participant p join fetch s.group g WHERE g.id = :id AND p.deleted = false")
|
||||||
|
List<StudentData> findAllByGroup_Id(Long id);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT s FROM StudentData s join fetch s.participant p WHERE s.id = :id AND p.deleted = false")
|
||||||
|
Optional<StudentData> findById(Long id);
|
||||||
|
}
|
||||||
@ -1,16 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.Student;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.User;
|
|
||||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface StudentRepository extends JpaRepository<Student, Long> {
|
|
||||||
default Student findByIdThrow(Long id) {
|
|
||||||
return this.findById(id).orElseThrow(() -> new NotFoundException(Student.class, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
Student findByUser(User user);
|
|
||||||
}
|
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Task;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface TaskRepository extends JpaRepository<Task, Long> {
|
||||||
|
default Task findByIdThrow(Long id) {
|
||||||
|
return findById(id).orElseThrow(() -> new NotFoundException(Task.class, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query(value = "SELECT t FROM task t " +
|
||||||
|
"WHERE t.type = :type " +
|
||||||
|
"and t.fields->>'makerParticipantId' = :id", nativeQuery = true)
|
||||||
|
List<Task> findDiplomaTopicAgreementTaskByMakerId(Long id, Task.Type type);
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import ru.mskobaro.tdms.business.entity.TeacherData;
|
||||||
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface TeacherDataRepository extends JpaRepository<TeacherData, Long> {
|
||||||
|
default TeacherData findByIdThrow(Long id) {
|
||||||
|
return this.findById(id).orElseThrow(() -> new NotFoundException(TeacherData.class, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT t FROM TeacherData t WHERE t.id = :id AND t.participant.deleted = false")
|
||||||
|
Optional<TeacherData> findById(Long id);
|
||||||
|
|
||||||
|
boolean existsByParticipant_IdAndParticipant_DeletedFalse(Long id);
|
||||||
|
|
||||||
|
@Query("SELECT t FROM TeacherData t WHERE t.participant.id = :id AND t.participant.deleted = false")
|
||||||
|
TeacherData findByParticipant_Id(Long id);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("select t from TeacherData t where t.participant.deleted = false")
|
||||||
|
List<TeacherData> findAll();
|
||||||
|
}
|
||||||
@ -1,13 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.Teacher;
|
|
||||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface TeacherRepository extends JpaRepository<Teacher, Long> {
|
|
||||||
default Teacher findByIdThrow(Long id) {
|
|
||||||
return this.findById(id).orElseThrow(() -> new NotFoundException(Teacher.class, id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +1,10 @@
|
|||||||
package ru.mskobaro.tdms.integration.database;
|
package ru.mskobaro.tdms.integration.database;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import ru.mskobaro.tdms.domain.entity.User;
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -12,5 +13,11 @@ public interface UserRepository extends JpaRepository<User, Long> {
|
|||||||
default User findByIdThrow(Long id) {
|
default User findByIdThrow(Long id) {
|
||||||
return this.findById(id).orElseThrow(() -> new NotFoundException(User.class, id));
|
return this.findById(id).orElseThrow(() -> new NotFoundException(User.class, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Query("SELECT u from User u join fetch u.participant p where u.id = :id and p.deleted = false")
|
||||||
|
Optional<User> findById(Long id);
|
||||||
|
|
||||||
|
@Query("SELECT u from User u join fetch u.participant p where u.login = :login and p.deleted = false")
|
||||||
Optional<User> findUserByLogin(String login);
|
Optional<User> findUserByLogin(String login);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import ru.mskobaro.tdms.business.service.DefenceService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.DefenceDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/defence")
|
||||||
|
public class DefenceController {
|
||||||
|
@Autowired
|
||||||
|
private DefenceService defenceService;
|
||||||
|
|
||||||
|
@GetMapping("/all")
|
||||||
|
public List<DefenceDTO> getAllDefences() {
|
||||||
|
return defenceService.getAllDefences();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,34 @@
|
|||||||
package ru.mskobaro.tdms.presentation.controller;
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import ru.mskobaro.tdms.business.service.DiplomaTopicService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.DiplomaTopicDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/diploma-topic/")
|
@RequestMapping("/api/v1/diploma-topic/")
|
||||||
@Validated
|
@Validated
|
||||||
public class DiplomaTopicController {
|
public class DiplomaTopicController {
|
||||||
|
@Autowired
|
||||||
|
private DiplomaTopicService diplomaTopicService;
|
||||||
|
|
||||||
|
@GetMapping("/all")
|
||||||
|
public List<DiplomaTopicDTO> getAll() {
|
||||||
|
return diplomaTopicService.findAll().stream().map(DiplomaTopicDTO::from).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/save")
|
||||||
|
public void save(@RequestBody DiplomaTopicDTO diplomaTopicDTO) {
|
||||||
|
diplomaTopicService.save(diplomaTopicDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/all-for-student")
|
||||||
|
public List<DiplomaTopicDTO> getAllForStudent(@RequestParam Long studentId) {
|
||||||
|
return diplomaTopicService.findAllForStudent(studentId).stream().map(DiplomaTopicDTO::from).toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,8 @@ package ru.mskobaro.tdms.presentation.controller;
|
|||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.mskobaro.tdms.domain.service.GroupService;
|
import ru.mskobaro.tdms.business.service.GroupService;
|
||||||
import ru.mskobaro.tdms.presentation.payload.GroupCreateDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||||
import ru.mskobaro.tdms.presentation.payload.GroupDTO;
|
|
||||||
import ru.mskobaro.tdms.presentation.payload.GroupEditDTO;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
@ -21,13 +19,13 @@ public class GroupController {
|
|||||||
return groupService.getAllGroups();
|
return groupService.getAllGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/create-group")
|
@PostMapping("/save")
|
||||||
public void createGroup(@RequestBody @Valid GroupCreateDTO groupCreateDTO) {
|
public void save(@RequestBody @Valid GroupDTO groupDTO) {
|
||||||
groupService.createGroup(groupCreateDTO.getName());
|
groupService.save(groupDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/edit-group")
|
@PostMapping("/delete")
|
||||||
public void editGroup(@RequestBody @Valid GroupEditDTO groupEditDTO) {
|
public void delete(@RequestParam(value = "id") Long groupId) {
|
||||||
groupService.editGroup(groupEditDTO);
|
groupService.deleteGroup(groupId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import ru.mskobaro.tdms.business.service.ParticipantService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.IdDto;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantDTO;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.ParticipantSaveDTO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/participant")
|
||||||
|
public class ParticipantController {
|
||||||
|
@Autowired
|
||||||
|
private ParticipantService participantService;
|
||||||
|
|
||||||
|
@GetMapping("/get-all-participants")
|
||||||
|
public Collection<ParticipantDTO> getAllParticipants() {
|
||||||
|
return participantService.getAllParticipants().stream()
|
||||||
|
.map(ParticipantDTO::fromEntity)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/save")
|
||||||
|
public void registerParticipant(@Valid @RequestBody ParticipantSaveDTO participantSaveDTO) {
|
||||||
|
participantService.saveParticipant(participantSaveDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public void deleteParticipant(@RequestBody IdDto id) {
|
||||||
|
participantService.deleteParticipant(id.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import ru.mskobaro.tdms.business.service.PreparationDirectionService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.PreparationDirectionDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/prep-direction")
|
||||||
|
public class PreparationDirectionController {
|
||||||
|
@Autowired
|
||||||
|
private PreparationDirectionService preparationDirectionService;
|
||||||
|
|
||||||
|
@GetMapping("/get-all")
|
||||||
|
public List<PreparationDirectionDTO> getAll() {
|
||||||
|
return preparationDirectionService.getAll().stream().map(PreparationDirectionDTO::from).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("save")
|
||||||
|
public void save(@RequestBody PreparationDirectionDTO preparationDirectionDTO) {
|
||||||
|
preparationDirectionService.save(preparationDirectionDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,22 +5,29 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import ru.mskobaro.tdms.domain.service.StudentService;
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
import ru.mskobaro.tdms.presentation.payload.StudentDTO;
|
import ru.mskobaro.tdms.business.service.StudentDataService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.StudentDataDTO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/student/")
|
@RequestMapping("/api/v1/student/")
|
||||||
public class StudentController {
|
public class StudentController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private StudentService studentService;
|
private StudentDataService studentDataService;
|
||||||
|
|
||||||
@GetMapping("/current")
|
@GetMapping(value = "/by-partic-id")
|
||||||
public StudentDTO getCurrentStudent() {
|
public StudentDataDTO getCurrentStudent(@RequestParam(value = "id") Long particId) {
|
||||||
return studentService.getCallerStudentDtoThrow();
|
StudentData studentData = studentDataService.getStudentByParticIdThrow(particId);
|
||||||
|
return StudentDataDTO.from(studentData, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/by-user-id")
|
@GetMapping(value = "all-without-group")
|
||||||
public StudentDTO getStudentByUserId(@RequestParam Long id) {
|
public Collection<StudentDataDTO> getAllStudentsWithoutGroup() {
|
||||||
return studentService.getStudentByUserIdThrow(id);
|
return studentDataService.getAllStudentsWithoutGroup().stream()
|
||||||
|
.map(sd -> StudentDataDTO.from(sd, true))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import ru.mskobaro.tdms.domain.service.SysInfoService;
|
import ru.mskobaro.tdms.business.service.SysInfoService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/sysinfo")
|
@RequestMapping("/api/v1/sysinfo")
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import ru.mskobaro.tdms.business.service.TaskService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.TaskDto;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/task")
|
||||||
|
public class TaskController {
|
||||||
|
@Autowired
|
||||||
|
private TaskService taskService;
|
||||||
|
|
||||||
|
@GetMapping("/diploma-agreement-maker")
|
||||||
|
public TaskDto diplomaTopicAgreementMaker() {
|
||||||
|
return TaskDto.from(taskService.findDiplomaTopicAgreementTaskCallerMaker());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/create-topic-agreement")
|
||||||
|
public void createDiplomaTopicAgreement(@RequestBody DiplomaTopicAgreementDTO diplomaTopicAgreementDTO) {
|
||||||
|
taskService.createDiplomaAgreementTask(diplomaTopicAgreementDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class DiplomaTopicAgreementDTO {
|
||||||
|
private String diplomaTopicName;
|
||||||
|
private Long diplomaTopicId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import ru.mskobaro.tdms.business.service.TeacherDataService;
|
||||||
|
import ru.mskobaro.tdms.presentation.controller.payload.TeacherDataDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/teacher-data")
|
||||||
|
public class TeacherDataController {
|
||||||
|
@Autowired
|
||||||
|
private TeacherDataService teacherDataService;
|
||||||
|
|
||||||
|
@GetMapping("/get-all")
|
||||||
|
public List<TeacherDataDTO> getAllTeacherData() {
|
||||||
|
return teacherDataService.findAll().stream().map(TeacherDataDTO::from).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/by-partic-id")
|
||||||
|
public TeacherDataDTO getTeacherDataByParticipantId(@RequestParam Long id) {
|
||||||
|
return TeacherDataDTO.from(teacherDataService.getTeacherDataByParticipantId(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,14 +3,14 @@ package ru.mskobaro.tdms.presentation.controller;
|
|||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import ru.mskobaro.tdms.domain.service.AuthenticationService;
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
import ru.mskobaro.tdms.domain.service.UserService;
|
import ru.mskobaro.tdms.business.service.AuthenticationService;
|
||||||
import ru.mskobaro.tdms.presentation.payload.LoginDTO;
|
import ru.mskobaro.tdms.business.service.UserService;
|
||||||
import ru.mskobaro.tdms.presentation.payload.RegistrationDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.LoginDTO;
|
||||||
import ru.mskobaro.tdms.presentation.payload.UserDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/user")
|
@RequestMapping("/api/v1/user")
|
||||||
@ -22,8 +22,11 @@ public class UserController {
|
|||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
@GetMapping("/current")
|
@GetMapping("/current")
|
||||||
public UserDTO getCurrentUser() {
|
public ResponseEntity<UserDTO> getCurrentUser() {
|
||||||
return userService.getCallerUserDTO();
|
User user = userService.getCallerUser();
|
||||||
|
return user == null
|
||||||
|
? ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
|
||||||
|
: ResponseEntity.ok(UserDTO.fromEntity(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/logout")
|
@PostMapping("/logout")
|
||||||
@ -35,14 +38,4 @@ public class UserController {
|
|||||||
public void login(@RequestBody @Valid LoginDTO loginDTO) {
|
public void login(@RequestBody @Valid LoginDTO loginDTO) {
|
||||||
authenticationService.login(loginDTO.getLogin(), loginDTO.getPassword());
|
authenticationService.login(loginDTO.getLogin(), loginDTO.getPassword());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/register")
|
|
||||||
public void register(@RequestBody @Valid RegistrationDTO registrationDTO) {
|
|
||||||
userService.registerUser(registrationDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/get-all")
|
|
||||||
public List<UserDTO> getAllUsers() {
|
|
||||||
return userService.getAllUsers();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import ru.mskobaro.tdms.business.entity.CommissionMemberData;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class CommissionMemberDTO {
|
||||||
|
private Long id;
|
||||||
|
private ParticipantDTO participant;
|
||||||
|
private String workPlace;
|
||||||
|
private String workPosition;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public static CommissionMemberDTO from(CommissionMemberData commissionMemberData) {
|
||||||
|
CommissionMemberDTO dto = new CommissionMemberDTO();
|
||||||
|
dto.setId(commissionMemberData.getId());
|
||||||
|
dto.setParticipant(ParticipantDTO.fromEntity(commissionMemberData.getParticipant()));
|
||||||
|
dto.setWorkPlace(commissionMemberData.getWorkPlace());
|
||||||
|
dto.setWorkPosition(commissionMemberData.getWorkPosition());
|
||||||
|
dto.setCreatedAt(commissionMemberData.getAuditInfo().getCreatedAt());
|
||||||
|
dto.setUpdatedAt(commissionMemberData.getAuditInfo().getUpdatedAt());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Defense;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class DefenceDTO {
|
||||||
|
private Long id;
|
||||||
|
private List<CommissionMemberDTO> commissionMembers;
|
||||||
|
private List<GroupDTO> groups;
|
||||||
|
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public static DefenceDTO from(Defense defense) {
|
||||||
|
DefenceDTO dto = new DefenceDTO();
|
||||||
|
dto.setId(defense.getId());
|
||||||
|
|
||||||
|
if (CollectionUtils.isNotEmpty(defense.getCommissionMembers())) {
|
||||||
|
dto.setCommissionMembers(
|
||||||
|
defense.getCommissionMembers().stream()
|
||||||
|
.map(CommissionMemberDTO::from)
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.setGroups(defense.getGroups().stream().map(g -> GroupDTO.from(g, true)).toList());
|
||||||
|
dto.setCreatedAt(defense.getAuditInfo().getCreatedAt());
|
||||||
|
dto.setUpdatedAt(defense.getAuditInfo().getUpdatedAt());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@ToString
|
||||||
|
public class DiplomaTopicDTO {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private TeacherDataDTO teacher;
|
||||||
|
private PreparationDirectionDTO preparationDirection;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public static DiplomaTopicDTO from(DiplomaTopic diplomaTopic) {
|
||||||
|
DiplomaTopicDTO dto = new DiplomaTopicDTO();
|
||||||
|
dto.setId(diplomaTopic.getId());
|
||||||
|
dto.setName(diplomaTopic.getName());
|
||||||
|
if (diplomaTopic.getTeacher() != null) {
|
||||||
|
dto.setTeacher(TeacherDataDTO.from(diplomaTopic.getTeacher()));
|
||||||
|
}
|
||||||
|
if (diplomaTopic.getDirectionOfPreparation() != null) {
|
||||||
|
dto.setPreparationDirection(PreparationDirectionDTO.from(diplomaTopic.getDirectionOfPreparation()));
|
||||||
|
}
|
||||||
|
dto.setCreatedAt(diplomaTopic.getAuditInfo().getCreatedAt());
|
||||||
|
dto.setUpdatedAt(diplomaTopic.getAuditInfo().getUpdatedAt());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Group;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class GroupDTO {
|
||||||
|
private Long id;
|
||||||
|
@NotEmpty(message = "Имя группы не может быть пустым")
|
||||||
|
@Size(min = 3, max = 50, message = "Имя группы должно быть от 3 до 50 символов")
|
||||||
|
@Pattern(regexp = "^[а-яА-ЯёЁ0-9_-]*$", message = "Имя группы должно содержать только русские буквы, дефис, нижнее подчеркивание и цифры")
|
||||||
|
private String name;
|
||||||
|
private List<StudentDataDTO> students;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
private PreparationDirectionDTO preparationDirection;
|
||||||
|
|
||||||
|
public static GroupDTO from(Group group, boolean includeStudents) {
|
||||||
|
GroupDTO dto = new GroupDTO();
|
||||||
|
dto.setId(group.getId());
|
||||||
|
dto.setName(group.getName());
|
||||||
|
if (includeStudents && group.getStudents() != null) {
|
||||||
|
dto.setStudents(
|
||||||
|
group.getStudents()
|
||||||
|
.stream()
|
||||||
|
.filter(sd -> !sd.getParticipant().isDeleted())
|
||||||
|
.map(sd -> StudentDataDTO.from(sd, false))
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
if (group.getDirectionOfPreparation() != null) {
|
||||||
|
dto.setPreparationDirection(PreparationDirectionDTO.from(group.getDirectionOfPreparation()));
|
||||||
|
}
|
||||||
|
dto.setCreatedAt(group.getAuditInfo().getCreatedAt());
|
||||||
|
dto.setUpdatedAt(group.getAuditInfo().getUpdatedAt());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class IdDto {
|
||||||
|
private Long id;
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||||
|
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Participant;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||||
|
public class ParticipantDTO {
|
||||||
|
private Long id;
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
private String middleName;
|
||||||
|
private String email;
|
||||||
|
private String numberPhone;
|
||||||
|
private UserDTO user;
|
||||||
|
private List<RoleDTO> roles;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public static ParticipantDTO fromEntity(Participant participant) {
|
||||||
|
ParticipantDTO participantDTO = new ParticipantDTO();
|
||||||
|
participantDTO.setId(participant.getId());
|
||||||
|
participantDTO.setFirstName(participant.getFirstName());
|
||||||
|
participantDTO.setLastName(participant.getLastName());
|
||||||
|
participantDTO.setMiddleName(participant.getMiddleName());
|
||||||
|
participantDTO.setEmail(participant.getEmail());
|
||||||
|
participantDTO.setNumberPhone(participant.getNumberPhone());
|
||||||
|
participantDTO.setRoles(RoleDTO.from(participant));
|
||||||
|
participantDTO.setCreatedAt(participant.getAuditInfo().getCreatedAt());
|
||||||
|
participantDTO.setUpdatedAt(participant.getAuditInfo().getUpdatedAt());
|
||||||
|
|
||||||
|
if (participant.getUser() != null) {
|
||||||
|
participantDTO.setUser(UserDTO.fromEntity(participant.getUser(), participantDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
return participantDTO;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import ru.mskobaro.tdms.business.service.RoleService.Authority;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public class ParticipantSaveDTO {
|
||||||
|
private Long id;
|
||||||
|
@NotEmpty(message = "Имя не может быть пустым")
|
||||||
|
@Pattern(regexp = "^[a-zA-Zа-яА-ЯёЁ\\s-]+$", message = "Имя должно содержать только буквы английского или русского алфавита, пробелы и дефис")
|
||||||
|
private String firstName;
|
||||||
|
@NotEmpty(message = "Фамилия не может быть пустой")
|
||||||
|
@Pattern(regexp = "^[a-zA-Zа-яА-ЯёЁ\\s-]+$", message = "Фамилия должна содержать только буквы английского или русского алфавита, пробелы и дефис")
|
||||||
|
private String lastName;
|
||||||
|
private String middleName;
|
||||||
|
@NotNull(message = "Почта не может быть пустой")
|
||||||
|
@Email(message = "Почта должна быть валидным адресом электронной почты")
|
||||||
|
private String email;
|
||||||
|
@NotNull(message = "Номер телефона не может быть пустым")
|
||||||
|
@Pattern(regexp = "^\\+[1-9]\\d{6,14}$", message = "Номер телефона должен начинаться с '+' и содержать от 7 до 15 цифр")
|
||||||
|
private String numberPhone;
|
||||||
|
private List<Authority> authorities;
|
||||||
|
|
||||||
|
@Valid
|
||||||
|
private UserRegistrationDTO userData;
|
||||||
|
@Valid
|
||||||
|
private StudentRegistrationDTO studentData;
|
||||||
|
@Valid
|
||||||
|
private TeacherRegistrationDTO teacherData;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public static class UserRegistrationDTO {
|
||||||
|
@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "Логин должен содержать только латинские буквы, цифры и знак подчеркивания")
|
||||||
|
@Size(min = 5, message = "Логин должен содержать минимум 5 символов")
|
||||||
|
@Size(max = 32, message = "Логин должен содержать максимум 32 символов")
|
||||||
|
private String login;
|
||||||
|
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$", message = "Пароль должен содержать хотя бы одну цифру, одну заглавную и одну строчную букву, минимум 8 символов")
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public static class StudentRegistrationDTO {
|
||||||
|
private Long groupId;
|
||||||
|
private Long curatorId;
|
||||||
|
private Long diplomaTopicId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public static class TeacherRegistrationDTO {
|
||||||
|
private List<Long> curatingGroups;
|
||||||
|
private List<Long> advisingStudents;
|
||||||
|
private String degree;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import ru.mskobaro.tdms.business.entity.DirectionOfPreparation;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class PreparationDirectionDTO {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private String code;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public static PreparationDirectionDTO from(DirectionOfPreparation preparationDirection) {
|
||||||
|
PreparationDirectionDTO dto = new PreparationDirectionDTO();
|
||||||
|
dto.setId(preparationDirection.getId());
|
||||||
|
dto.setName(preparationDirection.getName());
|
||||||
|
dto.setCode(preparationDirection.getCode());
|
||||||
|
dto.setCreatedAt(preparationDirection.getAuditInfo().getCreatedAt());
|
||||||
|
dto.setUpdatedAt(preparationDirection.getAuditInfo().getUpdatedAt());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
|
||||||
|
import ru.mskobaro.tdms.business.entity.Participant;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Role;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public record RoleDTO(String name, String code) {
|
||||||
|
|
||||||
|
public static RoleDTO from(Role role) {
|
||||||
|
return new RoleDTO(role.getName(), role.getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<RoleDTO> from(Participant participant) {
|
||||||
|
return participant.getRoles().stream().map(RoleDTO::from).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class StudentDataDTO {
|
||||||
|
private Long id;
|
||||||
|
private GroupDTO group;
|
||||||
|
private ParticipantDTO participant;
|
||||||
|
private TeacherDataDTO curator;
|
||||||
|
private DiplomaTopicDTO diplomaTopic;
|
||||||
|
|
||||||
|
public static StudentDataDTO from(StudentData studentData, boolean includeGroup) {
|
||||||
|
StudentDataDTO dto = new StudentDataDTO();
|
||||||
|
dto.setId(studentData.getId());
|
||||||
|
if (includeGroup && studentData.getGroup() != null) {
|
||||||
|
dto.setGroup(GroupDTO.from(studentData.getGroup(), false));
|
||||||
|
}
|
||||||
|
dto.setParticipant(ParticipantDTO.fromEntity(studentData.getParticipant()));
|
||||||
|
if (studentData.getCurator() != null) {
|
||||||
|
dto.setCurator(TeacherDataDTO.from(studentData.getCurator()));
|
||||||
|
}
|
||||||
|
if (studentData.getDiplomaTopic() != null) {
|
||||||
|
dto.setDiplomaTopic(DiplomaTopicDTO.from(studentData.getDiplomaTopic()));
|
||||||
|
}
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import ru.mskobaro.tdms.business.entity.Task;
|
||||||
|
import ru.mskobaro.tdms.business.taskfields.TaskFields;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TaskDto {
|
||||||
|
private Long id;
|
||||||
|
private Task.Type type;
|
||||||
|
private Task.Status status;
|
||||||
|
private TaskFields fields;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
|
||||||
|
public static TaskDto from(Task task) {
|
||||||
|
TaskDto dto = new TaskDto();
|
||||||
|
dto.setId(task.getId());
|
||||||
|
dto.setType(task.getType());
|
||||||
|
dto.setStatus(task.getStatus());
|
||||||
|
dto.setFields(task.getFields());
|
||||||
|
dto.setCreatedAt(task.getAuditInfo().getCreatedAt());
|
||||||
|
dto.setUpdatedAt(task.getAuditInfo().getUpdatedAt());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import ru.mskobaro.tdms.business.entity.TeacherData;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TeacherDataDTO {
|
||||||
|
private Long id;
|
||||||
|
private ParticipantDTO participant;
|
||||||
|
private String degree;
|
||||||
|
private String createdAt;
|
||||||
|
private String updatedAt;
|
||||||
|
|
||||||
|
public static TeacherDataDTO from(TeacherData teacherData) {
|
||||||
|
TeacherDataDTO dto = new TeacherDataDTO();
|
||||||
|
dto.setId(teacherData.getId());
|
||||||
|
dto.setParticipant(ParticipantDTO.fromEntity(teacherData.getParticipant()));
|
||||||
|
dto.setDegree(teacherData.getDegree());
|
||||||
|
dto.setCreatedAt(teacherData.getAuditInfo().getCreatedAt().toString());
|
||||||
|
dto.setUpdatedAt(teacherData.getAuditInfo().getUpdatedAt().toString());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package ru.mskobaro.tdms.presentation.controller.payload;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||||
|
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||||
|
import lombok.Builder;
|
||||||
|
import ru.mskobaro.tdms.business.entity.User;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||||
|
public record UserDTO(
|
||||||
|
Long id,
|
||||||
|
String login,
|
||||||
|
ParticipantDTO participant,
|
||||||
|
LocalDateTime createdAt,
|
||||||
|
LocalDateTime updatedAt
|
||||||
|
) {
|
||||||
|
public static UserDTO fromEntity(User user) {
|
||||||
|
return UserDTO.builder()
|
||||||
|
.id(user.getId())
|
||||||
|
.login(user.getLogin())
|
||||||
|
.participant(ParticipantDTO.fromEntity(user.getParticipant()))
|
||||||
|
.createdAt(user.getAuditInfo().getCreatedAt())
|
||||||
|
.updatedAt(user.getAuditInfo().getUpdatedAt())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserDTO fromEntity(User user, ParticipantDTO participant) {
|
||||||
|
return UserDTO.builder()
|
||||||
|
.id(user.getId())
|
||||||
|
.login(user.getLogin())
|
||||||
|
.participant(participant)
|
||||||
|
.createdAt(user.getAuditInfo().getCreatedAt())
|
||||||
|
.updatedAt(user.getAuditInfo().getUpdatedAt())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,16 +9,16 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
|||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||||
import ru.mskobaro.tdms.domain.exception.AccessDeniedException;
|
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
||||||
import ru.mskobaro.tdms.domain.exception.BusinessException;
|
import ru.mskobaro.tdms.business.exception.BusinessException;
|
||||||
import ru.mskobaro.tdms.presentation.payload.ErrorDTO;
|
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.springframework.http.HttpStatus.*;
|
import static org.springframework.http.HttpStatus.*;
|
||||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||||
import static ru.mskobaro.tdms.presentation.payload.ErrorDTO.ErrorCode.*;
|
import static ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO.ErrorCode.*;
|
||||||
|
|
||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
|
||||||
import jakarta.validation.constraints.Pattern;
|
|
||||||
import jakarta.validation.constraints.Size;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class GroupCreateDTO {
|
|
||||||
@NotEmpty(message = "Имя группы не может быть пустым")
|
|
||||||
@Size(min = 3, max = 50, message = "Имя группы должно быть от 3 до 50 символов")
|
|
||||||
@Pattern(regexp = "^[а-яА-ЯёЁ0-9_-]*$", message = "Имя группы должно содержать только русские буквы, дефис, нижнее подчеркивание и цифры")
|
|
||||||
private String name;
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class GroupDTO {
|
|
||||||
private Long id;
|
|
||||||
private String name;
|
|
||||||
private String curatorName;
|
|
||||||
private Boolean iAmCurator;
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@ToString
|
|
||||||
public class GroupEditDTO {
|
|
||||||
@NotNull(message = "Идентификатор группы не может быть пустым")
|
|
||||||
@Min(value = 1, message = "Идентификатор группы должен быть больше 0")
|
|
||||||
private Long id;
|
|
||||||
@NotEmpty(message = "Имя группы не может быть пустым")
|
|
||||||
@Size(min = 3, max = 50, message = "Имя группы должно быть от 3 до 50 символов")
|
|
||||||
@Pattern(regexp = "^[а-яА-ЯёЁ0-9_-]*$", message = "Имя группы должно содержать только русские буквы, дефис, нижнее подчеркивание и цифры")
|
|
||||||
private String name;
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.*;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.hibernate.validator.constraints.Length;
|
|
||||||
import ru.mskobaro.tdms.domain.service.RoleService.Authority;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@ToString
|
|
||||||
public class RegistrationDTO {
|
|
||||||
@NotEmpty(message = "Логин не может быть пустым")
|
|
||||||
@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "Логин должен содержать только латинские буквы, цифры и знак подчеркивания")
|
|
||||||
@Size(min = 5, message = "Логин должен содержать минимум 5 символов")
|
|
||||||
@Size(max = 32, message = "Логин должен содержать максимум 32 символов")
|
|
||||||
private String login;
|
|
||||||
@NotEmpty(message = "Пароль не может быть пустым")
|
|
||||||
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$", message = "Пароль должен содержать хотя бы одну цифру, одну заглавную и одну строчную букву, минимум 8 символов")
|
|
||||||
private String password;
|
|
||||||
@NotEmpty(message = "Имя не может быть пустым")
|
|
||||||
@Length(min = 3, message = "Имя должно содержать минимум 3 символа")
|
|
||||||
@Pattern(regexp = "^[a-zA-Zа-яА-ЯёЁ\\s]+$", message = "Имя должно содержать только буквы английского или русского алфавита и пробелы")
|
|
||||||
private String fullName;
|
|
||||||
@NotNull(message = "Почта не может быть пустой")
|
|
||||||
@Email(message = "Почта должна быть валидным адресом электронной почты")
|
|
||||||
private String email;
|
|
||||||
@NotNull(message = "Номер телефона не может быть пустым")
|
|
||||||
@Pattern(regexp = "^\\+[1-9]\\d{6,14}$", message = "Номер телефона должен начинаться с '+' и содержать от 7 до 15 цифр")
|
|
||||||
private String numberPhone;
|
|
||||||
@NotNull(message = "Тип аккаунта не может быть пустым")
|
|
||||||
private Authority accountType;
|
|
||||||
|
|
||||||
private StudentRegistrationDTO studentData;
|
|
||||||
private TeacherRegistrationDTO teacherData;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@ToString
|
|
||||||
public static class StudentRegistrationDTO {
|
|
||||||
@NotNull(message = "Группа не может быть пустой")
|
|
||||||
private Long groupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public static class TeacherRegistrationDTO {
|
|
||||||
private List<Long> curatingGroups;
|
|
||||||
private List<Long> advisingStudents;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
|
||||||
|
|
||||||
|
|
||||||
import ru.mskobaro.tdms.domain.entity.Role;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.User;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public record RoleDTO(String name, String authority) {
|
|
||||||
|
|
||||||
public static RoleDTO from(Role role) {
|
|
||||||
return new RoleDTO(role.getName(), role.getAuthority());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<RoleDTO> from(User user) {
|
|
||||||
return user.getRoles().stream().map(RoleDTO::from).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.Student;
|
|
||||||
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class StudentDTO {
|
|
||||||
private Long id;
|
|
||||||
private Boolean form;
|
|
||||||
private Integer protectionOrder;
|
|
||||||
private String magistracy;
|
|
||||||
private Boolean digitalFormatPresent;
|
|
||||||
private Integer markComment;
|
|
||||||
private Integer markPractice;
|
|
||||||
private String predefenceComment;
|
|
||||||
private String normalControl;
|
|
||||||
private Integer antiPlagiarism;
|
|
||||||
private String note;
|
|
||||||
private Boolean recordBookReturned;
|
|
||||||
private String work;
|
|
||||||
private UserDTO user;
|
|
||||||
private String diplomaTopic;
|
|
||||||
private UserDTO mentorUser;
|
|
||||||
private GroupDTO group;
|
|
||||||
|
|
||||||
public static StudentDTO from(Student student) {
|
|
||||||
StudentDTO studentDTO = new StudentDTO();
|
|
||||||
studentDTO.setId(student.getId());
|
|
||||||
studentDTO.setForm(student.getForm());
|
|
||||||
studentDTO.setProtectionOrder(student.getProtectionOrder());
|
|
||||||
studentDTO.setMagistracy(student.getMagistracy());
|
|
||||||
studentDTO.setDigitalFormatPresent(student.getDigitalFormatPresent());
|
|
||||||
studentDTO.setMarkComment(student.getMarkComment());
|
|
||||||
studentDTO.setMarkPractice(student.getMarkPractice());
|
|
||||||
studentDTO.setPredefenceComment(student.getPredefenceComment());
|
|
||||||
studentDTO.setNormalControl(student.getNormalControl());
|
|
||||||
studentDTO.setAntiPlagiarism(student.getAntiPlagiarism());
|
|
||||||
studentDTO.setNote(student.getNote());
|
|
||||||
studentDTO.setRecordBookReturned(student.getRecordBookReturned());
|
|
||||||
studentDTO.setWork(student.getWork());
|
|
||||||
studentDTO.setUser(UserDTO.from(student.getUser()));
|
|
||||||
studentDTO.setDiplomaTopic(student.getDiplomaTopic().getName());
|
|
||||||
return studentDTO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.presentation.payload;
|
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Builder;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.User;
|
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
@Builder
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
|
||||||
public record UserDTO(
|
|
||||||
Long id,
|
|
||||||
boolean authenticated,
|
|
||||||
String login,
|
|
||||||
String fullName,
|
|
||||||
String email,
|
|
||||||
String phone,
|
|
||||||
ZonedDateTime createdAt,
|
|
||||||
ZonedDateTime updatedAt,
|
|
||||||
List<String> authorities
|
|
||||||
) {
|
|
||||||
public static UserDTO unauthenticated() {
|
|
||||||
return UserDTO.builder()
|
|
||||||
.authenticated(false)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UserDTO from(User user) {
|
|
||||||
return UserDTO.builder()
|
|
||||||
.id(user.getId())
|
|
||||||
.authenticated(true)
|
|
||||||
.login(user.getLogin())
|
|
||||||
.fullName(user.getFullName())
|
|
||||||
.email(user.getEmail())
|
|
||||||
.phone(user.getNumberPhone())
|
|
||||||
.createdAt(user.getCreatedAt())
|
|
||||||
.updatedAt(user.getUpdatedAt())
|
|
||||||
.authorities(user.getAuthorities().stream().map(GrantedAuthority::getAuthority).toList())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -11,31 +11,28 @@ import org.springframework.context.annotation.Primary;
|
|||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
|
||||||
import org.springframework.security.authentication.ProviderManager;
|
import org.springframework.security.authentication.ProviderManager;
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.core.session.SessionRegistry;
|
||||||
|
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
|
||||||
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
|
||||||
import org.springframework.security.web.context.SecurityContextHolderFilter;
|
import org.springframework.security.web.context.SecurityContextHolderFilter;
|
||||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
|
||||||
import org.springframework.security.web.csrf.CsrfFilter;
|
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.CorsConfigurationSource;
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
import ru.mskobaro.tdms.system.web.DevAuthenticationRequestFilter;
|
|
||||||
import ru.mskobaro.tdms.system.web.LoggingRequestFilter;
|
import ru.mskobaro.tdms.system.web.LoggingRequestFilter;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static ru.mskobaro.tdms.domain.service.RoleService.Authority.*;
|
import static ru.mskobaro.tdms.business.service.RoleService.Authority.ADMIN;
|
||||||
|
import static ru.mskobaro.tdms.business.service.RoleService.Authority.SECRETARY;
|
||||||
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -45,15 +42,15 @@ public class SecurityConfig {
|
|||||||
private Environment environment;
|
private Environment environment;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, AuthenticationManager authenticationManager, CorsConfigurationSource cors) throws Exception {
|
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,
|
||||||
if (environment.matchesProfiles("dev")) {
|
AuthenticationManager authenticationManager,
|
||||||
httpSecurity.addFilterAfter(new DevAuthenticationRequestFilter(), SecurityContextHolderFilter.class);
|
CorsConfigurationSource cors
|
||||||
}
|
) throws Exception {
|
||||||
|
|
||||||
return httpSecurity
|
return httpSecurity
|
||||||
.addFilterAfter(new LoggingRequestFilter(), AnonymousAuthenticationFilter.class)
|
.addFilterAfter(new LoggingRequestFilter(), SecurityContextHolderFilter.class)
|
||||||
.authorizeHttpRequests(this::configureHttpAuthorization)
|
.authorizeHttpRequests(this::configureHttpAuthorization)
|
||||||
.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
|
// .csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
|
||||||
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
.cors(a -> a.configurationSource(cors))
|
.cors(a -> a.configurationSource(cors))
|
||||||
.authenticationManager(authenticationManager)
|
.authenticationManager(authenticationManager)
|
||||||
.sessionManagement(cfg -> {
|
.sessionManagement(cfg -> {
|
||||||
@ -65,7 +62,11 @@ public class SecurityConfig {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Primary
|
@Primary
|
||||||
public CorsConfigurationSource corsConfigurationProd(@Value("${application.domain}") String domain, @Value("${application.port}") String port, @Value("${application.protocol}") String protocol) {
|
public CorsConfigurationSource corsConfiguration(
|
||||||
|
@Value("${application.domain}") String domain,
|
||||||
|
@Value("${application.port}") String port,
|
||||||
|
@Value("${application.protocol}") String protocol
|
||||||
|
) {
|
||||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||||
corsConfiguration.setAllowedMethods(List.of(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name()));
|
corsConfiguration.setAllowedMethods(List.of(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name()));
|
||||||
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
|
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
|
||||||
@ -85,7 +86,14 @@ public class SecurityConfig {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService) {
|
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService) {
|
||||||
return new ProviderManager(authenticationProvider(userDetailsService));
|
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(passwordEncoder());
|
||||||
|
provider.setUserDetailsService(userDetailsService);
|
||||||
|
return new ProviderManager(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SessionRegistry sessionRegistry() {
|
||||||
|
return new SessionRegistryImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -93,32 +101,42 @@ public class SecurityConfig {
|
|||||||
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureHttpAuthorization(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry httpAuthorization) {
|
private void configureHttpAuthorization(
|
||||||
/* SysInfoController */
|
AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry httpAuthorization
|
||||||
|
) {
|
||||||
httpAuthorization.requestMatchers("/api/v1/sysinfo/**").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/sysinfo/**").permitAll();
|
||||||
/* UserController */
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/user/logout").authenticated();
|
httpAuthorization.requestMatchers("/api/v1/user/logout").authenticated();
|
||||||
httpAuthorization.requestMatchers("/api/v1/user/login").anonymous();
|
httpAuthorization.requestMatchers("/api/v1/user/login").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/user/current").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/user/current").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/user/get-all").hasAuthority(ADMIN.getAuthority());
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/user/register").hasAuthority(ADMIN.getAuthority());
|
httpAuthorization.requestMatchers("/api/v1/participant/get-all-participants").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/user/validate-registration").hasAuthority(ADMIN.getAuthority());
|
httpAuthorization.requestMatchers("/api/v1/participant/get-possible-curators").permitAll();
|
||||||
/* StudentController */
|
// Сложная логика авторизации, так что проверяем явно в ParticipantService
|
||||||
httpAuthorization.requestMatchers("/api/v1/student/current").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/participant/save").authenticated();
|
||||||
httpAuthorization.requestMatchers("api/v1/student/by-user-id").hasAnyAuthority(
|
httpAuthorization.requestMatchers("/api/v1/participant/delete").hasAuthority(ADMIN.getAuthority());
|
||||||
SECRETARY.getAuthority(), ADMIN.getAuthority(), STUDENT.getAuthority(), TEACHER.getAuthority());
|
|
||||||
/* GroupController */
|
|
||||||
httpAuthorization.requestMatchers("/api/v1/group/get-all-groups").permitAll();
|
httpAuthorization.requestMatchers("/api/v1/group/get-all-groups").permitAll();
|
||||||
httpAuthorization.requestMatchers("/api/v1/group/create-group").hasAuthority(ADMIN.getAuthority());
|
httpAuthorization.requestMatchers("/api/v1/group/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||||
/* deny all other api requests */
|
httpAuthorization.requestMatchers("/api/v1/group/delete").hasAnyAuthority(ADMIN.getAuthority());
|
||||||
|
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/student/by-partic-id").permitAll();
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/student/all-without-group").permitAll();
|
||||||
|
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/teacher-data/get-all").permitAll();
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/teacher-data/by-partic-id").permitAll();
|
||||||
|
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/prep-direction/get-all").permitAll();
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/prep-direction/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||||
|
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/defence/all").permitAll();
|
||||||
|
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/diploma-topic/all").permitAll();
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/diploma-topic/all-for-student").permitAll();
|
||||||
|
httpAuthorization.requestMatchers("/api/v1/diploma-topic/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||||
|
|
||||||
httpAuthorization.requestMatchers("/api/**").denyAll();
|
httpAuthorization.requestMatchers("/api/**").denyAll();
|
||||||
/* since api already blocked, all other requests are static resources */
|
|
||||||
httpAuthorization.requestMatchers("/**").permitAll();
|
httpAuthorization.requestMatchers("/**").permitAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
|
|
||||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(passwordEncoder());
|
|
||||||
provider.setUserDetailsService(userDetailsService);
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
package ru.mskobaro.tdms.system.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import org.springframework.web.servlet.resource.PathResourceResolver;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
@Override
|
||||||
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
|
registry.addResourceHandler("/**")
|
||||||
|
.addResourceLocations("classpath:/static/")
|
||||||
|
.resourceChain(true)
|
||||||
|
.addResolver(new PathResourceResolver() {
|
||||||
|
@Override
|
||||||
|
protected Resource getResource(String resourcePath, Resource location) throws IOException {
|
||||||
|
Resource requestedResource = location.createRelative(resourcePath);
|
||||||
|
return requestedResource.exists() && requestedResource.isReadable()
|
||||||
|
? requestedResource
|
||||||
|
: location.createRelative("index.html");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package ru.mskobaro.tdms.system.web;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AccessDeniedExceptionHandler implements AccessDeniedHandler {
|
||||||
|
@Autowired
|
||||||
|
private HandlerExceptionResolver handlerExceptionResolver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) {
|
||||||
|
handlerExceptionResolver.resolveException(request, response, null, new ru.mskobaro.tdms.business.exception.AccessDeniedException());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,46 +0,0 @@
|
|||||||
package ru.mskobaro.tdms.system.web;
|
|
||||||
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.core.context.TransientSecurityContext;
|
|
||||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.Role;
|
|
||||||
import ru.mskobaro.tdms.domain.entity.User;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static ru.mskobaro.tdms.domain.service.RoleService.Authority.ADMIN;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class DevAuthenticationRequestFilter extends OncePerRequestFilter {
|
|
||||||
public DevAuthenticationRequestFilter() {
|
|
||||||
log.warn("!!!ANY REQUEST WILL BE AUTHENTICATED AS DEV_ADMIN, IF YOU SEE THIS IN PRODUCTION, CHECK YOUR CONFIGURATION!!!");
|
|
||||||
log.warn("!!!ANY REQUEST WILL BE AUTHENTICATED AS DEV_ADMIN, IF YOU SEE THIS IN PRODUCTION, CHECK YOUR CONFIGURATION!!!");
|
|
||||||
log.warn("!!!ANY REQUEST WILL BE AUTHENTICATED AS DEV_ADMIN, IF YOU SEE THIS IN PRODUCTION, CHECK YOUR CONFIGURATION!!!");
|
|
||||||
log.warn("!!!ANY REQUEST WILL BE AUTHENTICATED AS DEV_ADMIN, IF YOU SEE THIS IN PRODUCTION, CHECK YOUR CONFIGURATION!!!");
|
|
||||||
log.warn("!!!ANY REQUEST WILL BE AUTHENTICATED AS DEV_ADMIN, IF YOU SEE THIS IN PRODUCTION, CHECK YOUR CONFIGURATION!!!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
|
||||||
Role role = new Role(-1L, "dev_admin_role", ADMIN.getAuthority());
|
|
||||||
User admin = new User();
|
|
||||||
admin.setRoles(List.of(role));
|
|
||||||
admin.setId(-1L);
|
|
||||||
admin.setLogin("dev_admin");
|
|
||||||
admin.setEmail("dev_admin@main.mail");
|
|
||||||
admin.setFullName("dev_admin");
|
|
||||||
admin.setNumberPhone("+79999999999");
|
|
||||||
admin.setPassword("{bcrypt}$2a$06$BHHQMjwQB2KI9sDdC9rRHOuYkTskjDt9WAyrscWP/Dcn7my3Jr77K");
|
|
||||||
var auth = new PreAuthenticatedAuthenticationToken(admin, null, admin.getAuthorities());
|
|
||||||
var context = new TransientSecurityContext(auth);
|
|
||||||
SecurityContextHolder.setContext(context);
|
|
||||||
filterChain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -6,24 +6,30 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LoggingRequestFilter extends OncePerRequestFilter {
|
public class LoggingRequestFilter extends OncePerRequestFilter {
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
String username = SecurityContextHolder.getContext().getAuthentication() != null ?
|
||||||
|
SecurityContextHolder.getContext().getAuthentication().getName() : "anonymousUser";
|
||||||
HttpSession session = request.getSession(false);
|
HttpSession session = request.getSession(false);
|
||||||
log.info("Request received: [{}] {} user: {}, session: {}, remote ip: {}",
|
log.info("Request received: [{}] {} user: {}, session: {}, remote ip: {} [{}]",
|
||||||
request.getMethod(), request.getRequestURI(), request.getRemoteUser(),
|
request.getMethod(), request.getRequestURI(), username,
|
||||||
session == null ? "no" : session.getId(), request.getRemoteAddr());
|
session == null ? "no" : session.getId(), request.getRemoteAddr(), uuid);
|
||||||
try {
|
try {
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
} finally {
|
} finally {
|
||||||
long duration = System.currentTimeMillis() - startTime;
|
long duration = System.currentTimeMillis() - startTime;
|
||||||
log.info("Response with {} status duration: {} ms", response.getStatus(), duration);
|
log.info("Response with {} status duration: {} ms [{}]", response.getStatus(), duration, uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,11 +30,6 @@ spring:
|
|||||||
schemas: ${db.schema}
|
schemas: ${db.schema}
|
||||||
banner:
|
banner:
|
||||||
location: banner.txt
|
location: banner.txt
|
||||||
web:
|
|
||||||
resources:
|
|
||||||
static-locations: classpath:/static/
|
|
||||||
# autoconfigure:
|
|
||||||
# exclude: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
|
|
||||||
server:
|
server:
|
||||||
port: ${application.port}
|
port: ${application.port}
|
||||||
address: ${application.domain}
|
address: ${application.domain}
|
||||||
|
|||||||
@ -0,0 +1,280 @@
|
|||||||
|
CREATE TABLE defense
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
defense_date DATE,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE defense_best_student_works
|
||||||
|
(
|
||||||
|
defense_id BIGINT,
|
||||||
|
student_data_id BIGINT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE defense_commission
|
||||||
|
(
|
||||||
|
defense_id BIGINT,
|
||||||
|
commission_member_data_id BIGINT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE diploma_topic
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
teacher_id BIGINT,
|
||||||
|
direction_of_preparation_id BIGINT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE direction_of_preparation
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
code TEXT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "group"
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
defense_id BIGINT,
|
||||||
|
direction_of_preparation_id BIGINT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE participant
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
first_name TEXT,
|
||||||
|
last_name TEXT,
|
||||||
|
middle_name TEXT,
|
||||||
|
email TEXT,
|
||||||
|
number_phone TEXT,
|
||||||
|
deleted BOOLEAN DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE participant_role
|
||||||
|
(
|
||||||
|
partic_id BIGINT NOT NULL,
|
||||||
|
role_id BIGINT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE role
|
||||||
|
(
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
authority TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
/* todo */
|
||||||
|
CREATE TABLE student_data
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
partic_id BIGINT,
|
||||||
|
study_form_id BIGINT,
|
||||||
|
|
||||||
|
curator_id BIGINT,
|
||||||
|
protection_order INTEGER,
|
||||||
|
protection_day INTEGER,
|
||||||
|
|
||||||
|
mark_comment INTEGER,
|
||||||
|
mark_practice INTEGER,
|
||||||
|
|
||||||
|
predefnese_comment TEXT,
|
||||||
|
normal_control BOOLEAN,
|
||||||
|
anti_plagiarism INTEGER,
|
||||||
|
record_book_returned BOOLEAN,
|
||||||
|
work TEXT,
|
||||||
|
diploma_topic_id BIGINT,
|
||||||
|
adviser_teacher_partic_id BIGINT,
|
||||||
|
group_id BIGINT,
|
||||||
|
marks_3 BIGINT,
|
||||||
|
marks_4 BIGINT,
|
||||||
|
marks_5 BIGINT,
|
||||||
|
commission_mark BIGINT,
|
||||||
|
estimated BOOLEAN,
|
||||||
|
diploma_with_honors BOOLEAN,
|
||||||
|
magistracy_recommendation BOOLEAN,
|
||||||
|
magistracy_wanted BOOLEAN,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
/* not implemented */
|
||||||
|
create table questionnaire
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
student_data_id BIGINT,
|
||||||
|
data TEXT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
create table study_form
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
/* todo */
|
||||||
|
create table stud_comment
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
comment TEXT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
/* todo */
|
||||||
|
create table student_data_comment
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
student_data_id BIGINT,
|
||||||
|
stud_comment_id BIGINT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE teacher_data
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
participant_id BIGINT,
|
||||||
|
degree TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE commission_member_data
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
partic_id BIGINT,
|
||||||
|
work_place TEXT,
|
||||||
|
work_position TEXT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "user"
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
login TEXT,
|
||||||
|
password TEXT,
|
||||||
|
partic_id BIGINT,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE task
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
type TEXT,
|
||||||
|
status TEXT,
|
||||||
|
fields jsonb,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE defense_commission
|
||||||
|
ADD CONSTRAINT FK_DEFCOM_ON_DEFNESE FOREIGN KEY (defense_id) REFERENCES defense (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE defense_commission
|
||||||
|
ADD CONSTRAINT FK_DEFCOM_ON_COMMEMD FOREIGN KEY (commission_member_data_id) REFERENCES commission_member_data (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE "group"
|
||||||
|
ADD CONSTRAINT FK_GROUP_ON_defnese FOREIGN KEY (defense_id) REFERENCES defense (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE "group"
|
||||||
|
ADD CONSTRAINT FK_GROUP_ON_DOP FOREIGN KEY (direction_of_preparation_id) REFERENCES direction_of_preparation (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE participant_role
|
||||||
|
ADD CONSTRAINT FK_PARROL_ON_PARTICIPANT FOREIGN KEY (partic_id) REFERENCES participant (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE participant_role
|
||||||
|
ADD CONSTRAINT FK_PARROL_ON_ROLE FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT UC_STUDENT_DATA_PARTIC UNIQUE (partic_id);
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT FK_STUDENT_DATA_ON_ADVISER_TEACHER_PARTIC FOREIGN KEY (adviser_teacher_partic_id) REFERENCES participant (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT FK_STUDENT_DATA_ON_DIPLOMA_TOPIC FOREIGN KEY (diploma_topic_id) REFERENCES diploma_topic (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT FK_STUDENT_DATA_ON_GROUP FOREIGN KEY (group_id) REFERENCES "group" (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT FK_STUDENT_DATA_ON_PARTIC FOREIGN KEY (partic_id) REFERENCES participant (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE participant
|
||||||
|
ADD CONSTRAINT UC_PARTICIPANT_EMAIL UNIQUE (email);
|
||||||
|
|
||||||
|
ALTER TABLE participant
|
||||||
|
ADD CONSTRAINT UC_PARTICIPANT_NUMBER_PHONE UNIQUE (number_phone);
|
||||||
|
|
||||||
|
ALTER TABLE "user"
|
||||||
|
ADD CONSTRAINT UC_USER_LOGIN UNIQUE (login);
|
||||||
|
|
||||||
|
ALTER TABLE "user"
|
||||||
|
ADD CONSTRAINT UC_USER_PARTIC UNIQUE (partic_id);
|
||||||
|
|
||||||
|
ALTER TABLE "user"
|
||||||
|
ADD CONSTRAINT FK_USER_ON_PARTIC FOREIGN KEY (partic_id) REFERENCES participant (id);
|
||||||
|
|
||||||
|
ALTER TABLE teacher_data
|
||||||
|
ADD CONSTRAINT UC_TEACHER_DATA_PARTIC UNIQUE (participant_id);
|
||||||
|
|
||||||
|
ALTER TABLE teacher_data
|
||||||
|
ADD CONSTRAINT FK_TEACHER_DATA_ON_PARTIC FOREIGN KEY (participant_id) REFERENCES participant (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE commission_member_data
|
||||||
|
ADD CONSTRAINT UC_COMMISION_MEMBER_DATA_PARTIC UNIQUE (partic_id);
|
||||||
|
|
||||||
|
ALTER TABLE commission_member_data
|
||||||
|
ADD CONSTRAINT FK_COMMISION_MEMBER_DATA_ON_PARTIC FOREIGN KEY (partic_id) REFERENCES participant (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE direction_of_preparation
|
||||||
|
ADD CONSTRAINT UC_DIRECTION_OF_PREPARATION_NAME UNIQUE (name);
|
||||||
|
|
||||||
|
ALTER TABLE direction_of_preparation
|
||||||
|
ADD CONSTRAINT UC_DIRECTION_OF_PREPARATION_CODE UNIQUE (code);
|
||||||
|
|
||||||
|
ALTER TABLE diploma_topic
|
||||||
|
ADD CONSTRAINT UC_DIPLOMA_TOPIC_NAME FOREIGN KEY (direction_of_preparation_id) REFERENCES direction_of_preparation (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE defense_best_student_works
|
||||||
|
ADD CONSTRAINT FK_DEFENSE_BEST_STUDENT_WORKS_ON_DEFENSE FOREIGN KEY (defense_id) REFERENCES defense (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE defense_best_student_works
|
||||||
|
ADD CONSTRAINT FK_DEFENSE_BEST_STUDENT_WORKS_ON_STUDENT_DATA FOREIGN KEY (student_data_id) REFERENCES student_data (id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE stud_comment
|
||||||
|
ADD CONSTRAINT UC_STUD_COMMENT_COMMENT UNIQUE (comment);
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT UC_STUDENT_DATA_DIPLOMA_TOPIC FOREIGN KEY (diploma_topic_id) REFERENCES diploma_topic (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT UC_STUDENT_DATA_STUDY_FORM FOREIGN KEY (study_form_id) REFERENCES study_form (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE student_data
|
||||||
|
ADD CONSTRAINT UC_STUDENT_DATA_CURATOR FOREIGN KEY (curator_id) REFERENCES teacher_data (id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE study_form
|
||||||
|
ADD CONSTRAINT UC_STUDY_FORM_NAME UNIQUE (name);
|
||||||
|
|
||||||
|
alter table questionnaire
|
||||||
|
add constraint UC_QUESTIONNAIRE_STUDENT_DATA_ID unique (student_data_id);
|
||||||
|
|
||||||
|
alter table questionnaire
|
||||||
|
add constraint FK_QUESTIONNAIRE_STUDENT_DATA foreign key (student_data_id) references student_data (id) on delete cascade on update cascade;
|
||||||
@ -1,13 +0,0 @@
|
|||||||
create table role
|
|
||||||
(
|
|
||||||
id bigint primary key,
|
|
||||||
|
|
||||||
name text not null unique,
|
|
||||||
authority text not null unique
|
|
||||||
);
|
|
||||||
|
|
||||||
-- COMMENTS
|
|
||||||
comment on table role is 'Таблица ролей пользователей';
|
|
||||||
|
|
||||||
comment on column role.name is 'Человекочитаемое имя роли';
|
|
||||||
comment on column role.authority is 'Имя роли в системе';
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
create table "user"
|
|
||||||
(
|
|
||||||
id bigserial primary key,
|
|
||||||
|
|
||||||
login text not null unique,
|
|
||||||
password text not null,
|
|
||||||
full_name text not null,
|
|
||||||
email text not null unique,
|
|
||||||
number_phone text not null unique,
|
|
||||||
|
|
||||||
created_at timestamptz not null,
|
|
||||||
updated_at timestamptz
|
|
||||||
);
|
|
||||||
|
|
||||||
-- COMMENTS
|
|
||||||
comment on table "user" is 'Таблица пользователей';
|
|
||||||
|
|
||||||
comment on column "user".login is 'Логин пользователя';
|
|
||||||
comment on column "user".password is 'Пароль пользователя';
|
|
||||||
comment on column "user".full_name is 'Полное имя пользователя в формате Фамилия Имя Отчество';
|
|
||||||
comment on column "user".email is 'Почта пользователя';
|
|
||||||
comment on column "user".number_phone is 'Номер телефона пользователя';
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
create table user_role
|
|
||||||
(
|
|
||||||
id bigserial primary key,
|
|
||||||
|
|
||||||
user_id bigint not null,
|
|
||||||
role_id bigint not null
|
|
||||||
);
|
|
||||||
|
|
||||||
-- FOREIGN KEY
|
|
||||||
alter table user_role
|
|
||||||
add constraint fk_user_role_user_id
|
|
||||||
foreign key (user_id) references "user" (id)
|
|
||||||
on delete cascade on update cascade;
|
|
||||||
|
|
||||||
alter table user_role
|
|
||||||
add constraint fk_user_role_role_id
|
|
||||||
foreign key (role_id) references role (id)
|
|
||||||
on delete restrict on update cascade;
|
|
||||||
|
|
||||||
-- COMMENTS
|
|
||||||
comment on table user_role is 'Таблица связи пользователей и ролей';
|
|
||||||
|
|
||||||
comment on column user_role.user_id is 'Идентификатор пользователя';
|
|
||||||
comment on column user_role.role_id is 'Идентификатор роли';
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
create table diploma_topic
|
|
||||||
(
|
|
||||||
id bigserial primary key,
|
|
||||||
|
|
||||||
name text not null
|
|
||||||
);
|
|
||||||
|
|
||||||
-- COMMENTS
|
|
||||||
comment on table diploma_topic is 'Таблица тем дипломных работ';
|
|
||||||
|
|
||||||
comment on column diploma_topic.name is 'Название темы дипломной работы';
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
create table teacher
|
|
||||||
(
|
|
||||||
id bigserial primary key,
|
|
||||||
user_id bigint not null,
|
|
||||||
|
|
||||||
created_at timestamptz not null,
|
|
||||||
updated_at timestamptz
|
|
||||||
);
|
|
||||||
|
|
||||||
-- FOREIGN KEY
|
|
||||||
alter table teacher
|
|
||||||
add constraint fk_teacher_user_id
|
|
||||||
foreign key (user_id) references "user" (id)
|
|
||||||
on delete cascade on update cascade;
|
|
||||||
|
|
||||||
-- COMMENTS
|
|
||||||
comment on table teacher is 'Таблица преподавателей';
|
|
||||||
|
|
||||||
comment on column teacher.user_id is 'Идентификатор пользователя';
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
create table "group"
|
|
||||||
(
|
|
||||||
id bigserial primary key,
|
|
||||||
|
|
||||||
name text not null unique,
|
|
||||||
curator_teacher_id bigint,
|
|
||||||
|
|
||||||
created_at timestamptz not null,
|
|
||||||
updated_at timestamptz
|
|
||||||
);
|
|
||||||
|
|
||||||
-- FOREIGN KEY
|
|
||||||
alter table "group"
|
|
||||||
add constraint fk_group_curator_teacher_id
|
|
||||||
foreign key (curator_teacher_id) references teacher (id)
|
|
||||||
on delete set null on update cascade;
|
|
||||||
|
|
||||||
-- COMMENTS
|
|
||||||
comment on table "group" is 'Таблица групп студентов';
|
|
||||||
|
|
||||||
comment on column "group".name is 'Название группы';
|
|
||||||
comment on column "group".curator_teacher_id is 'Идентификатор куратора группы';
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
create table student
|
|
||||||
(
|
|
||||||
id bigserial primary key,
|
|
||||||
user_id bigint not null,
|
|
||||||
diploma_topic_id bigint,
|
|
||||||
adviser_teacher_id bigint,
|
|
||||||
group_id bigint,
|
|
||||||
|
|
||||||
form boolean,
|
|
||||||
protection_day int,
|
|
||||||
protection_order int,
|
|
||||||
magistracy text,
|
|
||||||
digital_format_present boolean,
|
|
||||||
mark_comment int,
|
|
||||||
mark_practice int,
|
|
||||||
predefence_comment text,
|
|
||||||
normal_control text,
|
|
||||||
anti_plagiarism int,
|
|
||||||
note text,
|
|
||||||
record_book_returned boolean,
|
|
||||||
work text,
|
|
||||||
|
|
||||||
created_at timestamptz not null,
|
|
||||||
updated_at timestamptz
|
|
||||||
);
|
|
||||||
|
|
||||||
-- FOREIGN KEY
|
|
||||||
alter table student
|
|
||||||
add constraint fk_student_user_id
|
|
||||||
foreign key (user_id) references "user" (id)
|
|
||||||
on delete cascade on update cascade;
|
|
||||||
alter table student
|
|
||||||
add constraint fk_student_diploma_topic_id
|
|
||||||
foreign key (diploma_topic_id) references diploma_topic (id)
|
|
||||||
on delete set null on update cascade;
|
|
||||||
alter table student
|
|
||||||
add constraint fk_student_adviser_teacher_id
|
|
||||||
foreign key (adviser_teacher_id) references teacher (id)
|
|
||||||
on delete set null on update cascade;
|
|
||||||
alter table student
|
|
||||||
add constraint fk_student_group_id
|
|
||||||
foreign key (group_id) references "group" (id)
|
|
||||||
on delete set null on update cascade;
|
|
||||||
|
|
||||||
-- COMMENTS
|
|
||||||
comment on table student is 'Таблица студентов';
|
|
||||||
|
|
||||||
comment on column student.user_id is 'Идентификатор пользователя';
|
|
||||||
comment on column student.diploma_topic_id is 'Идентификатор темы дипломной работы';
|
|
||||||
comment on column student.adviser_teacher_id is 'Идентификатор научного руководителя';
|
|
||||||
comment on column student.group_id is 'Идентификатор группы';
|
|
||||||
|
|
||||||
comment on column student.form is 'Форма обучения';
|
|
||||||
comment on column student.protection_day is 'День защиты';
|
|
||||||
comment on column student.protection_order is 'Порядок защиты';
|
|
||||||
comment on column student.magistracy is 'Магистратура';
|
|
||||||
comment on column student.digital_format_present is 'Предоставлен в электронном виде';
|
|
||||||
comment on column student.mark_comment is 'Комментарий к оценке';
|
|
||||||
comment on column student.mark_practice is 'Оценка практики';
|
|
||||||
comment on column student.predefence_comment is 'Комментарий к защите';
|
|
||||||
comment on column student.normal_control is 'Обычный контроль';
|
|
||||||
comment on column student.anti_plagiarism is 'Антиплагиат';
|
|
||||||
comment on column student.note is 'Примечание';
|
|
||||||
comment on column student.record_book_returned is 'Ведомость возвращена';
|
|
||||||
comment on column student.work is 'Работа';
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user