Compare commits

...

2 Commits

Author SHA1 Message Date
Pierre Tellier
1cebebf1a5 feat: implemented most of the backend api for administrator
Some checks failed
Format / formatting (push) Failing after 6s
CI / build (push) Successful in 11s
2025-02-26 14:29:38 +01:00
Pierre Tellier
d8bc7cc9b6 feat: added log4j. It's way better than System.stderr. 2025-02-26 14:28:31 +01:00
13 changed files with 188 additions and 88 deletions

View File

@ -1,33 +1,35 @@
plugins { plugins {
id 'java' id 'java'
id 'org.springframework.boot' version '3.4.2' id 'org.springframework.boot' version '3.4.2'
id 'io.spring.dependency-management' version '1.1.7' id 'io.spring.dependency-management' version '1.1.7'
} }
group = 'enseirb' group = 'enseirb'
version = '0.0.1-SNAPSHOT' version = '0.0.1-SNAPSHOT'
java { java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(21) languageVersion = JavaLanguageVersion.of(21)
} }
} }
repositories { repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-data-rest' implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.postgresql:postgresql' implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.16.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.16.0'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
} }
tasks.named('test') { tasks.named('test') {
useJUnitPlatform() useJUnitPlatform()
} }

View File

@ -26,8 +26,8 @@ public class AdminApi {
* @return a list of all project managed by the current admin user * @return a list of all project managed by the current admin user
*/ */
@GetMapping("/admin/projects") @GetMapping("/admin/projects")
public Iterable<Administrator> getProjects() { public Iterable<Project> getProjects(@AuthenticationPrincipal Jwt principal) {
return adminApiService.getProjects(); return adminApiService.getProjectsOfAdmin(principal.getClaimAsString("email"));
} }
/** /**
@ -53,7 +53,7 @@ public class AdminApi {
/** /**
* Endpoint used to make a decision about a project. * Endpoint used to make a decision about a project.
* *
* <p>The decision must contains the administrator * <p>The decision must contain the administrator
* *
* @return the status code of the request * @return the status code of the request
*/ */
@ -96,7 +96,7 @@ public class AdminApi {
* @return the status code of the request * @return the status code of the request
*/ */
@DeleteMapping("/admin/projects/remove/{projectId}") @DeleteMapping("/admin/projects/remove/{projectId}")
public void deleteProject(@PathVariable String projectId) { public void deleteProject(@PathVariable long projectId) {
adminApiService.deleteProject(projectId); adminApiService.deleteProject(projectId);
} }
} }

View File

