Compare commits
2 Commits
d298a5f1f4
...
615c1c761c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
615c1c761c | ||
|
|
3a25996280 |
@ -10,15 +10,14 @@
|
||||
<version>0.0.1</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ru.mskobaro</groupId>
|
||||
<artifactId>server</artifactId>
|
||||
<version>0.0.1</version>
|
||||
|
||||
<name>TDMS::SERVER</name>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.compiler.source>23</maven.compiler.source>
|
||||
<maven.compiler.target>23</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<lombok.version>1.18.34</lombok.version>
|
||||
</properties>
|
||||
@ -127,6 +126,8 @@
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<source>23</source>
|
||||
<target>23</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
@ -15,7 +15,7 @@ public class TdmsApplication {
|
||||
Thread.currentThread().setName("spring-bootstrapper");
|
||||
ConfigurableApplicationContext ctx = SpringApplication.run(TdmsApplication.class, args);
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -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.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.*;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
|
||||
@ -18,6 +15,7 @@ import org.springframework.security.core.GrantedAuthority;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table(name = "`role`")
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class Role implements GrantedAuthority {
|
||||
@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 lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
|
||||
@Entity
|
||||
@Table(name = "study_form")
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Entity
|
||||
@Table(name = "diploma_topic")
|
||||
public class DiplomaTopic {
|
||||
public class StudyForm {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "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.*;
|
||||
@ -6,13 +6,10 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@ -32,33 +29,26 @@ public class User implements UserDetails {
|
||||
private String login;
|
||||
@Column(name = "password")
|
||||
private String password;
|
||||
@Column(name = "full_name")
|
||||
private String fullName;
|
||||
@Column(name = "email")
|
||||
private String email;
|
||||
@Column(name = "number_phone")
|
||||
private String numberPhone;
|
||||
@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;
|
||||
@OneToOne
|
||||
@JoinColumn(name = "partic_id")
|
||||
private Participant participant;
|
||||
|
||||
@Embedded
|
||||
private AuditInfo auditInfo;
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return roles.stream()
|
||||
return participant.getRoles().stream()
|
||||
.map(Role::getAuthority)
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return !participant.isDeleted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
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 AccessDeniedException() {
|
||||
super("Access denied");
|
||||
}
|
||||
|
||||
public AccessDeniedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorDTO.ErrorCode getErrorCode() {
|
||||
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 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 NotFoundException(Class<?> entityClass, Object id) {
|
||||
super(entityClass.getSimpleName() + " с идентификатором " + id + " не наеден");
|
||||
super(entityClass.getSimpleName() + " с идентификатором " + id + " не существует");
|
||||
}
|
||||
|
||||
public NotFoundException(Class<?> entityClass) {
|
||||
super(entityClass.getSimpleName() + " не найден");
|
||||
super(entityClass.getSimpleName() + " не существует");
|
||||
}
|
||||
|
||||
public NotFoundException() {
|
||||
super("Не найдено");
|
||||
super("Не существует");
|
||||
}
|
||||
|
||||
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.HttpSession;
|
||||
@ -6,10 +6,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.springframework.security.web.context.HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AuthenticationService {
|
||||
@ -17,25 +21,41 @@ public class AuthenticationService {
|
||||
private HttpServletRequest request;
|
||||
@Autowired
|
||||
private AuthenticationManager authenticationManager;
|
||||
@Autowired
|
||||
private SessionRegistry sessionRegistry;
|
||||
|
||||
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);
|
||||
if(session != null) {
|
||||
if (session != null) {
|
||||
session.invalidate();
|
||||
}
|
||||
|
||||
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
|
||||
public void login(String username, String password) {
|
||||
log.info("Logging in user: {}, ip: {}", username, request.getRemoteAddr());
|
||||
|
||||
var token = new UsernamePasswordAuthenticationToken(username, password);
|
||||
var authenticated = authenticationManager.authenticate(token);
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticated);
|
||||
|
||||
log.info("User {} logged in", username);
|
||||
request.getSession().setAttribute(SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
|
||||
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 lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -7,7 +9,8 @@ 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.Role;
|
||||
import ru.mskobaro.tdms.business.entity.Participant;
|
||||
import ru.mskobaro.tdms.business.entity.Role;
|
||||
import ru.mskobaro.tdms.integration.database.RoleRepository;
|
||||
|
||||
import java.util.Map;
|
||||
@ -17,17 +20,23 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
@Slf4j
|
||||
public class RoleService {
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum Authority {
|
||||
ADMIN("ROLE_ADMINISTRATOR"),
|
||||
COMM_MEMBER("ROLE_COMMISSION_MEMBER"),
|
||||
TEACHER("ROLE_TEACHER"),
|
||||
PLAGIARISM_CHECKER("ROLE_PLAGIARISM_CHECKER"),
|
||||
SECRETARY("ROLE_SECRETARY"),
|
||||
STUDENT("ROLE_STUDENT"),
|
||||
;
|
||||
|
||||
private final String authority;
|
||||
|
||||
@JsonValue
|
||||
public String getAuthority() {
|
||||
return authority;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static Authority from(String authority) {
|
||||
for (Authority value : values()) {
|
||||
if (value.getAuthority().equals(authority)) {
|
||||
@ -37,7 +46,8 @@ public class RoleService {
|
||||
throw new IllegalArgumentException("No such authority: " + authority);
|
||||
}
|
||||
}
|
||||
public transient Map<String, Role> roles;
|
||||
|
||||
private final Map<String, Role> roles = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
private RoleRepository roleRepository;
|
||||
@ -45,7 +55,6 @@ public class RoleService {
|
||||
@PostConstruct
|
||||
@Transactional
|
||||
public void bootstrapRolesCache() {
|
||||
roles = new ConcurrentHashMap<>();
|
||||
roleRepository.findAll().forEach(role -> roles.put(role.getAuthority(), role));
|
||||
log.info("Roles initialized: {}", roles);
|
||||
}
|
||||
@ -53,4 +62,21 @@ public class RoleService {
|
||||
public Role getRoleByAuthority(Authority authority) {
|
||||
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.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;
|
||||
|
||||
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;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.mskobaro.tdms.domain.entity.DiplomaTopic;
|
||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
||||
import ru.mskobaro.tdms.business.entity.DiplomaTopic;
|
||||
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
|
||||
public interface DiplomaTopicRepository extends JpaRepository<DiplomaTopic, Integer> {
|
||||
default DiplomaTopic findByIdThrow(Integer id) {
|
||||
public interface DiplomaTopicRepository extends JpaRepository<DiplomaTopic, Long> {
|
||||
default DiplomaTopic findByIdThrow(Long 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;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.mskobaro.tdms.domain.entity.Group;
|
||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
||||
import ru.mskobaro.tdms.business.entity.Group;
|
||||
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 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));
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
@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.stereotype.Repository;
|
||||
import ru.mskobaro.tdms.domain.entity.Role;
|
||||
import ru.mskobaro.tdms.business.entity.Role;
|
||||
|
||||
@Repository
|
||||
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;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.mskobaro.tdms.domain.entity.User;
|
||||
import ru.mskobaro.tdms.domain.exception.NotFoundException;
|
||||
import ru.mskobaro.tdms.business.entity.User;
|
||||
import ru.mskobaro.tdms.business.exception.NotFoundException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@ -12,5 +13,11 @@ public interface UserRepository extends JpaRepository<User, Long> {
|
||||
default User findByIdThrow(Long 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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.mskobaro.tdms.business.service.DiplomaTopicService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.DiplomaTopicDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/diploma-topic/")
|
||||
@Validated
|
||||
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 org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.mskobaro.tdms.domain.service.GroupService;
|
||||
import ru.mskobaro.tdms.presentation.payload.GroupCreateDTO;
|
||||
import ru.mskobaro.tdms.presentation.payload.GroupDTO;
|
||||
import ru.mskobaro.tdms.presentation.payload.GroupEditDTO;
|
||||
import ru.mskobaro.tdms.business.service.GroupService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.GroupDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@ -21,13 +19,13 @@ public class GroupController {
|
||||
return groupService.getAllGroups();
|
||||
}
|
||||
|
||||
@PostMapping("/create-group")
|
||||
public void createGroup(@RequestBody @Valid GroupCreateDTO groupCreateDTO) {
|
||||
groupService.createGroup(groupCreateDTO.getName());
|
||||
@PostMapping("/save")
|
||||
public void save(@RequestBody @Valid GroupDTO groupDTO) {
|
||||
groupService.save(groupDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/edit-group")
|
||||
public void editGroup(@RequestBody @Valid GroupEditDTO groupEditDTO) {
|
||||
groupService.editGroup(groupEditDTO);
|
||||
@PostMapping("/delete")
|
||||
public void delete(@RequestParam(value = "id") Long groupId) {
|
||||
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.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import ru.mskobaro.tdms.domain.service.StudentService;
|
||||
import ru.mskobaro.tdms.presentation.payload.StudentDTO;
|
||||
import ru.mskobaro.tdms.business.entity.StudentData;
|
||||
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
|
||||
@RequestMapping("/api/v1/student/")
|
||||
public class StudentController {
|
||||
@Autowired
|
||||
private StudentService studentService;
|
||||
private StudentDataService studentDataService;
|
||||
|
||||
@GetMapping("/current")
|
||||
public StudentDTO getCurrentStudent() {
|
||||
return studentService.getCallerStudentDtoThrow();
|
||||
@GetMapping(value = "/by-partic-id")
|
||||
public StudentDataDTO getCurrentStudent(@RequestParam(value = "id") Long particId) {
|
||||
StudentData studentData = studentDataService.getStudentByParticIdThrow(particId);
|
||||
return StudentDataDTO.from(studentData, true);
|
||||
}
|
||||
|
||||
@GetMapping("/by-user-id")
|
||||
public StudentDTO getStudentByUserId(@RequestParam Long id) {
|
||||
return studentService.getStudentByUserIdThrow(id);
|
||||
@GetMapping(value = "all-without-group")
|
||||
public Collection<StudentDataDTO> getAllStudentsWithoutGroup() {
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import ru.mskobaro.tdms.domain.service.SysInfoService;
|
||||
import ru.mskobaro.tdms.business.service.SysInfoService;
|
||||
|
||||
@RestController
|
||||
@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 lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.mskobaro.tdms.domain.service.AuthenticationService;
|
||||
import ru.mskobaro.tdms.domain.service.UserService;
|
||||
import ru.mskobaro.tdms.presentation.payload.LoginDTO;
|
||||
import ru.mskobaro.tdms.presentation.payload.RegistrationDTO;
|
||||
import ru.mskobaro.tdms.presentation.payload.UserDTO;
|
||||
|
||||
import java.util.List;
|
||||
import ru.mskobaro.tdms.business.entity.User;
|
||||
import ru.mskobaro.tdms.business.service.AuthenticationService;
|
||||
import ru.mskobaro.tdms.business.service.UserService;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.LoginDTO;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.UserDTO;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/user")
|
||||
@ -22,8 +22,11 @@ public class UserController {
|
||||
private UserService userService;
|
||||
|
||||
@GetMapping("/current")
|
||||
public UserDTO getCurrentUser() {
|
||||
return userService.getCallerUserDTO();
|
||||
public ResponseEntity<UserDTO> getCurrentUser() {
|
||||
User user = userService.getCallerUser();
|
||||
return user == null
|
||||
? ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
|
||||
: ResponseEntity.ok(UserDTO.fromEntity(user));
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
@ -35,14 +38,4 @@ public class UserController {
|
||||
public void login(@RequestBody @Valid LoginDTO loginDTO) {
|
||||
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.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.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.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||
import ru.mskobaro.tdms.domain.exception.AccessDeniedException;
|
||||
import ru.mskobaro.tdms.domain.exception.BusinessException;
|
||||
import ru.mskobaro.tdms.presentation.payload.ErrorDTO;
|
||||
import ru.mskobaro.tdms.business.exception.AccessDeniedException;
|
||||
import ru.mskobaro.tdms.business.exception.BusinessException;
|
||||
import ru.mskobaro.tdms.presentation.controller.payload.ErrorDTO;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.http.HttpStatus.*;
|
||||
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
|
||||
@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.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
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.AuthorizeHttpRequestsConfigurer;
|
||||
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.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
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.csrf.CookieCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import ru.mskobaro.tdms.system.web.DevAuthenticationRequestFilter;
|
||||
import ru.mskobaro.tdms.system.web.LoggingRequestFilter;
|
||||
|
||||
import java.time.Duration;
|
||||
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
|
||||
@ -45,27 +42,31 @@ public class SecurityConfig {
|
||||
private Environment environment;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, AuthenticationManager authenticationManager, CorsConfigurationSource cors) throws Exception {
|
||||
if (environment.matchesProfiles("dev")) {
|
||||
httpSecurity.addFilterAfter(new DevAuthenticationRequestFilter(), SecurityContextHolderFilter.class);
|
||||
}
|
||||
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,
|
||||
AuthenticationManager authenticationManager,
|
||||
CorsConfigurationSource cors
|
||||
) throws Exception {
|
||||
return httpSecurity
|
||||
.addFilterAfter(new LoggingRequestFilter(), AnonymousAuthenticationFilter.class)
|
||||
.authorizeHttpRequests(this::configureHttpAuthorization)
|
||||
.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
|
||||
.cors(a -> a.configurationSource(cors))
|
||||
.authenticationManager(authenticationManager)
|
||||
.sessionManagement(cfg -> {
|
||||
cfg.sessionCreationPolicy(SessionCreationPolicy.NEVER);
|
||||
cfg.maximumSessions(1);
|
||||
})
|
||||
.build();
|
||||
.addFilterAfter(new LoggingRequestFilter(), SecurityContextHolderFilter.class)
|
||||
.authorizeHttpRequests(this::configureHttpAuthorization)
|
||||
// .csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.cors(a -> a.configurationSource(cors))
|
||||
.authenticationManager(authenticationManager)
|
||||
.sessionManagement(cfg -> {
|
||||
cfg.sessionCreationPolicy(SessionCreationPolicy.NEVER);
|
||||
cfg.maximumSessions(1);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@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.setAllowedMethods(List.of(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name()));
|
||||
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
|
||||
@ -78,14 +79,21 @@ public class SecurityConfig {
|
||||
}
|
||||
|
||||
log.info("CORS configuration: [headers: {}, methods: {}, origins: {}, credentials: {}, maxAge: {}]",
|
||||
corsConfiguration.getAllowedHeaders(), corsConfiguration.getAllowedMethods(), corsConfiguration.getAllowedOrigins(),
|
||||
corsConfiguration.getAllowCredentials(), corsConfiguration.getMaxAge());
|
||||
corsConfiguration.getAllowedHeaders(), corsConfiguration.getAllowedMethods(), corsConfiguration.getAllowedOrigins(),
|
||||
corsConfiguration.getAllowCredentials(), corsConfiguration.getMaxAge());
|
||||
return request -> corsConfiguration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
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
|
||||
@ -93,32 +101,42 @@ public class SecurityConfig {
|
||||
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
}
|
||||
|
||||
private void configureHttpAuthorization(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry httpAuthorization) {
|
||||
/* SysInfoController */
|
||||
private void configureHttpAuthorization(
|
||||
AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry httpAuthorization
|
||||
) {
|
||||
httpAuthorization.requestMatchers("/api/v1/sysinfo/**").permitAll();
|
||||
/* UserController */
|
||||
|
||||
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/get-all").hasAuthority(ADMIN.getAuthority());
|
||||
httpAuthorization.requestMatchers("/api/v1/user/register").hasAuthority(ADMIN.getAuthority());
|
||||
httpAuthorization.requestMatchers("/api/v1/user/validate-registration").hasAuthority(ADMIN.getAuthority());
|
||||
/* StudentController */
|
||||
httpAuthorization.requestMatchers("/api/v1/student/current").permitAll();
|
||||
httpAuthorization.requestMatchers("api/v1/student/by-user-id").hasAnyAuthority(
|
||||
SECRETARY.getAuthority(), ADMIN.getAuthority(), STUDENT.getAuthority(), TEACHER.getAuthority());
|
||||
/* GroupController */
|
||||
|
||||
httpAuthorization.requestMatchers("/api/v1/participant/get-all-participants").permitAll();
|
||||
httpAuthorization.requestMatchers("/api/v1/participant/get-possible-curators").permitAll();
|
||||
// Сложная логика авторизации, так что проверяем явно в ParticipantService
|
||||
httpAuthorization.requestMatchers("/api/v1/participant/save").authenticated();
|
||||
httpAuthorization.requestMatchers("/api/v1/participant/delete").hasAuthority(ADMIN.getAuthority());
|
||||
|
||||
httpAuthorization.requestMatchers("/api/v1/group/get-all-groups").permitAll();
|
||||
httpAuthorization.requestMatchers("/api/v1/group/create-group").hasAuthority(ADMIN.getAuthority());
|
||||
/* deny all other api requests */
|
||||
httpAuthorization.requestMatchers("/api/v1/group/save").hasAnyAuthority(ADMIN.getAuthority(), SECRETARY.getAuthority());
|
||||
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();
|
||||
/* since api already blocked, all other requests are static resources */
|
||||
|
||||
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.HttpSession;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public class LoggingRequestFilter extends OncePerRequestFilter {
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
long startTime = System.currentTimeMillis();
|
||||
String username = SecurityContextHolder.getContext().getAuthentication() != null ?
|
||||
SecurityContextHolder.getContext().getAuthentication().getName() : "anonymousUser";
|
||||
HttpSession session = request.getSession(false);
|
||||
log.info("Request received: [{}] {} user: {}, session: {}, remote ip: {}",
|
||||
request.getMethod(), request.getRequestURI(), request.getRemoteUser(),
|
||||
session == null ? "no" : session.getId(), request.getRemoteAddr());
|
||||
log.info("Request received: [{}] {} user: {}, session: {}, remote ip: {} [{}]",
|
||||
request.getMethod(), request.getRequestURI(), username,
|
||||
session == null ? "no" : session.getId(), request.getRemoteAddr(), uuid);
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
} finally {
|
||||
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}
|
||||
banner:
|
||||
location: banner.txt
|
||||
web:
|
||||
resources:
|
||||
static-locations: classpath:/static/
|
||||
# autoconfigure:
|
||||
# exclude: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
|
||||
server:
|
||||
port: ${application.port}
|
||||
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