@ -11,34 +11,26 @@ import java.util.List;
@Table(name = "project") @Table(name = "project")
public class Project { public class Project {
@OneToMany(mappedBy = "projectParticipation", fetch = FetchType.LAZY, orphanRemoval = true)
private final List<Entrepreneur> listEntrepreneurParticipation = new ArrayList<>();
@OneToMany(mappedBy = "projectSectionCell", fetch = FetchType.LAZY, orphanRemoval = true)
private final List<SectionCell> listSectionCell = new ArrayList<>();
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idProject; private Long idProject;
@Column(length = 255) @Column(length = 255)
private String projectName; private String projectName;
private byte[] logo; private byte[] logo;
private LocalDate creationDate; private LocalDate creationDate;
@Column(length = 255) @Column(length = 255)
private String projectStatus; private String projectStatus;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "idAdministrator") @JoinColumn(name = "idAdministrator")
private Administrator projectAdministrator; private Administrator projectAdministrator;
@OneToMany(mappedBy = "projectParticipation", fetch = FetchType.LAZY, orphanRemoval = true)
private List<Entrepreneur> listEntrepreneurParticipation = new ArrayList<>();
@OneToOne(mappedBy = "projectProposed", fetch = FetchType.LAZY, orphanRemoval = true) @OneToOne(mappedBy = "projectProposed", fetch = FetchType.LAZY, orphanRemoval = true)
private Entrepreneur entrepreneurProposed; private Entrepreneur entrepreneurProposed;
@OneToMany(mappedBy = "projectSectionCell", fetch = FetchType.LAZY, orphanRemoval = true)
private List<SectionCell> listSectionCell = new ArrayList<>();
public Project() {} public Project() {}
public Project( public Project(
@ -93,4 +85,8 @@ public class Project {
public void setProjectStatus(String projectStatus) { public void setProjectStatus(String projectStatus) {
this.projectStatus = projectStatus; this.projectStatus = projectStatus;
} }
public void setAdministrator(Administrator administrator) {
this.projectAdministrator = administrator;
}
} }

View File

@ -1,7 +1,7 @@
package enseirb.myinpulse.model; package enseirb.myinpulse.model;
public class ProjectDecision { public class ProjectDecision {
int projectId; public long projectId;
int adminId; public long adminId;
int isAccepted; public long isAccepted;
} }

View File

@ -20,7 +20,7 @@ public class User {
private String userName; private String userName;
@Column(length = 255) @Column(length = 255)
private String mainMail; private String primaryMail;
@Column(length = 255) @Column(length = 255)
private String secondaryMail; private String secondaryMail;
@ -34,13 +34,13 @@ public class User {
Long idUser, Long idUser,
String userSurname, String userSurname,
String userName, String userName,
String mainMail, String primaryMail,
String secondaryMail, String secondaryMail,
String phoneNumber) { String phoneNumber) {
this.idUser = idUser; this.idUser = idUser;
this.userSurname = userSurname; this.userSurname = userSurname;
this.userName = userName; this.userName = userName;
this.mainMail = mainMail; this.primaryMail = primaryMail;
this.secondaryMail = secondaryMail; this.secondaryMail = secondaryMail;
this.phoneNumber = phoneNumber; this.phoneNumber = phoneNumber;
} }
@ -69,12 +69,12 @@ public class User {
userName = userName; userName = userName;
} }
public String getMainMail() { public String getPrimaryMail() {
return mainMail; return primaryMail;
} }
public void setMainMail(String mainMail) { public void setPrimaryMail(String mainMail) {
this.mainMail = mainMail; this.primaryMail = mainMail;
} }
public String getSecondaryMail() { public String getSecondaryMail() {

View File

@ -1,9 +1,14 @@
package enseirb.myinpulse.repository; package enseirb.myinpulse.repository;
import enseirb.myinpulse.model.Administrator;
import enseirb.myinpulse.model.Project; import enseirb.myinpulse.model.Project;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource @RepositoryRestResource
public interface ProjectRepository extends JpaRepository<Project, Long> {} public interface ProjectRepository extends JpaRepository<Project, Long> {
Iterable<Project> findByProjectAdministrator(Administrator administrator);
Iterable<Project> findByProjectStatus(String status);
}

View File

@ -5,8 +5,11 @@ import enseirb.myinpulse.model.User;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import java.util.Optional;
@RepositoryRestResource @RepositoryRestResource
public interface UserRepository extends JpaRepository<User, Long> { public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByPrimaryMail(String email);
/* @Query("SELECT u from User u") /* @Query("SELECT u from User u")
User findAllUser(); */ User findAllUser(); */

View File

@ -1,16 +1,37 @@
package enseirb.myinpulse.service; package enseirb.myinpulse.service;
import enseirb.myinpulse.model.*; import enseirb.myinpulse.model.*;
import enseirb.myinpulse.service.database.AdministratorService;
import enseirb.myinpulse.service.database.ProjectService;
import enseirb.myinpulse.service.database.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
@Service @Service
public class AdminApiService { public class AdminApiService {
// TODO
public Iterable<Administrator> getProjects() { private final ProjectService projectService;
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet"); private final UserService userService;
private final AdministratorService administratorService;
@Autowired
AdminApiService(
ProjectService projectService,
UserService userService,
AdministratorService administratorService) {
this.projectService = projectService;
this.userService = userService;
this.administratorService = administratorService;
}
// TODO: test
public Iterable<Project> getProjectsOfAdmin(String email) {
return projectService.getProjectsByAdminId(
administratorService.getAdministratorById(
this.userService.getIdUserByEmail(email)));
} }
// TODO // TODO
@ -18,19 +39,25 @@ public class AdminApiService {
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet"); throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet");
} }
// TODO // TODO: test
public Iterable<Project> getPendingProjects() { public Iterable<Project> getPendingProjects() {
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet"); return this.projectService.getPendingProjects();
} }
// TODO // TODO: test
public void validateProject(ProjectDecision decision) { public void validateProject(ProjectDecision decision) {
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet"); projectService.updateProject(
decision.projectId,
null,
null,
null,
"ACTIVE",
this.administratorService.getAdministratorById(decision.projectId));
} }
// TODO // TODO: solve todo + test
public void addNewProject(Project project) { public void addNewProject(Project project) {
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet"); projectService.addNewProject(project); // TODO: how can the user know the ID ?
} }
// TODO // TODO
@ -38,8 +65,8 @@ public class AdminApiService {
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet"); throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet");
} }
// TODO // TODO: test
public void deleteProject(String projectId) { public void deleteProject(long projectId) {
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet"); this.projectService.deleteProjectById(projectId);
} }
} }

View File

@ -1,38 +1,43 @@
package enseirb.myinpulse.service.database.old_controllers_to_convert_to_services; package enseirb.myinpulse.service.database;
import enseirb.myinpulse.model.Administrator; import enseirb.myinpulse.model.Administrator;
import enseirb.myinpulse.repository.AdministratorRepository; import enseirb.myinpulse.repository.AdministratorRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*; import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
import java.util.Optional; import java.util.Optional;
@RestController @Service
public class AdministratorController { public class AdministratorService {
protected static final Logger logger = LogManager.getLogger();
@Autowired AdministratorRepository administratorRepository; private final AdministratorRepository administratorRepository;
@Autowired
AdministratorService(AdministratorRepository administratorRepository) {
this.administratorRepository = administratorRepository;
}
@GetMapping("/Administrator")
@ResponseBody
public Iterable<Administrator> allAdministrators() { public Iterable<Administrator> allAdministrators() {
return this.administratorRepository.findAll(); return this.administratorRepository.findAll();
} }
@GetMapping("/Administrator/{id}") public Administrator getAdministratorById(long id) {
public Administrator getAdministratorById(@PathVariable Long id) {
Optional<Administrator> administrator = this.administratorRepository.findById(id); Optional<Administrator> administrator = this.administratorRepository.findById(id);
if (administrator.isEmpty()) { if (administrator.isEmpty()) {
logger.error("No administrator found with id {}", id);
throw new ResponseStatusException( throw new ResponseStatusException(
HttpStatus.NOT_FOUND, "Cet administrateur n'existe pas"); HttpStatus.NOT_FOUND, "Cet administrateur n'existe pas");
} }
return administrator.get(); return administrator.get();
} }
@PostMapping("/Administrateurs") public Administrator addAdministrator(Administrator administrator) {
public Administrator addAdministrator(@RequestBody Administrator administrator) {
return this.administratorRepository.save(administrator); return this.administratorRepository.save(administrator);
} }
} }

View File

@ -1,19 +1,25 @@
package enseirb.myinpulse.service.database; package enseirb.myinpulse.service.database;
import enseirb.myinpulse.model.Administrator;
import enseirb.myinpulse.model.Project; import enseirb.myinpulse.model.Project;
import enseirb.myinpulse.repository.ProjectRepository; import enseirb.myinpulse.repository.ProjectRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List;
import java.util.Optional; import java.util.Optional;
@Service @Service
public class ProjectService { public class ProjectService {
protected static final Logger logger = LogManager.getLogger();
private final ProjectRepository projectRepository; private final ProjectRepository projectRepository;
@Autowired @Autowired
@ -25,15 +31,19 @@ public class ProjectService {
return this.projectRepository.findAll(); return this.projectRepository.findAll();
} }
// TODO: change error
public Project getProjectById(Long id) { public Project getProjectById(Long id) {
Optional<Project> project = this.projectRepository.findById(id); Optional<Project> project = this.projectRepository.findById(id);
if (project.isEmpty()) { if (project.isEmpty()) {
System.err.println("Project with id " + id + " not found");
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Ce projet n'existe pas"); throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Ce projet n'existe pas");
} }
return project.get(); return project.get();
} }
public Iterable<Project> getProjectsByAdminId(Administrator administrator) {
return this.projectRepository.findByProjectAdministrator(administrator);
}
// TODO: validation // TODO: validation
public Project addNewProject(Project project) { public Project addNewProject(Project project) {
return this.projectRepository.save(project); return this.projectRepository.save(project);
@ -44,23 +54,52 @@ public class ProjectService {
String projectName, String projectName,
byte[] logo, byte[] logo,
LocalDate creationDate, LocalDate creationDate,
String projectStatus) { String projectStatus,
Administrator administrator) {
Optional<Project> project = this.projectRepository.findById(id); Optional<Project> project = this.projectRepository.findById(id);
if (project.isEmpty()) { if (project.isEmpty()) {
logger.error("Project with id {} not found.", id);
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Ce projet n'existe pas"); throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Ce projet n'existe pas");
} }
if (projectName != null) { if (projectName != null) {
project.get().setProjectName(projectName); project.get().setProjectName(projectName);
} }
if (logo != null) { if (logo != null) {
project.get().setLogo(logo); project.get().setLogo(logo);
} }
if (creationDate != null) { if (creationDate != null) {
project.get().setCreationDate(creationDate); project.get().setCreationDate(creationDate);
} }
if (projectStatus != null) { if (projectStatus != null) {
if (!validateStatus(projectStatus)) {
System.err.println("updateProjectStatus: Invalid status " + projectStatus);
throw new ResponseStatusException(
HttpStatus.NOT_ACCEPTABLE, "Ce status n'est pas accepté");
}
project.get().setProjectStatus(projectStatus); project.get().setProjectStatus(projectStatus);
} }
if (administrator != null) {
project.get().setAdministrator(administrator);
}
return this.projectRepository.save(project.get()); return this.projectRepository.save(project.get());
} }
public Boolean validateStatus(String status) {
return List.of("PENDING", "ACTIVE", "ENDED").contains(status);
}
public Iterable<Project> getPendingProjects() {
return this.projectRepository.findByProjectStatus("PENDING");
}
public void deleteProjectById(Long id) {
this.projectRepository.deleteById(id);
}
} }

View File

@ -1,41 +1,50 @@
package enseirb.myinpulse.service.database.old_controllers_to_convert_to_services; package enseirb.myinpulse.service.database;
import enseirb.myinpulse.model.User; import enseirb.myinpulse.model.User;
import enseirb.myinpulse.repository.UserRepository; import enseirb.myinpulse.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*; import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
import java.util.Optional; import java.util.Optional;
@RestController @Service
public class UserController { public class UserService {
private final UserRepository userRepository;
@Autowired UserRepository userRepository; @Autowired
UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public Iterable<User> getAllUsers() {
return this.userRepository.findAll();
}
// TODO
public long getIdUserByEmail(String email) {
Optional<User> opt_user = this.userRepository.findByPrimaryMail(email);
if (opt_user.isEmpty()) {
System.err.println("Couldn't find user with email " + email);
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
User user = opt_user.get();
return user.getIdUser();
}
@GetMapping("/User")
@ResponseBody
public Iterable<User> allUsers() { public Iterable<User> allUsers() {
return this.userRepository.findAll(); return this.userRepository.findAll();
} }
@GetMapping("/User/{id}")
public User getUserById(@PathVariable Long id) {
Optional<User> user = userRepository.findById(id);
if (user.isEmpty()) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Cet utilisateur n'existe pas");
}
return user.get();
}
@PostMapping("/User")
public User addUser(@RequestBody User user) { public User addUser(@RequestBody User user) {
return this.userRepository.save(user); return this.userRepository.save(user);
} }
@PostMapping("/User/{id}")
public User updateUser( public User updateUser(
@PathVariable Long id, @PathVariable Long id,
String userSurname, String userSurname,
@ -54,7 +63,7 @@ public class UserController {
user.get().setUserSurname(userSurname); user.get().setUserSurname(userSurname);
} }
if (mainMail != null) { if (mainMail != null) {
user.get().setMainMail(mainMail); user.get().setPrimaryMail(mainMail);
} }
if (secondaryMail != null) { if (secondaryMail != null) {
user.get().setSecondaryMail(secondaryMail); user.get().setSecondaryMail(secondaryMail);

View File

@ -8,7 +8,7 @@ SELECT setval('report_id_report_seq', 1, false);
SELECT setval('section_cell_id_section_cell_seq', 1, false); SELECT setval('section_cell_id_section_cell_seq', 1, false);
SELECT setval('user_inpulse_id_user_seq', 1, false); SELECT setval('user_inpulse_id_user_seq', 1, false);
INSERT INTO user_inpulse (user_surname, user_name, main_mail, secondary_mail, phone_number) INSERT INTO user_inpulse (user_surname, user_name, primary_mail, secondary_mail, phone_number)
VALUES ('Dupont', 'Dupond', 'super@mail.fr', 'super2@mail.fr', '06 45 72 45 98'), VALUES ('Dupont', 'Dupond', 'super@mail.fr', 'super2@mail.fr', '06 45 72 45 98'),
('Martin', 'Matin', 'genial@mail.fr', 'genial2@mail.fr', '06 52 14 58 73'), ('Martin', 'Matin', 'genial@mail.fr', 'genial2@mail.fr', '06 52 14 58 73'),
('Charvet', 'Lautre', 'mieux@tmail.fr', 'mieux2@tmail.fr', '07 49 82 16 35'), ('Charvet', 'Lautre', 'mieux@tmail.fr', 'mieux2@tmail.fr', '07 49 82 16 35'),

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="console"/>
</Root>
</Loggers>
</Configuration>