Compare commits
57 Commits
openapi_in
...
backend-te
Author | SHA1 | Date | |
---|---|---|---|
f3c5401b07 | |||
f2448a029f | |||
d4533ea725 | |||
255af7ee7f | |||
3b308cfa6d | |||
d31bf259dd | |||
43b40c9432 | |||
e84f69c21a | |||
c76e83f2bf | |||
1f0f9196c4 | |||
40e577ef07 | |||
13845394e3 | |||
f4589c6306 | |||
6004bce4e8 | |||
0730275e75 | |||
5183a088e7 | |||
b503cae235 | |||
fcf4e1c01d | |||
3f18304028 | |||
bbb4debcd8 | |||
6f7fc70c4c | |||
3d57ecb01a | |||
3673aa379c | |||
b672b2e9f9 | |||
193876e51c | |||
b8c7c6f587 | |||
bee47473d5 | |||
e7739af80b | |||
32557f8f87 | |||
8ee06b93a6 | |||
6861d07dfc | |||
8403bc0592 | |||
5edcf9ffc8 | |||
5615b0fb11 | |||
8a13993d8a | |||
561f6d16b3 | |||
832539f43b | |||
dfea20b9c4 | |||
f96872fb6b | |||
0140672812 | |||
7df2c768c8 | |||
6029457735 | |||
55112c8508 | |||
676f1204cb | |||
66be0baca6 | |||
7e1271cfe2 | |||
801ecb3817 | |||
cc89d4c79f | |||
adf9a93e2e | |||
37d8bcc719 | |||
385c5cd8d0 | |||
b672dd200c | |||
9e1f568ea4 | |||
aaa6e46d0c | |||
9b9cfbdb2e | |||
5b6b647697 | |||
ead11215ba |
@ -25,9 +25,8 @@ jobs:
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
with:
|
||||
cache-disabled: true # Once the code has been pushed once in main, this should be reenabled.
|
||||
|
||||
- name: init gradle
|
||||
working-directory: ./MyINPulse-back/
|
||||
run: ./gradlew build # todo: run test, currently fail because no database is present
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,7 +1,9 @@
|
||||
.env
|
||||
.idea
|
||||
keycloak/CAS/target
|
||||
keycloak/.installed
|
||||
docker-compose.yaml
|
||||
node_modules
|
||||
.vscode
|
||||
postgres/data
|
||||
bundled.yaml
|
||||
|
1
Makefile
1
Makefile
@ -2,6 +2,7 @@ help:
|
||||
@echo "make [clean dev-front prod dev-back dev]"
|
||||
|
||||
clean:
|
||||
pkill -9 node
|
||||
@cp config/frontdev.env front/MyINPulse-front/.env
|
||||
@cp config/frontdev.env .env
|
||||
@cp config/frontdev.env MyINPulse-back/.env
|
||||
|
@ -31,7 +31,7 @@ public class WebSecurityCustomConfiguration {
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOrigins(List.of(frontendUrl));
|
||||
configuration.setAllowedMethods(Arrays.asList("GET", "OPTIONS"));
|
||||
configuration.setAllowedMethods(Arrays.asList("GET", "OPTIONS", "POST", "PUT", "DELETE"));
|
||||
configuration.setAllowedHeaders(
|
||||
Arrays.asList("authorization", "content-type", "x-auth-token"));
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
@ -56,14 +56,18 @@ public class WebSecurityCustomConfiguration {
|
||||
http.authorizeHttpRequests(
|
||||
authorize ->
|
||||
authorize
|
||||
.requestMatchers("/entrepreneur/**", "/shared/**")
|
||||
.requestMatchers("/entrepreneur/**")
|
||||
.access(hasRole("REALM_MyINPulse-entrepreneur"))
|
||||
.requestMatchers("/admin/**", "/shared/**")
|
||||
.requestMatchers("/admin/**")
|
||||
.access(hasRole("REALM_MyINPulse-admin"))
|
||||
.requestMatchers("/shared/**")
|
||||
.hasAnyRole(
|
||||
"REALM_MyINPulse-admin",
|
||||
"REALM_MyINPulse-entrepreneur")
|
||||
.requestMatchers("/unauth/**")
|
||||
.permitAll()
|
||||
.authenticated()
|
||||
.anyRequest()
|
||||
.authenticated())
|
||||
.denyAll())
|
||||
.oauth2ResourceServer(
|
||||
oauth2 ->
|
||||
oauth2.jwt(
|
||||
|
@ -57,7 +57,7 @@ public class AdminApi {
|
||||
*
|
||||
* @return the status code of the request
|
||||
*/
|
||||
@PostMapping("/admin/projects/decision")
|
||||
@PostMapping("/admin/projects/pending/decision")
|
||||
public void validateProject(@RequestBody ProjectDecision decision) {
|
||||
adminApiService.validateProject(decision);
|
||||
}
|
||||
@ -67,7 +67,7 @@ public class AdminApi {
|
||||
*
|
||||
* @return the status code of the request
|
||||
*/
|
||||
@PostMapping("/admin/project/add")
|
||||
@PostMapping("/admin/project")
|
||||
public void addNewProject(@RequestBody Project project) {
|
||||
adminApiService.addNewProject(project);
|
||||
}
|
||||
@ -79,7 +79,7 @@ public class AdminApi {
|
||||
*
|
||||
* @return the status code of the request
|
||||
*/
|
||||
@PostMapping("/admin/appoitements/report/{appointmentId}")
|
||||
@PostMapping("/admin/appointments/report/{appointmentId}")
|
||||
public void createAppointmentReport(
|
||||
@PathVariable long appointmentId,
|
||||
@RequestBody Report report,
|
||||
@ -95,8 +95,35 @@ public class AdminApi {
|
||||
*
|
||||
* @return the status code of the request
|
||||
*/
|
||||
@DeleteMapping("/admin/projects/remove/{projectId}")
|
||||
@DeleteMapping("/admin/projects/{projectId}")
|
||||
public void deleteProject(@PathVariable long projectId) {
|
||||
adminApiService.deleteProject(projectId);
|
||||
}
|
||||
|
||||
@PostMapping("/admin/make-admin/{userId}")
|
||||
public void setAdmin(@PathVariable long userId, @AuthenticationPrincipal Jwt principal) {
|
||||
this.adminApiService.setAdmin(userId, principal.getTokenValue());
|
||||
}
|
||||
|
||||
@PostMapping("/admin/accounts/validate/{userId}")
|
||||
public void validateEntrepreneurAcc(
|
||||
@PathVariable long userId, @AuthenticationPrincipal Jwt principal) {
|
||||
this.adminApiService.validateEntrepreneurAccount(userId, principal.getTokenValue());
|
||||
}
|
||||
|
||||
@GetMapping("/admin/pending-accounts")
|
||||
public Iterable<User> validateEntrepreneurAcc() {
|
||||
return this.adminApiService.getPendingUsers();
|
||||
}
|
||||
|
||||
@PostMapping("/admin/create-account")
|
||||
public void createAccount(@AuthenticationPrincipal Jwt principal) {
|
||||
String userSurname = principal.getClaimAsString("userSurname");
|
||||
String username = principal.getClaimAsString("preferred_username");
|
||||
String primaryMail = principal.getClaimAsString("email");
|
||||
String secondaryMail = principal.getClaimAsString("secondaryMail");
|
||||
String phoneNumber = principal.getClaimAsString("phoneNumber");
|
||||
this.adminApiService.createAccount(
|
||||
userSurname, username, primaryMail, secondaryMail, phoneNumber);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,20 @@
|
||||
package enseirb.myinpulse.controller;
|
||||
|
||||
import enseirb.myinpulse.model.SectionCell;
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.service.EntrepreneurApiService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.model.SectionCell;
|
||||
import enseirb.myinpulse.service.EntrepreneurApiService;
|
||||
|
||||
@SpringBootApplication
|
||||
@RestController
|
||||
@ -28,13 +34,26 @@ public class EntrepreneurApi {
|
||||
*
|
||||
* @return status code
|
||||
*/
|
||||
@PutMapping("/entrepreneur/lcsection/modify/{sectionId}")
|
||||
@PutMapping("/entrepreneur/sectionCells/{sectionCellId}")
|
||||
public void editSectionCell(
|
||||
@PathVariable Long sectionId,
|
||||
@RequestBody SectionCell sectionCell,
|
||||
@PathVariable Long sectionCellId,
|
||||
@RequestBody String content,
|
||||
@AuthenticationPrincipal Jwt principal) {
|
||||
entrepreneurApiService.editSectionCell(
|
||||
sectionId, sectionCell, principal.getClaimAsString("email"));
|
||||
sectionCellId, content, principal.getClaimAsString("email"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint used to update a LC section.
|
||||
*
|
||||
* @return status code
|
||||
*/
|
||||
@GetMapping("/entrepreneur/projects")
|
||||
public Iterable<Project> getEntrepreneurProjectId(
|
||||
@PathVariable Long sectionCellId,
|
||||
@RequestBody String content,
|
||||
@AuthenticationPrincipal Jwt principal) {
|
||||
return entrepreneurApiService.getProjectIdViaClaim(principal.getClaimAsString("email"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,10 +63,11 @@ public class EntrepreneurApi {
|
||||
*
|
||||
* @return status code
|
||||
*/
|
||||
@DeleteMapping("/entrepreneur/lcsection/remove/{sectionId}")
|
||||
@DeleteMapping("/entrepreneur/sectionCells/{sectionCellId}")
|
||||
public void removeSectionCell(
|
||||
@PathVariable Long sectionId, @AuthenticationPrincipal Jwt principal) {
|
||||
entrepreneurApiService.removeSectionCell(sectionId, principal.getClaimAsString("email"));
|
||||
@PathVariable Long sectionCellId, @AuthenticationPrincipal Jwt principal) {
|
||||
entrepreneurApiService.removeSectionCell(
|
||||
sectionCellId, principal.getClaimAsString("email"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,7 +77,7 @@ public class EntrepreneurApi {
|
||||
*
|
||||
* @return status code
|
||||
*/
|
||||
@PostMapping("/entrepreneur/lcsection/add") // remove id from doc aswell
|
||||
@PostMapping("/entrepreneur/sectionCells")
|
||||
public void addLCSection(
|
||||
@RequestBody SectionCell sectionCell, @AuthenticationPrincipal Jwt principal) {
|
||||
entrepreneurApiService.addSectionCell(sectionCell, principal.getClaimAsString("email"));
|
||||
@ -70,9 +90,27 @@ public class EntrepreneurApi {
|
||||
*
|
||||
* @return status code
|
||||
*/
|
||||
@PostMapping("/entrepreneur/project/request")
|
||||
@PostMapping("/entrepreneur/projects/request")
|
||||
public void requestNewProject(
|
||||
@RequestBody Project project, @AuthenticationPrincipal Jwt principal) {
|
||||
entrepreneurApiService.requestNewProject(project, principal.getClaimAsString("email"));
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Endpoint to check if project is has already been validated by an admin
|
||||
*/
|
||||
@GetMapping("/entrepreneur/projects/project-is-active")
|
||||
public Boolean checkIfProjectValidated(@AuthenticationPrincipal Jwt principal) {
|
||||
return entrepreneurApiService.checkIfEntrepreneurProjectActive(
|
||||
principal.getClaimAsString("email"));
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Endpoint to check if a user requested a project (used when project is pending)
|
||||
*/
|
||||
@GetMapping("/entrepreneur/projects/has-pending-request")
|
||||
public Boolean checkIfHasRequested(@AuthenticationPrincipal Jwt principal) {
|
||||
return entrepreneurApiService.entrepreneurHasPendingRequestedProject(
|
||||
principal.getClaimAsString("email"));
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class SharedApi {
|
||||
*
|
||||
* @return a list of lean canvas sections
|
||||
*/
|
||||
@GetMapping("/shared/project/lcsection/{projectId}/{sectionId}/{date}")
|
||||
@GetMapping("/shared/projects/sectionCells/{projectId}/{sectionId}/{date}")
|
||||
public Iterable<SectionCell> getLCSection(
|
||||
@PathVariable("projectId") Long projectId,
|
||||
@PathVariable("sectionId") Long sectionId,
|
||||
@ -45,7 +45,7 @@ public class SharedApi {
|
||||
*
|
||||
* @return a list of all entrepreneurs in a project
|
||||
*/
|
||||
@GetMapping("/shared/entrepreneurs/{projectId}")
|
||||
@GetMapping("/shared/projects/entrepreneurs/{projectId}")
|
||||
public Iterable<Entrepreneur> getEntrepreneursByProjectId(
|
||||
@PathVariable int projectId, @AuthenticationPrincipal Jwt principal) {
|
||||
return sharedApiService.getEntrepreneursByProjectId(
|
||||
@ -80,7 +80,7 @@ public class SharedApi {
|
||||
*
|
||||
* @return a PDF file? TODO: how does that works ?
|
||||
*/
|
||||
@GetMapping("/shared/projects/appointments/report/{appointmentId}")
|
||||
@GetMapping("/shared/appointments/report/{appointmentId}")
|
||||
public void getPDFReport(
|
||||
@PathVariable int appointmentId, @AuthenticationPrincipal Jwt principal) {
|
||||
try {
|
||||
@ -97,7 +97,7 @@ public class SharedApi {
|
||||
/**
|
||||
* @return TODO
|
||||
*/
|
||||
@PostMapping("/shared/appointment/request")
|
||||
@PostMapping("/shared/appointments/request")
|
||||
public void createAppointmentRequest(
|
||||
@RequestBody Appointment appointment, @AuthenticationPrincipal Jwt principal) {
|
||||
sharedApiService.createAppointmentRequest(appointment, principal.getClaimAsString("email"));
|
||||
|
@ -0,0 +1,61 @@
|
||||
package enseirb.myinpulse.controller;
|
||||
|
||||
import enseirb.myinpulse.model.Entrepreneur;
|
||||
import enseirb.myinpulse.service.EntrepreneurApiService;
|
||||
import enseirb.myinpulse.service.UtilsService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@SpringBootApplication
|
||||
@RestController
|
||||
public class UnauthApi {
|
||||
|
||||
private final EntrepreneurApiService entrepreneurApiService;
|
||||
private final UtilsService utilsService;
|
||||
|
||||
@Autowired
|
||||
UnauthApi(EntrepreneurApiService entrepreneurApiService, UtilsService utilsService) {
|
||||
this.entrepreneurApiService = entrepreneurApiService;
|
||||
this.utilsService = utilsService;
|
||||
}
|
||||
|
||||
@PostMapping("/unauth/finalize")
|
||||
public void createAccount(@AuthenticationPrincipal Jwt principal) {
|
||||
boolean sneeStatus;
|
||||
if (principal.getClaimAsString("sneeStatus") != null) {
|
||||
sneeStatus = principal.getClaimAsString("sneeStatus").equals("true");
|
||||
} else {
|
||||
sneeStatus = false;
|
||||
}
|
||||
String userSurname = principal.getClaimAsString("userSurname");
|
||||
String username = principal.getClaimAsString("preferred_username");
|
||||
String primaryMail = principal.getClaimAsString("email");
|
||||
String secondaryMail = principal.getClaimAsString("secondaryMail");
|
||||
String phoneNumber = principal.getClaimAsString("phoneNumber");
|
||||
String school = principal.getClaimAsString("school");
|
||||
String course = principal.getClaimAsString("course");
|
||||
Entrepreneur e =
|
||||
new Entrepreneur(
|
||||
userSurname,
|
||||
username,
|
||||
primaryMail,
|
||||
secondaryMail,
|
||||
phoneNumber,
|
||||
school,
|
||||
course,
|
||||
sneeStatus,
|
||||
true);
|
||||
|
||||
entrepreneurApiService.createAccount(e);
|
||||
}
|
||||
|
||||
@GetMapping("/unauth/check-if-not-pending")
|
||||
public Boolean checkAccountStatus(@AuthenticationPrincipal Jwt principal) {
|
||||
// Throws 404 if user not found
|
||||
return utilsService.checkEntrepreneurNotPending(principal.getClaimAsString("email"));
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ public class Administrator extends User {
|
||||
String primaryMail,
|
||||
String secondaryMail,
|
||||
String phoneNumber) {
|
||||
super(null, userSurname, username, primaryMail, secondaryMail, phoneNumber);
|
||||
super(userSurname, username, primaryMail, secondaryMail, phoneNumber, false);
|
||||
}
|
||||
|
||||
public List<Project> getListProject() {
|
||||
|
@ -44,15 +44,30 @@ public class Entrepreneur extends User {
|
||||
String phoneNumber,
|
||||
String school,
|
||||
String course,
|
||||
boolean sneeStatus) {
|
||||
super(userSurname, username, primaryMail, secondaryMail, phoneNumber);
|
||||
boolean sneeStatus,
|
||||
boolean pending) {
|
||||
super(userSurname, username, primaryMail, secondaryMail, phoneNumber, pending);
|
||||
this.school = school;
|
||||
this.course = course;
|
||||
this.sneeStatus = sneeStatus;
|
||||
}
|
||||
|
||||
public Entrepreneur(
|
||||
String userSurname,
|
||||
String username,
|
||||
String primaryMail,
|
||||
String secondaryMail,
|
||||
String phoneNumber,
|
||||
String school,
|
||||
String course,
|
||||
boolean sneeStatus) {
|
||||
super(userSurname, username, primaryMail, secondaryMail, phoneNumber, true);
|
||||
this.school = school;
|
||||
this.course = course;
|
||||
this.sneeStatus = sneeStatus;
|
||||
}
|
||||
|
||||
public Entrepreneur(
|
||||
Long idUser,
|
||||
String userSurname,
|
||||
String userName,
|
||||
String primaryMail,
|
||||
@ -63,8 +78,9 @@ public class Entrepreneur extends User {
|
||||
boolean sneeStatus,
|
||||
Project projectParticipation,
|
||||
Project projectProposed,
|
||||
MakeAppointment makeAppointment) {
|
||||
super(idUser, userSurname, userName, primaryMail, secondaryMail, phoneNumber);
|
||||
MakeAppointment makeAppointment,
|
||||
boolean pending) {
|
||||
super(userSurname, userName, primaryMail, secondaryMail, phoneNumber, pending);
|
||||
this.school = school;
|
||||
this.course = course;
|
||||
this.sneeStatus = sneeStatus;
|
||||
|
@ -66,6 +66,15 @@ public class Project {
|
||||
this.entrepreneurProposed = entrepreneurProposed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
Project project = (Project) o;
|
||||
return this.idProject == project.idProject;
|
||||
}
|
||||
|
||||
public Long getIdProject() {
|
||||
return idProject;
|
||||
}
|
||||
|
@ -2,6 +2,9 @@ package enseirb.myinpulse.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.generator.EventType;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -20,6 +23,10 @@ public class SectionCell {
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long idSectionCell;
|
||||
|
||||
@Column(columnDefinition = "serial")
|
||||
@Generated(event = EventType.INSERT)
|
||||
private Long idReference;
|
||||
|
||||
@Column() private long sectionId;
|
||||
private String contentSectionCell;
|
||||
|
||||
@ -56,6 +63,14 @@ public class SectionCell {
|
||||
this.idSectionCell = idSectionCell;
|
||||
}
|
||||
|
||||
public Long getIdReference() {
|
||||
return idReference;
|
||||
}
|
||||
|
||||
public void setIdReference(Long idReference) {
|
||||
this.idReference = idReference;
|
||||
}
|
||||
|
||||
public Long getSectionId() {
|
||||
return sectionId;
|
||||
}
|
||||
|
@ -26,36 +26,23 @@ public class User {
|
||||
@Column(length = 20)
|
||||
private String phoneNumber;
|
||||
|
||||
@Column private boolean pending;
|
||||
|
||||
public User() {}
|
||||
|
||||
// TODO: this should be removed as we shouldn't be able to chose the ID. Leaving it for
|
||||
// compatibility purposes, as soon as it's not used anymore, delete it
|
||||
public User(
|
||||
Long idUser,
|
||||
String userSurname,
|
||||
String userName,
|
||||
String primaryMail,
|
||||
String secondaryMail,
|
||||
String phoneNumber) {
|
||||
this.idUser = idUser;
|
||||
this.userSurname = userSurname;
|
||||
this.userName = userName;
|
||||
this.primaryMail = primaryMail;
|
||||
this.secondaryMail = secondaryMail;
|
||||
this.phoneNumber = phoneNumber;
|
||||
}
|
||||
|
||||
public User(
|
||||
String userSurname,
|
||||
String userName,
|
||||
String primaryMail,
|
||||
String secondaryMail,
|
||||
String phoneNumber) {
|
||||
String phoneNumber,
|
||||
boolean pending) {
|
||||
this.userSurname = userSurname;
|
||||
this.userName = userName;
|
||||
this.primaryMail = primaryMail;
|
||||
this.secondaryMail = secondaryMail;
|
||||
this.phoneNumber = phoneNumber;
|
||||
this.pending = pending;
|
||||
}
|
||||
|
||||
public Long getIdUser() {
|
||||
@ -105,4 +92,12 @@ public class User {
|
||||
public void setPhoneNumber(String phoneNumber) {
|
||||
phoneNumber = phoneNumber;
|
||||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return pending;
|
||||
}
|
||||
|
||||
public void setPending(boolean pending) {
|
||||
this.pending = pending;
|
||||
}
|
||||
}
|
||||
|
@ -15,4 +15,6 @@ public interface SectionCellRepository extends JpaRepository<SectionCell, Long>
|
||||
|
||||
Iterable<SectionCell> findByProjectSectionCellAndSectionIdAndModificationDateBefore(
|
||||
Project project, long sectionId, LocalDateTime date);
|
||||
|
||||
Iterable<SectionCell> findByProjectSectionCell(Project project);
|
||||
}
|
||||
|
@ -9,8 +9,9 @@ import java.util.Optional;
|
||||
|
||||
@RepositoryRestResource
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
Optional<User> findByPrimaryMail(String email);
|
||||
Optional<User> findByPrimaryMail(String primaryMail);
|
||||
|
||||
Iterable<User> findAllByPendingEquals(boolean pending);
|
||||
/* @Query("SELECT u from User u")
|
||||
User findAllUser(); */
|
||||
|
||||
|
@ -24,6 +24,7 @@ public class AdminApiService {
|
||||
private final ProjectService projectService;
|
||||
private final UserService userService;
|
||||
private final AdministratorService administratorService;
|
||||
private final EntrepreneurService entrepreneurService;
|
||||
private final UtilsService utilsService;
|
||||
private final AppointmentService appointmentService;
|
||||
private final ReportService reportService;
|
||||
@ -35,6 +36,7 @@ public class AdminApiService {
|
||||
UserService userService,
|
||||
AdministratorService administratorService,
|
||||
UtilsService utilsService,
|
||||
EntrepreneurService entrepreneurService,
|
||||
AppointmentService appointmentService,
|
||||
ReportService reportService,
|
||||
SectionCellService sectionCellService) {
|
||||
@ -45,6 +47,7 @@ public class AdminApiService {
|
||||
this.appointmentService = appointmentService;
|
||||
this.reportService = reportService;
|
||||
this.sectionCellService = sectionCellService;
|
||||
this.entrepreneurService = entrepreneurService;
|
||||
}
|
||||
|
||||
// TODO: check if tests are sufficient - peer verification required
|
||||
@ -75,6 +78,12 @@ public class AdminApiService {
|
||||
}
|
||||
if (user instanceof Entrepreneur) {
|
||||
Project project = ((Entrepreneur) user).getProjectParticipation();
|
||||
if (project == null) {
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.NOT_FOUND,
|
||||
"The user has no project, thus no appointments. No users should have no project");
|
||||
}
|
||||
|
||||
project.getListSectionCell()
|
||||
.forEach(
|
||||
sectionCell -> {
|
||||
@ -97,13 +106,14 @@ public class AdminApiService {
|
||||
decision.projectId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
(decision.isAccepted == 1) ? ACTIVE : REJECTED,
|
||||
null,
|
||||
null,
|
||||
this.administratorService.getAdministratorById(decision.adminId));
|
||||
}
|
||||
|
||||
// TODO: check if tests are sufficient - peer verification required
|
||||
public void addNewProject(Project project) {
|
||||
public Project addNewProject(Project project) {
|
||||
project.setIdProject(null);
|
||||
// We remove the ID from the request to be sure that it will be auto generated
|
||||
try {
|
||||
@ -135,6 +145,7 @@ public class AdminApiService {
|
||||
sectionCell -> {
|
||||
sectionCell.setProjectSectionCell(newProject);
|
||||
});
|
||||
return newProject;
|
||||
}
|
||||
|
||||
public void createAppointmentReport(long appointmentId, Report report, String mail) {
|
||||
@ -163,4 +174,47 @@ public class AdminApiService {
|
||||
public void deleteProject(long projectId) {
|
||||
this.projectService.deleteProjectById(projectId);
|
||||
}
|
||||
|
||||
public void setAdmin(long userId, String token) {
|
||||
Entrepreneur e = this.entrepreneurService.getEntrepreneurById(userId);
|
||||
Administrator a =
|
||||
new Administrator(
|
||||
e.getUserSurname(),
|
||||
e.getUserName(),
|
||||
e.getPrimaryMail(),
|
||||
e.getSecondaryMail(),
|
||||
e.getPhoneNumber());
|
||||
this.entrepreneurService.deleteEntrepreneur(e);
|
||||
this.administratorService.addAdministrator(a);
|
||||
try {
|
||||
KeycloakApi.setRoleToUser(a.getUserName(), "MyINPulse-admin", token);
|
||||
} catch (Exception err) {
|
||||
logger.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
public void validateEntrepreneurAccount(long userId, String token) {
|
||||
Entrepreneur e = this.entrepreneurService.getEntrepreneurById(userId);
|
||||
try {
|
||||
KeycloakApi.setRoleToUser(e.getUserName(), "MyINPulse-entrepreneur", token);
|
||||
} catch (Exception err) {
|
||||
logger.error(err);
|
||||
}
|
||||
this.entrepreneurService.validateEntrepreneurById(userId);
|
||||
}
|
||||
|
||||
public Iterable<User> getPendingUsers() {
|
||||
return this.userService.getPendingAccounts();
|
||||
}
|
||||
|
||||
public void createAccount(
|
||||
String username,
|
||||
String userSurname,
|
||||
String primaryMail,
|
||||
String secondaryMail,
|
||||
String phoneNumber) {
|
||||
Administrator a =
|
||||
new Administrator(username, userSurname, primaryMail, secondaryMail, phoneNumber);
|
||||
this.administratorService.addAdministrator(a);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
package enseirb.myinpulse.service;
|
||||
|
||||
import static enseirb.myinpulse.model.ProjectDecisionValue.PENDING;
|
||||
import static enseirb.myinpulse.model.ProjectDecisionValue.ACTIVE;
|
||||
|
||||
import enseirb.myinpulse.model.Entrepreneur;
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.model.SectionCell;
|
||||
import enseirb.myinpulse.service.database.ProjectService;
|
||||
import enseirb.myinpulse.service.database.SectionCellService;
|
||||
import enseirb.myinpulse.model.User;
|
||||
import enseirb.myinpulse.service.database.*;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -14,6 +16,10 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class EntrepreneurApiService {
|
||||
|
||||
@ -22,24 +28,39 @@ public class EntrepreneurApiService {
|
||||
private final SectionCellService sectionCellService;
|
||||
private final ProjectService projectService;
|
||||
private final UtilsService utilsService;
|
||||
private final UserService userService;
|
||||
private final EntrepreneurService entrepreneurService;
|
||||
private final AdministratorService administratorService;
|
||||
private final AppointmentService appointmentService;
|
||||
private final AnnotationService annotationService;
|
||||
|
||||
@Autowired
|
||||
EntrepreneurApiService(
|
||||
SectionCellService sectionCellService,
|
||||
ProjectService projectService,
|
||||
UtilsService utilsService) {
|
||||
UtilsService utilsService,
|
||||
UserService userService,
|
||||
EntrepreneurService entrepreneurService,
|
||||
AdministratorService administratorService,
|
||||
AppointmentService appointmentService,
|
||||
AnnotationService annotationService) {
|
||||
this.sectionCellService = sectionCellService;
|
||||
this.projectService = projectService;
|
||||
this.utilsService = utilsService;
|
||||
this.userService = userService;
|
||||
this.entrepreneurService = entrepreneurService;
|
||||
this.administratorService = administratorService;
|
||||
this.appointmentService = appointmentService;
|
||||
this.annotationService = annotationService;
|
||||
}
|
||||
|
||||
public void editSectionCell(Long sectionCellId, SectionCell sectionCell, String mail) {
|
||||
SectionCell editSectionCell = sectionCellService.getSectionCellById(sectionCellId);
|
||||
if (editSectionCell == null) {
|
||||
System.err.println("Trying to edit unknown section cell");
|
||||
public void editSectionCell(Long sectionCellId, String content, String mail) {
|
||||
if (sectionCellId == null) {
|
||||
logger.warn("Trying to edit unknown section cell");
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.NOT_FOUND, "Cette cellule de section n'existe pas");
|
||||
}
|
||||
SectionCell sectionCell = sectionCellService.getSectionCellById(sectionCellId);
|
||||
if (!utilsService.isAllowedToCheckProject(
|
||||
mail, this.sectionCellService.getProjectId(sectionCellId))) {
|
||||
logger.warn(
|
||||
@ -55,27 +76,45 @@ public class EntrepreneurApiService {
|
||||
mail,
|
||||
sectionCellId,
|
||||
this.sectionCellService.getProjectId(sectionCellId));
|
||||
sectionCellService.updateSectionCell(
|
||||
sectionCellId,
|
||||
sectionCell.getSectionId(),
|
||||
sectionCell.getContentSectionCell(),
|
||||
sectionCell.getModificationDate());
|
||||
SectionCell newSectionCell =
|
||||
new SectionCell(
|
||||
null,
|
||||
sectionCell.getSectionId(),
|
||||
content,
|
||||
LocalDateTime.now(),
|
||||
sectionCell.getProjectSectionCell());
|
||||
newSectionCell.setIdReference(sectionCell.getIdReference());
|
||||
this.addSectionCell(newSectionCell, mail);
|
||||
sectionCell
|
||||
.getAppointmentSectionCell()
|
||||
.forEach(
|
||||
appointment -> {
|
||||
this.appointmentService.updateAppointmentListSectionCell(
|
||||
appointment.getIdAppointment(), newSectionCell);
|
||||
});
|
||||
sectionCell
|
||||
.getListAnnotation()
|
||||
.forEach(
|
||||
annotation -> {
|
||||
this.annotationService.updateAnnotationSectionCell(
|
||||
annotation.getIdAnnotation(), newSectionCell);
|
||||
});
|
||||
}
|
||||
|
||||
public void removeSectionCell(Long sectionCellId, String mail) {
|
||||
SectionCell editSectionCell = sectionCellService.getSectionCellById(sectionCellId);
|
||||
if (editSectionCell == null) {
|
||||
System.err.println("Trying to remove unknown section cell");
|
||||
if (sectionCellId == null) {
|
||||
logger.warn("Trying to remove unknown section cell");
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.NOT_FOUND, "Cette cellule de section n'existe pas");
|
||||
}
|
||||
SectionCell editSectionCell = sectionCellService.getSectionCellById(sectionCellId);
|
||||
if (!utilsService.isAllowedToCheckProject(
|
||||
mail, this.sectionCellService.getProjectId(sectionCellId))) {
|
||||
logger.warn(
|
||||
"User {} tried to remove section cells {} of the project {} but is not allowed to.",
|
||||
mail,
|
||||
sectionCellId,
|
||||
this.sectionCellService.getSectionCellById(sectionCellId));
|
||||
this.sectionCellService.getProjectId(sectionCellId));
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.UNAUTHORIZED, "You're not allowed to check this project");
|
||||
}
|
||||
@ -84,52 +123,162 @@ public class EntrepreneurApiService {
|
||||
mail,
|
||||
sectionCellId,
|
||||
this.sectionCellService.getProjectId(sectionCellId));
|
||||
sectionCellService.removeSectionCellById(sectionCellId);
|
||||
SectionCell removedSectionCell =
|
||||
new SectionCell(
|
||||
null,
|
||||
-1L,
|
||||
"",
|
||||
LocalDateTime.now(),
|
||||
this.projectService.getProjectById(
|
||||
editSectionCell.getProjectSectionCell().getIdProject()));
|
||||
sectionCellService.addNewSectionCell(removedSectionCell);
|
||||
this.sectionCellService.updateSectionCellReferenceId(
|
||||
removedSectionCell.getIdSectionCell(), editSectionCell.getIdReference());
|
||||
projectService.updateProjectListSectionCell(
|
||||
sectionCellService.getProjectId(sectionCellId), removedSectionCell);
|
||||
// sectionCellService.removeSectionCellById(sectionCellId);
|
||||
}
|
||||
|
||||
public void addSectionCell(SectionCell sectionCell, String mail) {
|
||||
if (sectionCell == null) {
|
||||
System.err.println("Trying to create an empty section cell");
|
||||
logger.warn("Trying to create an empty section cell");
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.BAD_REQUEST, "La cellule de section fournie est vide");
|
||||
}
|
||||
if (sectionCell.getSectionId() == -1) {
|
||||
logger.warn("Trying to create an illegal section cell");
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.BAD_REQUEST, "La cellule de section fournie n'est pas valide");
|
||||
}
|
||||
if (!utilsService.isAllowedToCheckProject(
|
||||
mail, this.sectionCellService.getProjectId(sectionCell.getIdSectionCell()))) {
|
||||
mail, sectionCell.getProjectSectionCell().getIdProject())) {
|
||||
logger.warn(
|
||||
"User {} tried to add a section cell to the project {} but is not allowed to.",
|
||||
mail,
|
||||
this.sectionCellService.getProjectId(sectionCell.getIdSectionCell()));
|
||||
sectionCell.getProjectSectionCell().getIdProject());
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.UNAUTHORIZED, "You're not allowed to check this project");
|
||||
}
|
||||
logger.info(
|
||||
"User {} added a new section cell {} to the project with id {}",
|
||||
"User {} added a new section cell {} to the project {}",
|
||||
mail,
|
||||
sectionCell.getIdSectionCell(),
|
||||
this.sectionCellService.getProjectId(sectionCell.getIdSectionCell()));
|
||||
SectionCell newSectionCell = sectionCellService.addNewSectionCell(sectionCell);
|
||||
sectionCell.getProjectSectionCell().getIdProject());
|
||||
SectionCell newSectionCell =
|
||||
sectionCellService.addNewSectionCell(
|
||||
sectionCell); // if here, logger fails cause id is null (not added yet)
|
||||
newSectionCell.getProjectSectionCell().updateListSectionCell(newSectionCell);
|
||||
newSectionCell
|
||||
.getAppointmentSectionCell()
|
||||
.forEach(
|
||||
appointment -> {
|
||||
appointment.updateListSectionCell(newSectionCell);
|
||||
this.appointmentService.updateAppointmentListSectionCell(
|
||||
appointment.getIdAppointment(), newSectionCell);
|
||||
});
|
||||
newSectionCell
|
||||
.getListAnnotation()
|
||||
.forEach(
|
||||
annotation -> {
|
||||
annotation.setSectionCellAnnotation(newSectionCell);
|
||||
this.annotationService.updateAnnotationSectionCell(
|
||||
annotation.getIdAnnotation(), newSectionCell);
|
||||
});
|
||||
}
|
||||
|
||||
public void requestNewProject(Project project, String mail) {
|
||||
if (project == null) {
|
||||
logger.error("Trying to request the creation of a null project");
|
||||
logger.warn("Trying to request the creation of a null project");
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Le projet fourni est vide");
|
||||
}
|
||||
logger.info("User {} created a new project with id {}", mail, project.getIdProject());
|
||||
project.setProjectStatus(PENDING);
|
||||
logger.info("User {} created a new project named {}", mail, project.getProjectName());
|
||||
project.setEntrepreneurProposed((Entrepreneur) this.userService.getUserByEmail(mail));
|
||||
projectService.addNewProject(project);
|
||||
this.projectService.updateProjectStatus(project.getIdProject(), PENDING);
|
||||
if (project.getProjectAdministrator() != null) {
|
||||
this.administratorService.updateAdministratorListProject(
|
||||
project.getProjectAdministrator().getIdUser(), project);
|
||||
}
|
||||
this.entrepreneurService.updateEntrepreneurProjectProposed(
|
||||
this.userService.getUserByEmail(mail).getIdUser(), project);
|
||||
this.entrepreneurService.updateEntrepreneurProjectParticipation(
|
||||
this.userService.getUserByEmail(mail).getIdUser(), project);
|
||||
project.getListEntrepreneurParticipation()
|
||||
.forEach(
|
||||
entrepreneur ->
|
||||
this.entrepreneurService.updateEntrepreneurProjectParticipation(
|
||||
entrepreneur.getIdUser(), project));
|
||||
project.getListSectionCell()
|
||||
.forEach(
|
||||
sectionCell ->
|
||||
this.sectionCellService.updateSectionCellProject(
|
||||
sectionCell.getIdSectionCell(), project));
|
||||
}
|
||||
|
||||
public void createAccount(Entrepreneur e) {
|
||||
try {
|
||||
userService.getUserByEmail(e.getPrimaryMail());
|
||||
logger.error("The user {} already exists in the system", e.getPrimaryMail());
|
||||
} catch (ResponseStatusException err) {
|
||||
this.entrepreneurService.addEntrepreneur(e);
|
||||
return;
|
||||
}
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "User already exists in the system");
|
||||
}
|
||||
|
||||
public Iterable<Project> getProjectIdViaClaim(String email) {
|
||||
Long UserId = this.userService.getUserByEmail(email).getIdUser();
|
||||
Entrepreneur entrepreneur = this.entrepreneurService.getEntrepreneurById(UserId);
|
||||
List<Project> Project_List = new ArrayList<>();
|
||||
|
||||
Project_List.add(entrepreneur.getProjectParticipation());
|
||||
return Project_List;
|
||||
}
|
||||
|
||||
public Iterable<Entrepreneur> getAllEntrepreneurs() {
|
||||
return entrepreneurService.getAllEntrepreneurs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an entrepreneur with the given email has a project that is ACTIVE.
|
||||
*
|
||||
* @param email The email of the entrepreneur.
|
||||
* @return true if the entrepreneur has an active project, false otherwise.
|
||||
*/
|
||||
public Boolean checkIfEntrepreneurProjectActive(String email) {
|
||||
User user = this.userService.getUserByEmail(email);
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
Long userId = user.getIdUser();
|
||||
|
||||
Entrepreneur entrepreneur = this.entrepreneurService.getEntrepreneurById(userId);
|
||||
if (entrepreneur == null) {
|
||||
return false;
|
||||
}
|
||||
Project proposedProject = entrepreneur.getProjectProposed();
|
||||
return proposedProject != null && proposedProject.getProjectStatus() == ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an entrepreneur with the given email has proposed a project.
|
||||
*
|
||||
* @param email The email of the entrepreneur.
|
||||
* @return true if the entrepreneur has a proposed project, false otherwise.
|
||||
*/
|
||||
public Boolean entrepreneurHasPendingRequestedProject(String email) {
|
||||
User user = this.userService.getUserByEmail(email);
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
Long userId = user.getIdUser();
|
||||
|
||||
Entrepreneur entrepreneur = this.entrepreneurService.getEntrepreneurById(userId);
|
||||
if (entrepreneur == null) {
|
||||
return false;
|
||||
}
|
||||
Project proposedProject = entrepreneur.getProjectProposed();
|
||||
if (entrepreneur.getProjectProposed() == null) {
|
||||
return false;
|
||||
}
|
||||
return proposedProject.getProjectStatus() == PENDING;
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,17 @@ import enseirb.myinpulse.exception.UserNotFoundException;
|
||||
import enseirb.myinpulse.model.RoleRepresentation;
|
||||
import enseirb.myinpulse.model.UserRepresentation;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.management.relation.RoleNotFoundException;
|
||||
|
||||
public class KeycloakApi {
|
||||
|
||||
protected static final Logger logger = LogManager.getLogger();
|
||||
static final String keycloakUrl;
|
||||
static final String realmName;
|
||||
|
||||
@ -29,44 +34,48 @@ public class KeycloakApi {
|
||||
realmName = System.getenv("VITE_KEYCLOAK_REALM");
|
||||
}
|
||||
|
||||
static String toBearer(String b) {
|
||||
return "Bearer " + b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses Keycloak API to retrieve a role representation of a role by its name
|
||||
*
|
||||
* @param roleName name of the role
|
||||
* @param bearer authorization header used by the client to authenticate to keycloak
|
||||
* @param token authorization header used by the client to authenticate to keycloak
|
||||
*/
|
||||
public static RoleRepresentation getRoleRepresentationByName(String roleName, String bearer)
|
||||
public static RoleRepresentation getRoleRepresentationByName(String roleName, String token)
|
||||
throws RoleNotFoundException {
|
||||
RoleRepresentation[] response =
|
||||
RoleRepresentation response =
|
||||
RestClient.builder()
|
||||
.baseUrl(keycloakUrl)
|
||||
.defaultHeader("Authorization", bearer)
|
||||
.defaultHeader("Authorization", toBearer(token))
|
||||
.build()
|
||||
.get()
|
||||
.uri("/admin/realms/{realmName}/roles/{roleName}", realmName, roleName)
|
||||
.retrieve()
|
||||
.body(RoleRepresentation[].class);
|
||||
|
||||
if (response == null || response.length == 0) {
|
||||
throw new RoleNotFoundException("Role not found");
|
||||
}
|
||||
return response[0];
|
||||
.body(RoleRepresentation.class);
|
||||
/*
|
||||
{"id":"7a845f2e-c832-4465-8cd8-894d72bc13f1","name":"MyINPulse-entrepreneur","description":"Role for entrepreneur","composite":false,"clientRole":false,"containerId":"0d6f691b-e328-471a-b89e-c30bd7e5b6b0","attributes":{}}
|
||||
*/
|
||||
// TODO: check what happens when role does not exist
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use keycloak API to to retreive a userID via his name or email.
|
||||
*
|
||||
* @param username username or mail of the user
|
||||
* @param bearer bearer of the user, allowing access to database
|
||||
* @param token bearer of the user, allowing access to database
|
||||
* @return the userid, as a String
|
||||
* @throws UserNotFoundException
|
||||
*/
|
||||
public static String getUserIdByName(String username, String bearer)
|
||||
public static String getUserIdByName(String username, String token)
|
||||
throws UserNotFoundException {
|
||||
UserRepresentation[] response =
|
||||
RestClient.builder()
|
||||
.baseUrl(keycloakUrl)
|
||||
.defaultHeader("Authorization", bearer)
|
||||
.defaultHeader("Authorization", toBearer(token))
|
||||
.build()
|
||||
.get()
|
||||
.uri(
|
||||
@ -91,27 +100,26 @@ public class KeycloakApi {
|
||||
*
|
||||
* @param username
|
||||
* @param roleName
|
||||
* @param bearer
|
||||
* @param token
|
||||
* @throws RoleNotFoundException
|
||||
* @throws UserNotFoundException
|
||||
*/
|
||||
public static void setRoleToUser(String username, String roleName, String bearer)
|
||||
public static void setRoleToUser(String username, String roleName, String token)
|
||||
throws RoleNotFoundException, UserNotFoundException {
|
||||
RoleRepresentation roleRepresentation = getRoleRepresentationByName(roleName, bearer);
|
||||
String userId = getUserIdByName(username, bearer);
|
||||
|
||||
RoleRepresentation roleRepresentation = getRoleRepresentationByName(roleName, token);
|
||||
String userId = getUserIdByName(username, token);
|
||||
List<RoleRepresentation> rolesToAdd = List.of(roleRepresentation);
|
||||
logger.debug("Adding role {} to user {}", roleRepresentation.id, userId);
|
||||
RestClient.builder()
|
||||
.baseUrl(keycloakUrl)
|
||||
.defaultHeader("Authorization", bearer)
|
||||
.defaultHeader("Authorization", toBearer(token))
|
||||
.build()
|
||||
.post()
|
||||
.uri(
|
||||
"/admin/realms/${realmName}/users/${userId}/role-mappings/realm",
|
||||
realmName,
|
||||
userId)
|
||||
.body(roleRepresentation)
|
||||
.uri("/admin/realms/" + realmName + "/users/" + userId + "/role-mappings/realm")
|
||||
.body(rolesToAdd)
|
||||
.contentType(APPLICATION_JSON)
|
||||
.retrieve();
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,8 @@ package enseirb.myinpulse.service;
|
||||
|
||||
import com.itextpdf.text.*;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
|
||||
import enseirb.myinpulse.controller.AdminApi;
|
||||
import enseirb.myinpulse.controller.EntrepreneurApi;
|
||||
import enseirb.myinpulse.model.*;
|
||||
import enseirb.myinpulse.service.database.*;
|
||||
|
||||
@ -24,11 +25,19 @@ import java.nio.file.StandardCopyOption;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Service
|
||||
public class SharedApiService {
|
||||
|
||||
private final AdminApi adminApi;
|
||||
|
||||
private final EntrepreneurApi entrepreneurApi;
|
||||
|
||||
protected static final Logger logger = LogManager.getLogger();
|
||||
|
||||
private final ProjectService projectService;
|
||||
@ -44,12 +53,16 @@ public class SharedApiService {
|
||||
EntrepreneurService entrepreneurService,
|
||||
SectionCellService sectionCellService,
|
||||
AppointmentService appointmentService,
|
||||
UtilsService utilsService) {
|
||||
UtilsService utilsService,
|
||||
EntrepreneurApi entrepreneurApi,
|
||||
AdminApi adminApi) {
|
||||
this.projectService = projectService;
|
||||
this.entrepreneurService = entrepreneurService;
|
||||
this.sectionCellService = sectionCellService;
|
||||
this.appointmentService = appointmentService;
|
||||
this.utilsService = utilsService;
|
||||
this.entrepreneurApi = entrepreneurApi;
|
||||
this.adminApi = adminApi;
|
||||
}
|
||||
|
||||
// TODO filter this with date
|
||||
@ -69,10 +82,54 @@ public class SharedApiService {
|
||||
LocalDateTime dateTime = LocalDateTime.parse(date, formatter);
|
||||
|
||||
Project project = this.projectService.getProjectById(projectId);
|
||||
return this.sectionCellService.getSectionCellsByProjectAndSectionIdBeforeDate(
|
||||
return this.sectionCellService.getLatestSectionCellsByIdReferenceBeforeDate(
|
||||
project, sectionId, dateTime);
|
||||
}
|
||||
|
||||
// Retrieve all up to date (for every sectionId) sectionCells of a project
|
||||
public Iterable<SectionCell> getAllSectionCells(long projectId, String mail) {
|
||||
if (!utilsService.isAllowedToCheckProject(mail, projectId)) {
|
||||
logger.warn(
|
||||
"User {} tried to check section cells of the project {} but is not allowed to.",
|
||||
mail,
|
||||
projectId);
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.UNAUTHORIZED, "You're not allowed to check this project");
|
||||
}
|
||||
|
||||
Project project = this.projectService.getProjectById(projectId);
|
||||
|
||||
Map<Long, SectionCell> latestSectionCellsMap =
|
||||
new HashMap<>(); // List for the intermediate result
|
||||
|
||||
// Iterate through all SectionCells associated with the project
|
||||
// This loop iterates over project.getListSectionCell() but does NOT modify it which causes
|
||||
// ConcurrentModificationException.
|
||||
// Modifications are done only on the latestSectionCellsMap (which is safe).
|
||||
project.getListSectionCell() // <-- Iterating over the original list (read-only)
|
||||
.forEach(
|
||||
projectCell -> {
|
||||
Long idReference = projectCell.getIdReference();
|
||||
// Check if we have already seen a SectionCell with this idReference in
|
||||
// our map
|
||||
if (latestSectionCellsMap.containsKey(idReference)) {
|
||||
SectionCell existingCell = latestSectionCellsMap.get(idReference);
|
||||
// Compare modification dates. If the current cell is newer, replace
|
||||
// the one in the map.
|
||||
if (projectCell
|
||||
.getModificationDate()
|
||||
.isAfter(existingCell.getModificationDate())) {
|
||||
latestSectionCellsMap.put(idReference, projectCell);
|
||||
}
|
||||
} else {
|
||||
// If this is the first time we encounter this idReference, add the
|
||||
// cell to the map.
|
||||
latestSectionCellsMap.put(idReference, projectCell);
|
||||
}
|
||||
});
|
||||
return new ArrayList<>(latestSectionCellsMap.values());
|
||||
}
|
||||
|
||||
// TODO: test
|
||||
public Iterable<Entrepreneur> getEntrepreneursByProjectId(long projectId, String mail) {
|
||||
if (!utilsService.isAllowedToCheckProject(mail, projectId)) {
|
||||
@ -114,18 +171,26 @@ public class SharedApiService {
|
||||
"User {} tried to check the appointments related to the project {}",
|
||||
mail,
|
||||
projectId);
|
||||
Iterable<SectionCell> sectionCells =
|
||||
this.sectionCellService.getSectionCellsByProject(
|
||||
projectService.getProjectById(projectId),
|
||||
2L); // sectionId useless in this function ?
|
||||
List<Appointment> appointments = new ArrayList<Appointment>();
|
||||
sectionCells.forEach(
|
||||
|
||||
Project project = projectService.getProjectById(projectId);
|
||||
|
||||
Iterable<SectionCell> sectionCellsIterable =
|
||||
this.sectionCellService.getSectionCellsByProject(project);
|
||||
|
||||
// Use a Set to collect unique appointments
|
||||
Set<Appointment> uniqueAppointments = new HashSet<>();
|
||||
|
||||
sectionCellsIterable.forEach(
|
||||
sectionCell -> {
|
||||
appointments.addAll(
|
||||
List<Appointment> sectionAppointments =
|
||||
this.sectionCellService.getAppointmentsBySectionCellId(
|
||||
sectionCell.getIdSectionCell()));
|
||||
sectionCell.getIdSectionCell());
|
||||
// Add all appointments from this section cell to the Set
|
||||
uniqueAppointments.addAll(sectionAppointments);
|
||||
});
|
||||
return appointments;
|
||||
|
||||
// Convert the Set back to a List for the return value
|
||||
return new ArrayList<>(uniqueAppointments);
|
||||
}
|
||||
|
||||
public void getPDFReport(long appointmentId, String mail)
|
||||
@ -247,6 +312,13 @@ public class SharedApiService {
|
||||
sectionCell -> {
|
||||
sectionCell.updateAppointmentSectionCell(newAppointment);
|
||||
});
|
||||
newAppointment.getAppointmentReport().setAppointmentReport(newAppointment);
|
||||
|
||||
/*
|
||||
* On initial insertion, the resport value is null unless that report does already exist in the db somewhere
|
||||
* If a non null value is passed and it does not exist in db it will throw an exception
|
||||
*/
|
||||
if (newAppointment.getAppointmentReport() != null) {
|
||||
newAppointment.getAppointmentReport().setAppointmentReport(newAppointment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class UtilsService {
|
||||
|
||||
@ -44,19 +46,36 @@ public class UtilsService {
|
||||
}
|
||||
User user = this.userService.getUserByEmail(mail);
|
||||
Entrepreneur entrepreneur = this.entrepreneurService.getEntrepreneurById(user.getIdUser());
|
||||
if (entrepreneur == null) {
|
||||
logger.debug("testing access with an unknown Entrepreneur");
|
||||
return false;
|
||||
}
|
||||
if (entrepreneur.getProjectParticipation() == null) {
|
||||
logger.debug("testing access with an user with no project participation");
|
||||
return false;
|
||||
}
|
||||
Project project = this.projectService.getProjectById(projectId);
|
||||
return entrepreneur.getProjectParticipation() == project;
|
||||
// We compare the ID instead of the project themselves
|
||||
return Objects.equals(
|
||||
entrepreneur.getProjectParticipation().getIdProject(), project.getIdProject());
|
||||
}
|
||||
|
||||
// TODO: test
|
||||
Boolean isAnAdmin(String mail) {
|
||||
public Boolean isAnAdmin(String mail) {
|
||||
try {
|
||||
long userId = this.userService.getUserByEmail(mail).getIdUser();
|
||||
Administrator a = this.administratorService.getAdministratorById(userId);
|
||||
return true;
|
||||
} catch (ResponseStatusException e) {
|
||||
logger.info(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean checkEntrepreneurNotPending(String email) {
|
||||
// Throws 404 if user not found
|
||||
User user = userService.getUserByEmail(email);
|
||||
return !user.isPending();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package enseirb.myinpulse.service.database;
|
||||
|
||||
import enseirb.myinpulse.model.Administrator;
|
||||
import enseirb.myinpulse.model.Annotation;
|
||||
import enseirb.myinpulse.model.MakeAppointment;
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.repository.AdministratorRepository;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -52,6 +55,49 @@ public class AdministratorService {
|
||||
return this.administratorRepository.save(administrator);
|
||||
}
|
||||
|
||||
public void updateAdministratorListProject(long idAdministrator, Project project) {
|
||||
Administrator administrator = getAdministratorById(idAdministrator);
|
||||
administrator.updateListProject(project);
|
||||
this.administratorRepository.save(administrator);
|
||||
}
|
||||
|
||||
public void updateAdministratorListAnnotation(long idAdministrator, Annotation annotation) {
|
||||
Administrator administrator = getAdministratorById(idAdministrator);
|
||||
administrator.updateListAnnotation(annotation);
|
||||
this.administratorRepository.save(administrator);
|
||||
}
|
||||
|
||||
public void updateAdministratorMakeAppointment(
|
||||
long idAdministrator, MakeAppointment makeAppointment) {
|
||||
Administrator administrator = getAdministratorById(idAdministrator);
|
||||
administrator.setMakeAppointment(makeAppointment);
|
||||
this.administratorRepository.save(administrator);
|
||||
}
|
||||
|
||||
public Administrator updateAdministrator(
|
||||
Long idAdministrator,
|
||||
Project project,
|
||||
Annotation annotation,
|
||||
MakeAppointment makeAppointment) {
|
||||
Optional<Administrator> administrator = administratorRepository.findById(idAdministrator);
|
||||
if (administrator.isEmpty()) {
|
||||
logger.error(
|
||||
"updateAdministrator : No administrator found with id {}", idAdministrator);
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.NOT_FOUND, "Cet administrateur n'existe pas");
|
||||
}
|
||||
if (project != null) {
|
||||
administrator.get().updateListProject(project);
|
||||
}
|
||||
if (annotation != null) {
|
||||
administrator.get().updateListAnnotation(annotation);
|
||||
}
|
||||
if (makeAppointment != null) {
|
||||
administrator.get().setMakeAppointment(makeAppointment);
|
||||
}
|
||||
return this.administratorRepository.save(administrator.get());
|
||||
}
|
||||
|
||||
/*
|
||||
public Administrator getAdministratorByProject(Project project) {
|
||||
r
|
||||
|
@ -1,6 +1,8 @@
|
||||
package enseirb.myinpulse.service.database;
|
||||
|
||||
import enseirb.myinpulse.model.Administrator;
|
||||
import enseirb.myinpulse.model.Annotation;
|
||||
import enseirb.myinpulse.model.SectionCell;
|
||||
import enseirb.myinpulse.repository.AnnotationRepository;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -46,6 +48,12 @@ public class AnnotationService {
|
||||
this.annotationRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public void updateAnnotationComment(long idAnnotation, String comment) {
|
||||
Annotation annotation = getAnnotationById(idAnnotation);
|
||||
annotation.setComment(comment);
|
||||
this.annotationRepository.save(annotation);
|
||||
}
|
||||
|
||||
public Annotation updateAnnotation(Long id, String comment) {
|
||||
Optional<Annotation> annotation = annotationRepository.findById(id);
|
||||
if (annotation.isEmpty()) {
|
||||
@ -58,4 +66,16 @@ public class AnnotationService {
|
||||
}
|
||||
return this.annotationRepository.save(annotation.get());
|
||||
}
|
||||
|
||||
public void updateAnnotationSectionCell(long idAnnotation, SectionCell sectionCell) {
|
||||
Annotation annotation = getAnnotationById(idAnnotation);
|
||||
annotation.setSectionCellAnnotation(sectionCell);
|
||||
this.annotationRepository.save(annotation);
|
||||
}
|
||||
|
||||
public void updateAnnotationAdministrator(long idAnnotation, Administrator administrator) {
|
||||
Annotation annotation = getAnnotationById(idAnnotation);
|
||||
annotation.setAdministratorAnnotation(administrator);
|
||||
this.annotationRepository.save(annotation);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package enseirb.myinpulse.service.database;
|
||||
|
||||
import enseirb.myinpulse.model.Appointment;
|
||||
import enseirb.myinpulse.model.SectionCell;
|
||||
import enseirb.myinpulse.repository.AppointmentRepository;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -47,13 +48,50 @@ public class AppointmentService {
|
||||
this.appointmentRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public void updateAppointmentDate(long idAppointment, LocalDate date) {
|
||||
Appointment appointment = getAppointmentById(idAppointment);
|
||||
appointment.setAppointmentDate(date);
|
||||
this.appointmentRepository.save(appointment);
|
||||
}
|
||||
|
||||
public void updateAppointmentTime(long idAppointment, LocalTime time) {
|
||||
Appointment appointment = getAppointmentById(idAppointment);
|
||||
appointment.setAppointmentTime(time);
|
||||
this.appointmentRepository.save(appointment);
|
||||
}
|
||||
|
||||
public void updateAppointmentDuration(long idAppointment, LocalTime duration) {
|
||||
Appointment appointment = getAppointmentById(idAppointment);
|
||||
appointment.setAppointmentDuration(duration);
|
||||
this.appointmentRepository.save(appointment);
|
||||
}
|
||||
|
||||
public void updateAppointmentPlace(long idAppointment, String place) {
|
||||
Appointment appointment = getAppointmentById(idAppointment);
|
||||
appointment.setAppointmentPlace(place);
|
||||
this.appointmentRepository.save(appointment);
|
||||
}
|
||||
|
||||
public void updateAppointmentSubject(long idAppointment, String subject) {
|
||||
Appointment appointment = getAppointmentById(idAppointment);
|
||||
appointment.setAppointmentSubject(subject);
|
||||
this.appointmentRepository.save(appointment);
|
||||
}
|
||||
|
||||
public void updateAppointmentListSectionCell(long idAppointment, SectionCell sectionCell) {
|
||||
Appointment appointment = getAppointmentById(idAppointment);
|
||||
appointment.updateListSectionCell(sectionCell);
|
||||
this.appointmentRepository.save(appointment);
|
||||
}
|
||||
|
||||
public Appointment updateAppointment(
|
||||
Long id,
|
||||
LocalDate appointmentDate,
|
||||
LocalTime appointmentTime,
|
||||
LocalTime appointmentDuration,
|
||||
String appointmentPlace,
|
||||
String appointmentSubject) {
|
||||
String appointmentSubject,
|
||||
SectionCell sectionCell) {
|
||||
Optional<Appointment> appointment = this.appointmentRepository.findById(id);
|
||||
if (appointment.isEmpty()) {
|
||||
logger.error("updateAppointment : No appointment found with id {}", id);
|
||||
@ -74,6 +112,9 @@ public class AppointmentService {
|
||||
if (appointmentSubject != null) {
|
||||
appointment.get().setAppointmentSubject(appointmentSubject);
|
||||
}
|
||||
if (sectionCell != null) {
|
||||
appointment.get().updateListSectionCell(sectionCell);
|
||||
}
|
||||
return this.appointmentRepository.save(appointment.get());
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package enseirb.myinpulse.service.database;
|
||||
|
||||
import enseirb.myinpulse.model.Entrepreneur;
|
||||
import enseirb.myinpulse.model.MakeAppointment;
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.repository.EntrepreneurRepository;
|
||||
|
||||
@ -41,8 +42,52 @@ public class EntrepreneurService {
|
||||
return this.entrepreneurRepository.save(entrepreneur);
|
||||
}
|
||||
|
||||
public void updateEntrepreneurSchool(long idEntrepreneur, String school) {
|
||||
Entrepreneur entrepreneur = getEntrepreneurById(idEntrepreneur);
|
||||
entrepreneur.setSchool(school);
|
||||
this.entrepreneurRepository.save(entrepreneur);
|
||||
}
|
||||
|
||||
public void updateEntrepreneurCourse(long idEntrepreneur, String course) {
|
||||
Entrepreneur entrepreneur = getEntrepreneurById(idEntrepreneur);
|
||||
entrepreneur.setCourse(course);
|
||||
this.entrepreneurRepository.save(entrepreneur);
|
||||
}
|
||||
|
||||
public void updateEntrepreneurSneeStatus(long idEntrepreneur, boolean status) {
|
||||
Entrepreneur entrepreneur = getEntrepreneurById(idEntrepreneur);
|
||||
entrepreneur.setSneeStatus(status);
|
||||
this.entrepreneurRepository.save(entrepreneur);
|
||||
}
|
||||
|
||||
public void updateEntrepreneurProjectParticipation(
|
||||
long idEntrepreneur, Project projectParticipation) {
|
||||
Entrepreneur entrepreneur = getEntrepreneurById(idEntrepreneur);
|
||||
entrepreneur.setProjectParticipation(projectParticipation);
|
||||
this.entrepreneurRepository.save(entrepreneur);
|
||||
}
|
||||
|
||||
public void updateEntrepreneurProjectProposed(long idEntrepreneur, Project projectProposed) {
|
||||
Entrepreneur entrepreneur = getEntrepreneurById(idEntrepreneur);
|
||||
entrepreneur.setProjectParticipation(projectProposed);
|
||||
this.entrepreneurRepository.save(entrepreneur);
|
||||
}
|
||||
|
||||
public void updateEntrepreneurMakeAppointment(
|
||||
long idEntrepreneur, MakeAppointment makeAppointment) {
|
||||
Entrepreneur entrepreneur = getEntrepreneurById(idEntrepreneur);
|
||||
entrepreneur.setMakeAppointment(makeAppointment);
|
||||
this.entrepreneurRepository.save(entrepreneur);
|
||||
}
|
||||
|
||||
public Entrepreneur updateEntrepreneur(
|
||||
Long id, String school, String course, Boolean sneeStatus) {
|
||||
Long id,
|
||||
String school,
|
||||
String course,
|
||||
Boolean sneeStatus,
|
||||
Project projectParticipation,
|
||||
Project projectProposed,
|
||||
MakeAppointment makeAppointment) {
|
||||
Optional<Entrepreneur> entrepreneur = entrepreneurRepository.findById(id);
|
||||
if (entrepreneur.isEmpty()) {
|
||||
logger.error("updateEntrepreneur : No entrepreneur found with id {}", id);
|
||||
@ -58,10 +103,33 @@ public class EntrepreneurService {
|
||||
if (sneeStatus != null) {
|
||||
entrepreneur.get().setSneeStatus(sneeStatus);
|
||||
}
|
||||
if (projectParticipation != null) {
|
||||
entrepreneur.get().setProjectParticipation(projectParticipation);
|
||||
}
|
||||
if (projectProposed != null) {
|
||||
entrepreneur.get().setProjectParticipation(projectProposed);
|
||||
}
|
||||
if (makeAppointment != null) {
|
||||
entrepreneur.get().setMakeAppointment(makeAppointment);
|
||||
}
|
||||
return this.entrepreneurRepository.save(entrepreneur.get());
|
||||
}
|
||||
|
||||
public Iterable<Entrepreneur> GetEntrepreneurByProject(Project project) {
|
||||
return this.entrepreneurRepository.getEntrepreneurByProjectParticipation(project);
|
||||
}
|
||||
|
||||
public void deleteEntrepreneur(Entrepreneur e) {
|
||||
this.entrepreneurRepository.delete(e);
|
||||
}
|
||||
|
||||
public void validateEntrepreneurById(Long id) {
|
||||
System.out.println("\nVALIDATING\n");
|
||||
Optional<Entrepreneur> e = this.entrepreneurRepository.findById(id);
|
||||
if (e.isEmpty()) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Entrepreneur n'existe pas");
|
||||
}
|
||||
e.get().setPending(false);
|
||||
this.entrepreneurRepository.save(e.get());
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,7 @@ package enseirb.myinpulse.service.database;
|
||||
|
||||
import static enseirb.myinpulse.model.ProjectDecisionValue.PENDING;
|
||||
|
||||
import enseirb.myinpulse.model.Administrator;
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.model.ProjectDecisionValue;
|
||||
import enseirb.myinpulse.model.*;
|
||||
import enseirb.myinpulse.repository.ProjectRepository;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -14,7 +12,6 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -52,12 +49,50 @@ public class ProjectService {
|
||||
return this.projectRepository.save(project);
|
||||
}
|
||||
|
||||
public void updateProjectName(long idProject, String name) {
|
||||
Project project = getProjectById(idProject);
|
||||
project.setProjectName(name);
|
||||
this.projectRepository.save(project);
|
||||
}
|
||||
|
||||
public void updateProjectLogo(long idProject, byte[] logo) {
|
||||
Project project = getProjectById(idProject);
|
||||
project.setLogo(logo);
|
||||
this.projectRepository.save(project);
|
||||
}
|
||||
|
||||
public void updateProjectStatus(long idProject, ProjectDecisionValue status) {
|
||||
Project project = getProjectById(idProject);
|
||||
project.setProjectStatus(status);
|
||||
this.projectRepository.save(project);
|
||||
}
|
||||
|
||||
public void updateProjectEntrepreneurParticipation(
|
||||
long idProject, Entrepreneur entrepreneurParticipation) {
|
||||
Project project = getProjectById(idProject);
|
||||
project.updateListEntrepreneurParticipation(entrepreneurParticipation);
|
||||
this.projectRepository.save(project);
|
||||
}
|
||||
|
||||
public void updateProjectListSectionCell(long idProject, SectionCell sectionCell) {
|
||||
Project project = getProjectById(idProject);
|
||||
project.updateListSectionCell(sectionCell);
|
||||
this.projectRepository.save(project);
|
||||
}
|
||||
|
||||
public void updateProjectAdministrator(long idProject, Administrator administrator) {
|
||||
Project project = getProjectById(idProject);
|
||||
project.setProjectAdministrator(administrator);
|
||||
this.projectRepository.save(project);
|
||||
}
|
||||
|
||||
public Project updateProject(
|
||||
Long id,
|
||||
String projectName,
|
||||
byte[] logo,
|
||||
LocalDate creationDate,
|
||||
ProjectDecisionValue projectStatus,
|
||||
Entrepreneur entrepreneurParticipation,
|
||||
SectionCell sectionCell,
|
||||
Administrator administrator) {
|
||||
Optional<Project> project = this.projectRepository.findById(id);
|
||||
|
||||
@ -73,11 +108,6 @@ public class ProjectService {
|
||||
if (logo != null) {
|
||||
project.get().setLogo(logo);
|
||||
}
|
||||
|
||||
if (creationDate != null) {
|
||||
project.get().setCreationDate(creationDate);
|
||||
}
|
||||
|
||||
if (projectStatus != null) {
|
||||
// TODO: check if this is really useful
|
||||
/*
|
||||
@ -89,7 +119,12 @@ public class ProjectService {
|
||||
*/
|
||||
project.get().setProjectStatus(projectStatus);
|
||||
}
|
||||
|
||||
if (entrepreneurParticipation != null) {
|
||||
project.get().updateListEntrepreneurParticipation(entrepreneurParticipation);
|
||||
}
|
||||
if (sectionCell != null) {
|
||||
project.get().updateListSectionCell(sectionCell);
|
||||
}
|
||||
if (administrator != null) {
|
||||
project.get().setProjectAdministrator(administrator);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package enseirb.myinpulse.service.database;
|
||||
|
||||
import enseirb.myinpulse.model.Appointment;
|
||||
import enseirb.myinpulse.model.Report;
|
||||
import enseirb.myinpulse.repository.ReportRepository;
|
||||
|
||||
@ -46,7 +47,19 @@ public class ReportService {
|
||||
this.reportRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public Report updateReport(Long id, String reportContent) {
|
||||
public void updateReportContent(long idReport, String content) {
|
||||
Report report = getReportById(idReport);
|
||||
report.setReportContent(content);
|
||||
this.reportRepository.save(report);
|
||||
}
|
||||
|
||||
public void updateReportAppointment(long idReport, Appointment appointment) {
|
||||
Report report = getReportById(idReport);
|
||||
report.setAppointmentReport(appointment);
|
||||
this.reportRepository.save(report);
|
||||
}
|
||||
|
||||
public Report updateReport(Long id, String reportContent, Appointment appointment) {
|
||||
Optional<Report> report = this.reportRepository.findById(id);
|
||||
if (report.isEmpty()) {
|
||||
logger.error("updateReport : No report found with id {}", id);
|
||||
@ -55,6 +68,9 @@ public class ReportService {
|
||||
if (reportContent != null) {
|
||||
report.get().setReportContent(reportContent);
|
||||
}
|
||||
if (appointment != null) {
|
||||
report.get().setAppointmentReport(appointment);
|
||||
}
|
||||
return this.reportRepository.save(report.get());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package enseirb.myinpulse.service.database;
|
||||
|
||||
import enseirb.myinpulse.model.Annotation;
|
||||
import enseirb.myinpulse.model.Appointment;
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.model.SectionCell;
|
||||
@ -13,7 +14,10 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
@ -50,22 +54,63 @@ public class SectionCellService {
|
||||
this.sectionCellRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public void updateSectionCellReferenceId(Long idSectionCell, Long referenceId) {
|
||||
SectionCell sectionCell = this.getSectionCellById(idSectionCell);
|
||||
sectionCell.setIdReference(referenceId);
|
||||
this.sectionCellRepository.save(sectionCell);
|
||||
}
|
||||
|
||||
public void updateSectionCellContent(long idSectionCell, String content) {
|
||||
SectionCell sectionCell = getSectionCellById(idSectionCell);
|
||||
sectionCell.setContentSectionCell(content);
|
||||
this.sectionCellRepository.save(sectionCell);
|
||||
}
|
||||
|
||||
public void updateSectionCellListAppointment(long idSectionCell, Appointment appointment) {
|
||||
SectionCell sectionCell = getSectionCellById(idSectionCell);
|
||||
sectionCell.updateAppointmentSectionCell(appointment);
|
||||
this.sectionCellRepository.save(sectionCell);
|
||||
}
|
||||
|
||||
public void updateSectionCellListAnnotation(long idSectionCell, Annotation annotation) {
|
||||
SectionCell sectionCell = getSectionCellById(idSectionCell);
|
||||
sectionCell.updateListAnnotation(annotation);
|
||||
this.sectionCellRepository.save(sectionCell);
|
||||
}
|
||||
|
||||
public void updateSectionCellProject(long idSectionCell, Project project) {
|
||||
SectionCell sectionCell = getSectionCellById(idSectionCell);
|
||||
sectionCell.setProjectSectionCell(project);
|
||||
this.sectionCellRepository.save(sectionCell);
|
||||
}
|
||||
|
||||
public SectionCell updateSectionCell(
|
||||
Long id, Long sectionId, String contentSectionCell, LocalDateTime modificationDate) {
|
||||
Long id,
|
||||
String contentSectionCell,
|
||||
Appointment appointment,
|
||||
Annotation annotation,
|
||||
Project project) {
|
||||
Optional<SectionCell> sectionCell = this.sectionCellRepository.findById(id);
|
||||
if (sectionCell.isEmpty()) {
|
||||
logger.error("updateSectionCell : No sectionCell found with id {}", id);
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.NOT_FOUND, "Cette cellule de section n'existe pas");
|
||||
}
|
||||
if (sectionId != null) {
|
||||
sectionCell.get().setSectionId(sectionId);
|
||||
}
|
||||
if (contentSectionCell != null) {
|
||||
sectionCell.get().setContentSectionCell(contentSectionCell);
|
||||
sectionCell.get().setModificationDate(LocalDateTime.now());
|
||||
}
|
||||
if (modificationDate != null) {
|
||||
sectionCell.get().setModificationDate(modificationDate);
|
||||
if (appointment != null) {
|
||||
sectionCell.get().updateAppointmentSectionCell(appointment);
|
||||
sectionCell.get().setModificationDate(LocalDateTime.now());
|
||||
}
|
||||
if (annotation != null) {
|
||||
sectionCell.get().updateListAnnotation(annotation);
|
||||
sectionCell.get().setModificationDate(LocalDateTime.now());
|
||||
}
|
||||
if (project != null) {
|
||||
sectionCell.get().setProjectSectionCell(project);
|
||||
sectionCell.get().setModificationDate(LocalDateTime.now());
|
||||
}
|
||||
return this.sectionCellRepository.save(sectionCell.get());
|
||||
}
|
||||
@ -74,6 +119,18 @@ public class SectionCellService {
|
||||
return this.sectionCellRepository.findByProjectSectionCellAndSectionId(project, sectionId);
|
||||
}
|
||||
|
||||
public Iterable<SectionCell> getSectionCellsByProject(Project project) {
|
||||
logger.info("Fetching SectionCells for Project ID: {}", project.getIdProject());
|
||||
Iterable<SectionCell> sectionCells =
|
||||
this.sectionCellRepository.findByProjectSectionCell(project);
|
||||
List<SectionCell> sectionCellList = new ArrayList<>();
|
||||
sectionCells.forEach(
|
||||
cell -> {
|
||||
sectionCellList.add(cell);
|
||||
});
|
||||
return sectionCellList;
|
||||
}
|
||||
|
||||
public Long getProjectId(Long sectionCellId) {
|
||||
SectionCell sectionCell = getSectionCellById(sectionCellId);
|
||||
Project sectionProject = sectionCell.getProjectSectionCell();
|
||||
@ -90,4 +147,37 @@ public class SectionCellService {
|
||||
return sectionCellRepository.findByProjectSectionCellAndSectionIdAndModificationDateBefore(
|
||||
project, sectionId, date);
|
||||
}
|
||||
|
||||
public Iterable<SectionCell> getLatestSectionCellsByIdReferenceBeforeDate(
|
||||
Project project, long sectionId, LocalDateTime date) {
|
||||
|
||||
// 1. Fetch ALL relevant SectionCells modified before the date
|
||||
Iterable<SectionCell> allMatchingCells =
|
||||
sectionCellRepository.findByProjectSectionCellAndSectionIdAndModificationDateBefore(
|
||||
project, sectionId, date);
|
||||
|
||||
// 2. Find the latest for each idReference
|
||||
Map<Long, SectionCell> latestCellsByIdReference = new HashMap<>();
|
||||
|
||||
for (SectionCell cell : allMatchingCells) {
|
||||
Long idReference = cell.getIdReference();
|
||||
|
||||
// Check if we've seen this idReference before
|
||||
if (latestCellsByIdReference.containsKey(idReference)) {
|
||||
// If yes, compare modification dates
|
||||
SectionCell existingLatest = latestCellsByIdReference.get(idReference);
|
||||
|
||||
// If the current cell is more recent, update the map
|
||||
if (cell.getModificationDate().isAfter(existingLatest.getModificationDate())) {
|
||||
latestCellsByIdReference.put(idReference, cell);
|
||||
}
|
||||
} else {
|
||||
// If this is the first time we see this idReference, add it to the map
|
||||
latestCellsByIdReference.put(idReference, cell);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Return the collection of the latest cells (the values from the map)
|
||||
return latestCellsByIdReference.values();
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,15 @@ public class UserService {
|
||||
return this.userRepository.findAll();
|
||||
}
|
||||
|
||||
public User getUserById(long id) {
|
||||
Optional<User> user = this.userRepository.findById(id);
|
||||
if (user.isEmpty()) {
|
||||
logger.error("getUserById : No user found with id {}", id);
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Cet utilisateur n'existe pas");
|
||||
}
|
||||
return user.get();
|
||||
}
|
||||
|
||||
// TODO
|
||||
public User getUserByEmail(String email) {
|
||||
Optional<User> opt_user = this.userRepository.findByPrimaryMail(email);
|
||||
@ -49,6 +58,36 @@ public class UserService {
|
||||
return this.userRepository.save(user);
|
||||
}
|
||||
|
||||
public void updateUserSurname(long idUser, String surname) {
|
||||
User user = getUserById(idUser);
|
||||
user.setUserSurname(surname);
|
||||
this.userRepository.save(user);
|
||||
}
|
||||
|
||||
public void updateUserName(long idUser, String name) {
|
||||
User user = getUserById(idUser);
|
||||
user.setUserName(name);
|
||||
this.userRepository.save(user);
|
||||
}
|
||||
|
||||
public void updateUserPrimaryMail(long idUser, String primaryMail) {
|
||||
User user = getUserById(idUser);
|
||||
user.setPrimaryMail(primaryMail);
|
||||
this.userRepository.save(user);
|
||||
}
|
||||
|
||||
public void updateUserSecondaryMail(long idUser, String secondaryMail) {
|
||||
User user = getUserById(idUser);
|
||||
user.setSecondaryMail(secondaryMail);
|
||||
this.userRepository.save(user);
|
||||
}
|
||||
|
||||
public void updateUserPhoneNumber(long idUser, String phoneNumber) {
|
||||
User user = getUserById(idUser);
|
||||
user.setPhoneNumber(phoneNumber);
|
||||
this.userRepository.save(user);
|
||||
}
|
||||
|
||||
public User updateUser(
|
||||
@PathVariable Long id,
|
||||
String userSurname,
|
||||
@ -78,4 +117,8 @@ public class UserService {
|
||||
}
|
||||
return this.userRepository.save(user.get());
|
||||
}
|
||||
|
||||
public Iterable<User> getPendingAccounts() {
|
||||
return this.userRepository.findAllByPendingEquals(true);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
spring.application.name=myinpulse
|
||||
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:7080/realms/test/protocol/openid-connect/certs
|
||||
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:7080/realms/test
|
||||
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:7080/realms/${VITE_KEYCLOAK_REALM}/protocol/openid-connect/certs
|
||||
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:7080/realms/${VITE_KEYCLOAK_REALM}
|
||||
spring.datasource.url=jdbc:postgresql://${DATABASE_URL}/${BACKEND_DB}
|
||||
spring.datasource.username=${BACKEND_USER}
|
||||
spring.datasource.password=${BACKEND_PASSWORD}
|
||||
|
@ -4,14 +4,10 @@ import static enseirb.myinpulse.model.ProjectDecisionValue.*;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import enseirb.myinpulse.model.Administrator;
|
||||
import enseirb.myinpulse.model.Entrepreneur;
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.model.ProjectDecision;
|
||||
import enseirb.myinpulse.model.*;
|
||||
import enseirb.myinpulse.service.AdminApiService;
|
||||
import enseirb.myinpulse.service.database.AdministratorService;
|
||||
import enseirb.myinpulse.service.database.EntrepreneurService;
|
||||
import enseirb.myinpulse.service.database.ProjectService;
|
||||
import enseirb.myinpulse.service.UtilsService;
|
||||
import enseirb.myinpulse.service.database.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -21,6 +17,8 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -30,14 +28,22 @@ public class AdminApiServiceTest {
|
||||
private static long administratorid;
|
||||
private static Administrator administrator;
|
||||
private static Entrepreneur entrepreneur;
|
||||
private static Appointment appt;
|
||||
private static Project p;
|
||||
@Autowired private AdminApiService adminApiService;
|
||||
@Autowired private ProjectService projectService;
|
||||
@Autowired private EntrepreneurService entrepreneurService;
|
||||
@Autowired private SectionCellService sectionCellService;
|
||||
@Autowired private AppointmentService appointmentService;
|
||||
@Autowired private UtilsService utilsService;
|
||||
|
||||
@BeforeAll
|
||||
static void setup(
|
||||
@Autowired AdministratorService administratorService,
|
||||
@Autowired ProjectService projectService,
|
||||
@Autowired EntrepreneurService entrepreneurService) {
|
||||
@Autowired EntrepreneurService entrepreneurService,
|
||||
@Autowired AppointmentService appoitmentService,
|
||||
@Autowired SectionCellService sectionCellService) {
|
||||
administratorService.addAdministrator(
|
||||
new Administrator(
|
||||
"admin",
|
||||
@ -54,6 +60,7 @@ public class AdminApiServiceTest {
|
||||
"testAdmin@example.com",
|
||||
""));
|
||||
administratorid = administrator.getIdUser();
|
||||
|
||||
entrepreneur =
|
||||
new Entrepreneur(
|
||||
"JeSuisUnEntrepreneurDeCompet",
|
||||
@ -65,14 +72,32 @@ public class AdminApiServiceTest {
|
||||
"info ofc",
|
||||
false);
|
||||
entrepreneurService.addEntrepreneur(entrepreneur);
|
||||
projectService.addNewProject(
|
||||
new Project(
|
||||
"sampleProjectAdminApiService",
|
||||
|
||||
Entrepreneur entrepreneur2 =
|
||||
new Entrepreneur(
|
||||
"GDProjets", "", "Entrepreneur2@inpulse.com", "", "", "", "info ofc", true);
|
||||
entrepreneurService.addEntrepreneur(entrepreneur2);
|
||||
|
||||
p =
|
||||
projectService.addNewProject(
|
||||
new Project(
|
||||
"sampleProjectAdminApiService",
|
||||
null,
|
||||
LocalDate.now(),
|
||||
ACTIVE,
|
||||
administratorService.getAdministratorByPrimaryMain(
|
||||
"testAdminFull@example.com")));
|
||||
|
||||
entrepreneurService.updateEntrepreneurProjectParticipation(entrepreneur2.getIdUser(), p);
|
||||
|
||||
appt =
|
||||
new Appointment(
|
||||
null,
|
||||
LocalDate.now(),
|
||||
ACTIVE,
|
||||
administratorService.getAdministratorByPrimaryMain(
|
||||
"testAdminFull@example.com")));
|
||||
LocalTime.now(),
|
||||
LocalTime.now(),
|
||||
"Salle TD 03",
|
||||
"Discussion importante");
|
||||
}
|
||||
|
||||
private <T> List<T> IterableToList(Iterable<T> iterable) {
|
||||
@ -106,7 +131,7 @@ public class AdminApiServiceTest {
|
||||
List<Project> l = IterableToList(projects);
|
||||
assertEquals(1, l.size());
|
||||
Project p = l.getFirst();
|
||||
assertEquals(p.getProjectName(), "sampleProjectAdminApiService");
|
||||
assertEquals("sampleProjectAdminApiService", p.getProjectName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -180,7 +205,7 @@ public class AdminApiServiceTest {
|
||||
@Test
|
||||
void addProjectToAdmin() {
|
||||
assertEquals(0, administrator.getListProject().size());
|
||||
Project p1 = new Project("assProjectToAdmin", null, LocalDate.now(), ACTIVE, administrator);
|
||||
Project p1 = new Project("addProjectToAdmin", null, LocalDate.now(), ACTIVE, administrator);
|
||||
this.adminApiService.addNewProject(p1);
|
||||
assertEquals(1, administrator.getListProject().size());
|
||||
}
|
||||
@ -189,7 +214,7 @@ public class AdminApiServiceTest {
|
||||
void addProjectToUser() {
|
||||
assertNull(entrepreneur.getProjectParticipation());
|
||||
Project p1 =
|
||||
new Project("assProjectToAdmin", null, LocalDate.now(), ACTIVE, null, entrepreneur);
|
||||
new Project("addProjectToAdmin", null, LocalDate.now(), ACTIVE, null, entrepreneur);
|
||||
this.adminApiService.addNewProject(p1);
|
||||
assertEquals(p1, entrepreneur.getProjectParticipation());
|
||||
}
|
||||
@ -202,7 +227,7 @@ public class AdminApiServiceTest {
|
||||
assertNull(e1.getProjectParticipation());
|
||||
assertNull(e2.getProjectParticipation());
|
||||
assertNull(e3.getProjectParticipation());
|
||||
Project p1 = new Project("assProjectToAdmin", null, LocalDate.now(), ACTIVE, null, null);
|
||||
Project p1 = new Project("addProjectToAdmin", null, LocalDate.now(), ACTIVE, null, null);
|
||||
p1.updateListEntrepreneurParticipation(e1);
|
||||
p1.updateListEntrepreneurParticipation(e2);
|
||||
p1.updateListEntrepreneurParticipation(e3);
|
||||
@ -221,4 +246,86 @@ public class AdminApiServiceTest {
|
||||
this.adminApiService.addNewProject(p1);
|
||||
assertThrows(ResponseStatusException.class, () -> this.adminApiService.addNewProject(p2));
|
||||
}
|
||||
|
||||
// We could do a delete active project, but it's not really useful.
|
||||
@Test
|
||||
void deletePendingProject() {
|
||||
int oldsize = IterableToList(this.adminApiService.getPendingProjects()).size();
|
||||
Project p1 =
|
||||
new Project("PendingProjectAdminApiService2", null, LocalDate.now(), PENDING, null);
|
||||
Project p2 = this.adminApiService.addNewProject(p1);
|
||||
|
||||
assertEquals(oldsize + 1, IterableToList(this.adminApiService.getPendingProjects()).size());
|
||||
this.adminApiService.deleteProject(p2.getIdProject());
|
||||
|
||||
assertEquals(oldsize, IterableToList(this.adminApiService.getPendingProjects()).size());
|
||||
for (int i = 0; i < oldsize; i++) {
|
||||
assertNotEquals(
|
||||
p1.getIdProject(),
|
||||
IterableToList(this.adminApiService.getPendingProjects())
|
||||
.get(i)
|
||||
.getIdProject());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUpcommingAppointmentUnkwnownUser() {
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> {
|
||||
Iterable<Appointment> a =
|
||||
this.adminApiService.getUpcomingAppointments(
|
||||
"entrepreneur-inexistent@mail.fr");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUpcommingAppointmentNoProject() {
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> {
|
||||
Iterable<Appointment> a =
|
||||
this.adminApiService.getUpcomingAppointments(
|
||||
"Entrepreneur@inpulse.com");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUpcommingAppointmentEmpty() {
|
||||
Iterable<Appointment> a =
|
||||
this.adminApiService.getUpcomingAppointments("Entrepreneur2@inpulse.com");
|
||||
assertEquals(0, IterableToList(a).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateEntrepreneurAccount() {
|
||||
assertTrue(entrepreneurService.getEntrepreneurById(entrepreneur.getIdUser()).isPending());
|
||||
assertEquals(2, IterableToList(adminApiService.getPendingUsers()).size());
|
||||
adminApiService.validateEntrepreneurAccount(entrepreneur.getIdUser(), "");
|
||||
assertFalse(entrepreneurService.getEntrepreneurById(entrepreneur.getIdUser()).isPending());
|
||||
assertEquals(1, IterableToList(adminApiService.getPendingUsers()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateApptRepport() {
|
||||
System.err.println(appt.getIdAppointment());
|
||||
SectionCell s =
|
||||
sectionCellService.addNewSectionCell(
|
||||
new SectionCell(null, 1L, "jaja", LocalDateTime.now(), p));
|
||||
appointmentService.addNewAppointment(appt);
|
||||
|
||||
appointmentService.updateAppointmentListSectionCell(appt.getIdAppointment(), s);
|
||||
projectService.updateProjectListSectionCell(p.getIdProject(), s);
|
||||
this.adminApiService.createAppointmentReport(
|
||||
appt.getIdAppointment(),
|
||||
new Report(null, "je rapporte de fou"),
|
||||
"testAdminFull@example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetAdmin() {
|
||||
assertFalse(utilsService.isAnAdmin(entrepreneur.getPrimaryMail()));
|
||||
adminApiService.setAdmin(entrepreneur.getIdUser(), "");
|
||||
assertTrue(utilsService.isAnAdmin(entrepreneur.getPrimaryMail()));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,324 @@
|
||||
package enseirb.myinpulse;
|
||||
|
||||
import static enseirb.myinpulse.model.ProjectDecisionValue.*;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import enseirb.myinpulse.model.*;
|
||||
import enseirb.myinpulse.service.EntrepreneurApiService;
|
||||
import enseirb.myinpulse.service.database.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@SpringBootTest
|
||||
@Transactional
|
||||
public class EntrepreneurApiServiceTest {
|
||||
private static Entrepreneur entrepreneur;
|
||||
private static Project project;
|
||||
private static Iterable<SectionCell> sectionCells2;
|
||||
private static Iterable<SectionCell> sectionCells3;
|
||||
@Autowired private EntrepreneurApiService entrepreneurApiService;
|
||||
@Autowired private EntrepreneurService entrepreneurService;
|
||||
@Autowired private ProjectService projectService;
|
||||
@Autowired private SectionCellService sectionCellService;
|
||||
@Autowired private AnnotationService annotationService;
|
||||
@Autowired private AppointmentService appointmentService;
|
||||
|
||||
@BeforeAll
|
||||
static void setup(
|
||||
@Autowired EntrepreneurService entrepreneurService,
|
||||
@Autowired ProjectService projectService,
|
||||
@Autowired SectionCellService sectionCellService) {
|
||||
entrepreneur =
|
||||
entrepreneurService.addEntrepreneur(
|
||||
new Entrepreneur(
|
||||
"entre",
|
||||
"preneur",
|
||||
"entrepreneur@mail.fr",
|
||||
"entrepreneur2@mail.fr",
|
||||
"01 45 71 25 48",
|
||||
"ENSEIRB",
|
||||
"Info",
|
||||
false));
|
||||
entrepreneurService.addEntrepreneur(
|
||||
new Entrepreneur(
|
||||
"entre2",
|
||||
"preneur2",
|
||||
"testentrepreneur@mail.fr",
|
||||
"testentrepreneur2@mail.fr",
|
||||
"",
|
||||
"ENSEGID",
|
||||
"",
|
||||
true));
|
||||
project =
|
||||
projectService.addNewProject(
|
||||
new Project("Project", null, LocalDate.now(), ACTIVE, null, entrepreneur));
|
||||
entrepreneurService.updateEntrepreneurProjectProposed(entrepreneur.getIdUser(), project);
|
||||
entrepreneurService.updateEntrepreneurProjectParticipation(
|
||||
entrepreneur.getIdUser(), project);
|
||||
SectionCell s1 =
|
||||
sectionCellService.addNewSectionCell(
|
||||
new SectionCell(
|
||||
null,
|
||||
2L,
|
||||
"contenu très intéressant",
|
||||
LocalDateTime.now(),
|
||||
project));
|
||||
|
||||
SectionCell s2 =
|
||||
sectionCellService.addNewSectionCell(
|
||||
new SectionCell(
|
||||
null,
|
||||
3L,
|
||||
"contenu très intéressant2",
|
||||
LocalDateTime.now(),
|
||||
project));
|
||||
sectionCells2 = sectionCellService.getSectionCellsByProject(project, 2L);
|
||||
sectionCells3 = sectionCellService.getSectionCellsByProject(project, 3L);
|
||||
}
|
||||
|
||||
private <T> List<T> IterableToList(Iterable<T> iterable) {
|
||||
List<T> l = new ArrayList<>();
|
||||
iterable.forEach(l::add);
|
||||
return l;
|
||||
}
|
||||
|
||||
@Test
|
||||
void editValidSectionCell() {
|
||||
System.out.println("editValidSectionCell : ");
|
||||
SectionCell modified = IterableToList(sectionCells2).getLast();
|
||||
this.sectionCellService.updateSectionCellListAnnotation(
|
||||
modified.getIdSectionCell(),
|
||||
annotationService.addNewAnnotation(new Annotation(null, "oui j'annote encore")));
|
||||
this.sectionCellService.updateSectionCellListAppointment(
|
||||
modified.getIdSectionCell(),
|
||||
appointmentService.addNewAppointment(
|
||||
new Appointment(
|
||||
null,
|
||||
LocalDate.now(),
|
||||
LocalTime.now(),
|
||||
LocalTime.of(2, 5),
|
||||
"TD14",
|
||||
"clément s'est plaint")));
|
||||
entrepreneurApiService.editSectionCell(
|
||||
modified.getIdSectionCell(), "modified content", "entrepreneur@mail.fr");
|
||||
// We get the data from the database again.
|
||||
SectionCell s =
|
||||
IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).getLast();
|
||||
assertEquals("modified content", s.getContentSectionCell());
|
||||
assertEquals(
|
||||
2, IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void editInvalidSectionCell() {
|
||||
System.out.println("editInvalidSectionCell : ");
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() ->
|
||||
entrepreneurApiService.editSectionCell(
|
||||
-1L, "should not be modified", "entrepreneur@mail.fr"));
|
||||
SectionCell s =
|
||||
IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).getLast();
|
||||
assertEquals("contenu très intéressant", s.getContentSectionCell());
|
||||
assertEquals(
|
||||
1, IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void editSectionCellInvalidAccess() {
|
||||
System.out.println("editSectionCellInvalidAccess : ");
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() ->
|
||||
entrepreneurApiService.editSectionCell(
|
||||
IterableToList(sectionCells3).getFirst().getIdSectionCell(),
|
||||
"should not be modified",
|
||||
"testentrepreneur@mail.fr"));
|
||||
SectionCell s =
|
||||
IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).getFirst();
|
||||
|
||||
assertEquals("contenu très intéressant", s.getContentSectionCell());
|
||||
}
|
||||
|
||||
@Test
|
||||
void editNullSectionCell() {
|
||||
System.out.println("editNullSectionCell : ");
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() ->
|
||||
entrepreneurApiService.editSectionCell(
|
||||
null, "modified content", "entrepreneur@mail.fr"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeValidSectionCell() {
|
||||
System.out.println("removeValidSectionCell : ");
|
||||
SectionCell tmpCell =
|
||||
sectionCellService.addNewSectionCell(
|
||||
new SectionCell(
|
||||
null, 2L, "contenu temporaire", LocalDateTime.now(), project));
|
||||
assertEquals(
|
||||
2, IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).size());
|
||||
assertDoesNotThrow(
|
||||
() ->
|
||||
entrepreneurApiService.removeSectionCell(
|
||||
tmpCell.getIdSectionCell(), "entrepreneur@mail.fr"));
|
||||
assertEquals(
|
||||
tmpCell.getIdReference(),
|
||||
IterableToList(sectionCellService.getSectionCellsByProject(project, -1L))
|
||||
.getLast()
|
||||
.getIdReference());
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeInvalidSectionCell() {
|
||||
System.out.println("removeInvalidSectionCell : ");
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> entrepreneurApiService.removeSectionCell(-1L, "entrepreneur@mail.fr"));
|
||||
SectionCell s =
|
||||
IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).getFirst();
|
||||
|
||||
assertEquals("contenu très intéressant", s.getContentSectionCell());
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeNullSectionCell() {
|
||||
System.out.println("removeNullSectionCell : ");
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> entrepreneurApiService.removeSectionCell(null, "entrepreneur@mail.fr"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addValidSectionCell() {
|
||||
System.out.println("addValidSectionCell : ");
|
||||
SectionCell added =
|
||||
sectionCellService.addNewSectionCell(
|
||||
new SectionCell(null, 2L, "contenu ajouté", LocalDateTime.now(), project));
|
||||
added.updateListAnnotation(
|
||||
annotationService.addNewAnnotation(new Annotation(null, "oui j'annote")));
|
||||
added.updateAppointmentSectionCell(
|
||||
appointmentService.addNewAppointment(
|
||||
new Appointment(
|
||||
null,
|
||||
LocalDate.now(),
|
||||
LocalTime.now(),
|
||||
LocalTime.of(2, 5),
|
||||
"TD15",
|
||||
"clément qui se plaint")));
|
||||
entrepreneurApiService.addSectionCell(added, "entrepreneur@mail.fr");
|
||||
SectionCell s =
|
||||
IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).getLast();
|
||||
assertEquals("contenu ajouté", s.getContentSectionCell());
|
||||
assertEquals(
|
||||
2, IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSectionCellInvalidAccess() {
|
||||
System.out.println("addSectionCellInvalidAccess : ");
|
||||
SectionCell added =
|
||||
new SectionCell(null, 2L, "contenu ajouté", LocalDateTime.now(), project);
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> entrepreneurApiService.addSectionCell(added, "fauxentrepreneur@mail.fr"));
|
||||
SectionCell s =
|
||||
IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).getLast();
|
||||
assertEquals(
|
||||
1, IterableToList(sectionCellService.getSectionCellsByProject(project, 2L)).size());
|
||||
assertEquals("contenu très intéressant", s.getContentSectionCell());
|
||||
}
|
||||
|
||||
@Test
|
||||
void addInvalidSectionCell() {
|
||||
System.out.println("addInvalidSectionCell : ");
|
||||
SectionCell added =
|
||||
sectionCellService.addNewSectionCell(
|
||||
new SectionCell(null, -1L, "contenu ajouté", LocalDateTime.now(), project));
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> entrepreneurApiService.addSectionCell(added, "entrepreneur@mail.fr"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addNullSectionCell() {
|
||||
System.out.println("addNullSectionCell : ");
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> entrepreneurApiService.addSectionCell(null, "entrepreneur@mail.fr"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void requestValidProject() {
|
||||
System.out.println("requestValidProject : ");
|
||||
int nb_project = IterableToList(this.projectService.getAllProjects()).size();
|
||||
Project validProject =
|
||||
new Project("validProject", null, LocalDate.now(), ACTIVE, null, entrepreneur);
|
||||
validProject.updateListEntrepreneurParticipation(
|
||||
IterableToList(entrepreneurService.getAllEntrepreneurs()).getLast());
|
||||
validProject.updateListSectionCell((IterableToList(sectionCells2).getFirst()));
|
||||
entrepreneurApiService.requestNewProject(validProject, "entrepreneur@mail.fr");
|
||||
assertEquals(PENDING, validProject.getProjectStatus());
|
||||
assertEquals((nb_project + 1), IterableToList(this.projectService.getAllProjects()).size());
|
||||
assertEquals(
|
||||
IterableToList(entrepreneurService.getAllEntrepreneurs()).getLast(),
|
||||
validProject.getListEntrepreneurParticipation().getLast());
|
||||
assertEquals(
|
||||
IterableToList(sectionCells2).getFirst().getIdSectionCell(),
|
||||
validProject.getListSectionCell().getFirst().getIdSectionCell());
|
||||
}
|
||||
|
||||
@Test
|
||||
void requestNullProject() {
|
||||
System.out.println("requestNullProject : ");
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> entrepreneurApiService.requestNewProject(null, "entrepreneur@mail.fr"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createNewValidAccount() {
|
||||
System.out.println("createNewValidAccount : ");
|
||||
int nb_entrepreneur = IterableToList(this.entrepreneurService.getAllEntrepreneurs()).size();
|
||||
Entrepreneur newEntrepreneur =
|
||||
new Entrepreneur(
|
||||
"New",
|
||||
"Test",
|
||||
"mailtest@test.fr",
|
||||
"mailtest2@test.fr",
|
||||
"0888888888",
|
||||
"ENSEIRB",
|
||||
"ELEC",
|
||||
false,
|
||||
true);
|
||||
assertDoesNotThrow(() -> entrepreneurApiService.createAccount(newEntrepreneur));
|
||||
assertEquals(
|
||||
(nb_entrepreneur + 1),
|
||||
IterableToList(this.entrepreneurService.getAllEntrepreneurs()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createExistingAccount() {
|
||||
System.out.println("createExistingAccount : ");
|
||||
int nb_entrepreneur = IterableToList(this.entrepreneurService.getAllEntrepreneurs()).size();
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> entrepreneurApiService.createAccount(entrepreneur));
|
||||
assertEquals(
|
||||
nb_entrepreneur,
|
||||
IterableToList(this.entrepreneurService.getAllEntrepreneurs()).size());
|
||||
}
|
||||
}
|
@ -0,0 +1,922 @@
|
||||
package enseirb.myinpulse;
|
||||
|
||||
import static enseirb.myinpulse.model.ProjectDecisionValue.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import enseirb.myinpulse.model.*;
|
||||
import enseirb.myinpulse.service.SharedApiService;
|
||||
import enseirb.myinpulse.service.database.*;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import enseirb.myinpulse.service.UtilsService;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll; // Use BeforeAll for static setup
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test; // Keep this import
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
// Helper to easily convert Iterable to List
|
||||
class TestUtils {
|
||||
static <T> List<T> toList(Iterable<T> iterable) {
|
||||
List<T> list = new ArrayList<>();
|
||||
if (iterable != null) {
|
||||
iterable.forEach(list::add);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@SpringBootTest
|
||||
@Transactional // Each @Test method runs in a transaction that is rolled back
|
||||
public class SharedApiServiceTest {
|
||||
|
||||
@Autowired private SharedApiService sharedApiService;
|
||||
|
||||
// Autowire actual services to use in setup and test verification
|
||||
@Autowired private ProjectService projectService;
|
||||
@Autowired private AdministratorService administratorService;
|
||||
@Autowired private EntrepreneurService entrepreneurService;
|
||||
@Autowired private SectionCellService sectionCellService;
|
||||
@Autowired private AppointmentService appointmentService;
|
||||
|
||||
// Mock UtilsService to control authorization logic
|
||||
@MockitoBean private UtilsService mockUtilsService;
|
||||
|
||||
// Static variables for data created once before all tests
|
||||
private static Project staticAuthorizedProject;
|
||||
private static String staticAuthorizedMail;
|
||||
private static Administrator staticAuthorizedAdmin;
|
||||
|
||||
private static Project staticUnauthorizedProject;
|
||||
private static String staticUnauthorizedMail;
|
||||
|
||||
// --- Static Setup (Runs once before all tests) ---
|
||||
// Use @BeforeAll static method with injected services
|
||||
@BeforeAll
|
||||
static void setupOnce(
|
||||
@Autowired AdministratorService administratorService,
|
||||
@Autowired ProjectService projectService,
|
||||
@Autowired EntrepreneurService entrepreneurService) {
|
||||
|
||||
// Create and Save core test data here using injected services
|
||||
staticAuthorizedAdmin =
|
||||
administratorService.addAdministrator(getTestAdmin("static_authorized_admin"));
|
||||
staticAuthorizedMail = staticAuthorizedAdmin.getPrimaryMail();
|
||||
|
||||
staticUnauthorizedProject =
|
||||
projectService.addNewProject(
|
||||
getTestProject(
|
||||
"static_unauthorized_project",
|
||||
administratorService.addAdministrator(
|
||||
getTestAdmin("static_unauthorized_admin"))));
|
||||
staticUnauthorizedMail =
|
||||
administratorService
|
||||
.addAdministrator(getTestAdmin("static_unauthorized_user"))
|
||||
.getPrimaryMail(); // User who is NOT admin of the unauthorized project
|
||||
|
||||
staticAuthorizedProject =
|
||||
projectService.addNewProject(
|
||||
getTestProject("static_authorized_project", staticAuthorizedAdmin));
|
||||
|
||||
// Link a static entrepreneur to the authorized project if needed for some tests
|
||||
// Entrepreneur staticLinkedEntrepreneur =
|
||||
// entrepreneurService.addEntrepreneur(getTestEntrepreneur("static_linked_entrepreneur"));
|
||||
// staticAuthorizedProject.updateListEntrepreneurParticipation(staticLinkedEntrepreneur);
|
||||
// projectService.addNewProject(staticAuthorizedProject); // Re-save the project after
|
||||
// updating lists
|
||||
}
|
||||
|
||||
// --- Per-Test Setup (Runs before each test method) ---
|
||||
@BeforeEach
|
||||
void setupForEach() {
|
||||
// Reset mock expectations before each test
|
||||
MockitoAnnotations.openMocks(
|
||||
this); // Needed for mocks if not using @ExtendWith(MockitoExtension.class)
|
||||
|
||||
// --- Configure the mock UtilsService based on the actual authorization rules ---
|
||||
|
||||
// Rule: Any admin can check any project.
|
||||
// Assuming staticAuthorizedMail is an admin:
|
||||
when(mockUtilsService.isAllowedToCheckProject(eq(staticAuthorizedMail), anyLong()))
|
||||
.thenReturn(true); // Admin allowed for ANY project ID
|
||||
|
||||
// Rule: An entrepreneur can only check their own stuff.
|
||||
// Assuming staticUnauthorizedMail is an entrepreneur NOT linked to staticAuthorizedProject
|
||||
// or staticUnauthorizedProject:
|
||||
when(mockUtilsService.isAllowedToCheckProject(eq(staticUnauthorizedMail), anyLong()))
|
||||
.thenReturn(false); // Unauthorized entrepreneur NOT allowed for ANY project ID by
|
||||
// default
|
||||
}
|
||||
|
||||
// --- Helper Methods (Can remain non-static or static as needed) ---
|
||||
private static Administrator getTestAdmin(String name) {
|
||||
return new Administrator(
|
||||
name + "_surname",
|
||||
name,
|
||||
name + "@example.com",
|
||||
"secondary_" + name + "@example.com",
|
||||
"0123456789");
|
||||
}
|
||||
|
||||
private static Entrepreneur getTestEntrepreneur(String name) {
|
||||
return new Entrepreneur(
|
||||
name + "_surname",
|
||||
name,
|
||||
name + "@example.com",
|
||||
"secondary_" + name + "@example.com",
|
||||
"0123456789",
|
||||
"Test School",
|
||||
"Test Course",
|
||||
false);
|
||||
}
|
||||
|
||||
private static Project getTestProject(String name, Administrator admin) {
|
||||
Project project = new Project(name, null, LocalDate.now(), ACTIVE, admin);
|
||||
return project;
|
||||
}
|
||||
|
||||
private static SectionCell getTestSectionCell(
|
||||
Project project, Long sectionId, String content, LocalDateTime date) {
|
||||
SectionCell sectionCell = new SectionCell();
|
||||
sectionCell.setProjectSectionCell(project);
|
||||
sectionCell.setSectionId(sectionId);
|
||||
sectionCell.setContentSectionCell(content);
|
||||
sectionCell.setModificationDate(date);
|
||||
return sectionCell;
|
||||
}
|
||||
|
||||
private static SectionCell getTestSectionCell(
|
||||
Project project, Long sectionId, String content, LocalDateTime date, Long refrenceId) {
|
||||
SectionCell sectionCell = new SectionCell();
|
||||
sectionCell.setProjectSectionCell(project);
|
||||
sectionCell.setSectionId(sectionId);
|
||||
sectionCell.setContentSectionCell(content);
|
||||
sectionCell.setModificationDate(date);
|
||||
sectionCell.setIdReference(refrenceId);
|
||||
return sectionCell;
|
||||
}
|
||||
|
||||
private static Appointment getTestAppointment(
|
||||
LocalDate date,
|
||||
LocalTime time,
|
||||
LocalTime duration,
|
||||
String place,
|
||||
String subject,
|
||||
List<SectionCell> sectionCells,
|
||||
Report report) {
|
||||
Appointment appointment = new Appointment();
|
||||
appointment.setAppointmentDate(date);
|
||||
appointment.setAppointmentTime(time);
|
||||
appointment.setAppointmentDuration(duration);
|
||||
appointment.setAppointmentPlace(place);
|
||||
appointment.setAppointmentSubject(subject);
|
||||
|
||||
if (sectionCells != null) {
|
||||
sectionCells.forEach(appointment::updateListSectionCell);
|
||||
}
|
||||
|
||||
if (report != null) {
|
||||
appointment.setAppointmentReport(report);
|
||||
report.setAppointmentReport(appointment);
|
||||
}
|
||||
|
||||
return appointment;
|
||||
}
|
||||
|
||||
private static Report getTestReport(String content) {
|
||||
Report report = new Report();
|
||||
report.setReportContent(content);
|
||||
return report;
|
||||
}
|
||||
|
||||
/*
|
||||
* _____ _ ____ _ _ ____ _ _
|
||||
* |_ _|__ ___| |_/ ___| ___ ___| |_(_) ___ _ __ / ___|___| | |
|
||||
* | |/ _ \/ __| __\___ \ / _ \/ __| __| |/ _ \| '_ \| | / _ \ | |
|
||||
* | | __/\__ \ |_ ___) | __/ (__| |_| | (_) | | | | |__| __/ | |
|
||||
* |_|\___||___/\__|____/ \___|\___|\__|_|\___/|_| |_|\____\___|_|_|
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tests retrieving section cells for a specific project and section ID before a given date
|
||||
* when the user is authorized but no matching cells exist.
|
||||
* Verifies that an empty list is returned.
|
||||
*/
|
||||
@Test
|
||||
void testGetSectionCells_Authorized_NotFound() {
|
||||
// Arrange: No specific section cells needed for this test, rely on clean @BeforeEach state
|
||||
Long targetSectionId = 1L;
|
||||
LocalDateTime dateFilter = LocalDateTime.now().plusDays(1);
|
||||
|
||||
// Act
|
||||
Iterable<SectionCell> result =
|
||||
sharedApiService.getSectionCells(
|
||||
staticAuthorizedProject.getIdProject(),
|
||||
targetSectionId,
|
||||
dateFilter.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
|
||||
staticAuthorizedMail);
|
||||
|
||||
List<SectionCell> resultList = TestUtils.toList(result);
|
||||
|
||||
// Assert
|
||||
assertTrue(resultList.isEmpty());
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests retrieving section cells when the user is not authorized for the project.
|
||||
* Verifies that an Unauthorized ResponseStatusException is thrown.
|
||||
*/
|
||||
@Test
|
||||
void testGetSectionCells_Unauthorized() {
|
||||
// Arrange: mockUtilsService configured in BeforeEach
|
||||
// Act & Assert
|
||||
ResponseStatusException exception =
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> {
|
||||
sharedApiService.getSectionCells(
|
||||
staticAuthorizedProject
|
||||
.getIdProject(), // Project static user is not
|
||||
// authorized for
|
||||
1L,
|
||||
LocalDateTime.now()
|
||||
.format(
|
||||
DateTimeFormatter.ofPattern(
|
||||
"yyyy-MM-dd HH:mm")),
|
||||
staticUnauthorizedMail); // Static unauthorized user mail
|
||||
});
|
||||
|
||||
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests retrieving all section cells for a project when the user is authorized
|
||||
* but the project has no section cells.
|
||||
* Verifies that an empty list is returned.
|
||||
*/
|
||||
@Test
|
||||
void testGetAllSectionCells_Authorized_NoCells() {
|
||||
// Arrange: staticAuthorizedProject has no section cells initially in BeforeAll
|
||||
// Act
|
||||
Iterable<SectionCell> result =
|
||||
sharedApiService.getAllSectionCells(
|
||||
staticAuthorizedProject.getIdProject(), staticAuthorizedMail);
|
||||
|
||||
List<SectionCell> resultList = TestUtils.toList(result);
|
||||
|
||||
// Assert
|
||||
assertTrue(resultList.isEmpty());
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests retrieving all section cells when the user is not authorized for the project.
|
||||
* Verifies that an Unauthorized ResponseStatusException is thrown.
|
||||
*/
|
||||
@Test
|
||||
void testGetAllSectionCells_Unauthorized() {
|
||||
// Arrange: mockUtilsService configured in BeforeEach
|
||||
// Act & Assert
|
||||
ResponseStatusException exception =
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> {
|
||||
sharedApiService.getAllSectionCells(
|
||||
staticAuthorizedProject.getIdProject(), staticUnauthorizedMail);
|
||||
});
|
||||
|
||||
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests retrieving section cells for a specific project and section ID before a given date
|
||||
* when the user is authorized and matching cells exist.
|
||||
* Verifies that only the correct cells are returned.
|
||||
*/
|
||||
@Test
|
||||
// Commenting out failing test
|
||||
void testGetSectionCells_Authorized_Found() {
|
||||
Long targetSectionId = 1L;
|
||||
// Set a date filter slightly in the future so our "latest before" cell is included
|
||||
LocalDateTime dateFilter = LocalDateTime.now().plusMinutes(5);
|
||||
|
||||
// Creating versions of the SAME SectionCell (share the same idReference)
|
||||
|
||||
// the first version. This will get a GENERATED idReference.
|
||||
SectionCell firstVersion =
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject,
|
||||
targetSectionId,
|
||||
"Content V1 (Oldest)",
|
||||
LocalDateTime.now().minusDays(3) // Oldest date
|
||||
);
|
||||
sectionCellService.addNewSectionCell(firstVersion);
|
||||
|
||||
Long sharedIdReference = firstVersion.getIdReference();
|
||||
assertNotNull(
|
||||
sharedIdReference,
|
||||
"idReference should be generated after saving the first version");
|
||||
System.out.println("Generated sharedIdReference: " + sharedIdReference);
|
||||
|
||||
// Create subsequent versions and MANUALLY set the SAME idReference.
|
||||
// These represent updates to the cell identified by sharedIdReference.
|
||||
|
||||
SectionCell middleVersion =
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject,
|
||||
targetSectionId,
|
||||
"Content V2 (Middle)",
|
||||
LocalDateTime.now().minusDays(2), // Middle date, before filter
|
||||
sharedIdReference);
|
||||
middleVersion = sectionCellService.addNewSectionCell(middleVersion);
|
||||
sectionCellService.updateSectionCellReferenceId(
|
||||
middleVersion.getIdSectionCell(), sharedIdReference);
|
||||
|
||||
SectionCell latestBeforeFilter =
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject,
|
||||
targetSectionId,
|
||||
"Content V3 (Latest Before Filter)",
|
||||
LocalDateTime.now().minusDays(1), // Latest date before filter
|
||||
sharedIdReference);
|
||||
latestBeforeFilter = sectionCellService.addNewSectionCell(latestBeforeFilter);
|
||||
sectionCellService.updateSectionCellReferenceId(
|
||||
latestBeforeFilter.getIdSectionCell(), sharedIdReference);
|
||||
|
||||
SectionCell futureVersion =
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject,
|
||||
targetSectionId,
|
||||
"Content V4 (Future - Should Be Excluded)",
|
||||
LocalDateTime.now().plusDays(1), // Date is AFTER the filter
|
||||
sharedIdReference);
|
||||
futureVersion = sectionCellService.addNewSectionCell(futureVersion);
|
||||
sectionCellService.updateSectionCellReferenceId(
|
||||
futureVersion.getIdSectionCell(), sharedIdReference);
|
||||
|
||||
// --- Create other SectionCells that should NOT be included (different sectionId or
|
||||
// project) ---
|
||||
|
||||
// Cell in a different section ID
|
||||
sectionCellService.addNewSectionCell(
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject,
|
||||
99L, // Different sectionId
|
||||
"Content in Different Section",
|
||||
LocalDateTime.now()));
|
||||
|
||||
// Act
|
||||
Iterable<SectionCell> result =
|
||||
sharedApiService.getSectionCells(
|
||||
staticAuthorizedProject.getIdProject(), // Use static project ID
|
||||
targetSectionId,
|
||||
dateFilter.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
|
||||
staticAuthorizedMail); // Use static authorized mail
|
||||
|
||||
List<SectionCell> resultList = TestUtils.toList(result);
|
||||
|
||||
assertEquals(1, resultList.size());
|
||||
// Verify that the returned cell is the 'latestBeforeFilter' cell
|
||||
// Comparing by idSectionCell is a good way to verify the exact entity
|
||||
assertEquals(
|
||||
latestBeforeFilter.getIdSectionCell(),
|
||||
resultList.get(0).getIdSectionCell(),
|
||||
"The returned SectionCell should be the one with the latest modification date before the filter.");
|
||||
|
||||
// Also assert the idReference and content
|
||||
assertEquals(
|
||||
sharedIdReference,
|
||||
resultList.get(0).getIdReference(),
|
||||
"The returned cell should have the shared idReference.");
|
||||
assertEquals(
|
||||
"Content V3 (Latest Before Filter)",
|
||||
resultList.get(0).getContentSectionCell(),
|
||||
"The returned cell should have the correct content.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests retrieving the most recent section cell for each unique idReference
|
||||
* within a project when the user is authorized and cells exist.
|
||||
* Verifies that only the latest version of each referenced cell is returned.
|
||||
*/
|
||||
// Tests getAllSectionCells
|
||||
@Test
|
||||
// Commenting out failing test - Removed this comment as we are fixing it
|
||||
void testGetAllSectionCells_Authorized_FoundLatest() {
|
||||
// Arrange: Create specific SectionCells for this test
|
||||
// Define the idReference values we will use for grouping
|
||||
Long refIdGroup1 = 101L;
|
||||
Long refIdGroup2 = 102L;
|
||||
Long refIdOtherProject = 103L;
|
||||
|
||||
// --- Create and Add Cells for Group 1 (refIdGroup1) ---
|
||||
// Create the older cell for group 1
|
||||
SectionCell tempOldCell1 =
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject, // Project
|
||||
1L, // Section ID (assuming this groups by section within refId)
|
||||
"Ref1 Old", // Name
|
||||
LocalDateTime.now().minusDays(3), // Date (older)
|
||||
null); // Pass null or let getTestSectionCell handle it, we'll set
|
||||
// idReference later
|
||||
final SectionCell oldCell1 =
|
||||
sectionCellService.addNewSectionCell(tempOldCell1); // Add to DB
|
||||
|
||||
// Create the newer cell for group 1
|
||||
SectionCell tempNewerCell1 =
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject, // Project
|
||||
1L, // Section ID
|
||||
"Ref1 Newer", // Name
|
||||
LocalDateTime.now().minusDays(2), // Date (newer than oldCell1)
|
||||
null); // Pass null
|
||||
final SectionCell newerCell1 =
|
||||
sectionCellService.addNewSectionCell(tempNewerCell1); // Add to DB
|
||||
|
||||
// Now, update the idReference for both cells in Group 1 to the desired value
|
||||
sectionCellService.updateSectionCellReferenceId(oldCell1.getIdSectionCell(), refIdGroup1);
|
||||
sectionCellService.updateSectionCellReferenceId(newerCell1.getIdSectionCell(), refIdGroup1);
|
||||
|
||||
// --- Create and Add Cells for Group 2 (refIdGroup2) ---
|
||||
// Create the older cell for group 2
|
||||
SectionCell tempOldCell2 =
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject, // Project
|
||||
2L, // Section ID (different section)
|
||||
"Ref2 Old", // Name
|
||||
LocalDateTime.now().minusDays(1), // Date (older than newerCell2)
|
||||
null); // Pass null
|
||||
final SectionCell oldCell2 =
|
||||
sectionCellService.addNewSectionCell(tempOldCell2); // Add to DB
|
||||
|
||||
// Create the newer cell for group 2
|
||||
SectionCell tempNewerCell2 =
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject, // Project
|
||||
2L, // Section ID
|
||||
"Ref2 Newer", // Name
|
||||
LocalDateTime.now(), // Date (latest)
|
||||
null); // Pass null
|
||||
final SectionCell newerCell2 =
|
||||
sectionCellService.addNewSectionCell(tempNewerCell2); // Add to DB
|
||||
|
||||
// Now, update the idReference for both cells in Group 2 to the desired value
|
||||
sectionCellService.updateSectionCellReferenceId(oldCell2.getIdSectionCell(), refIdGroup2);
|
||||
sectionCellService.updateSectionCellReferenceId(newerCell2.getIdSectionCell(), refIdGroup2);
|
||||
|
||||
// --- Create and Add Cell for Other Project (refIdOtherProject) ---
|
||||
Project otherProject =
|
||||
projectService.addNewProject(
|
||||
getTestProject(
|
||||
"other_project_for_cell_test",
|
||||
administratorService.addAdministrator(
|
||||
getTestAdmin("other_admin_cell_test"))));
|
||||
|
||||
SectionCell tempOtherProjectCell =
|
||||
getTestSectionCell(
|
||||
otherProject, // DIFFERENT Project
|
||||
1L, // Section ID
|
||||
"Other Project Cell", // Name
|
||||
LocalDateTime.now(), // Date
|
||||
null); // Pass null
|
||||
final SectionCell otherProjectCell =
|
||||
sectionCellService.addNewSectionCell(tempOtherProjectCell); // Add to DB
|
||||
|
||||
// Now, update the idReference for the Other Project cell
|
||||
sectionCellService.updateSectionCellReferenceId(
|
||||
otherProjectCell.getIdSectionCell(), refIdOtherProject);
|
||||
|
||||
// Act
|
||||
// Ensure the service call uses the correct project ID and mail
|
||||
Iterable<SectionCell> result =
|
||||
sharedApiService.getAllSectionCells(
|
||||
staticAuthorizedProject.getIdProject(), // Use static project ID
|
||||
staticAuthorizedMail); // Use static authorized mail
|
||||
|
||||
List<SectionCell> resultList = TestUtils.toList(result);
|
||||
|
||||
// Assert
|
||||
// We expect 2 cells from the staticAuthorizedProject:
|
||||
// - The latest one from refIdGroup1 (newerCell1)
|
||||
// - The latest one from refIdGroup2 (newerCell2)
|
||||
assertEquals(2, resultList.size());
|
||||
|
||||
// Assert that the result list contains the LATEST cell from each group within the correct
|
||||
// project
|
||||
assertTrue(
|
||||
resultList.stream()
|
||||
.anyMatch(
|
||||
cell ->
|
||||
cell.getIdSectionCell()
|
||||
.equals(newerCell1.getIdSectionCell())),
|
||||
"Should contain the latest cell for Group 1"); // Add assertion message
|
||||
assertTrue(
|
||||
resultList.stream()
|
||||
.anyMatch(
|
||||
cell ->
|
||||
cell.getIdSectionCell()
|
||||
.equals(newerCell2.getIdSectionCell())),
|
||||
"Should contain the latest cell for Group 2"); // Add assertion message
|
||||
|
||||
// Assert that the result list does NOT contain the OLDER cells from the correct project
|
||||
assertFalse(
|
||||
resultList.stream()
|
||||
.anyMatch(
|
||||
cell ->
|
||||
cell.getIdSectionCell()
|
||||
.equals(oldCell1.getIdSectionCell())),
|
||||
"Should not contain the older cell for Group 1"); // Add assertion message
|
||||
assertFalse(
|
||||
resultList.stream()
|
||||
.anyMatch(
|
||||
cell ->
|
||||
cell.getIdSectionCell()
|
||||
.equals(oldCell2.getIdSectionCell())),
|
||||
"Should not contain the older cell for Group 2"); // Add assertion message
|
||||
|
||||
// Assert that the result list does NOT contain the cell from the other project
|
||||
assertFalse(
|
||||
resultList.stream()
|
||||
.anyMatch(
|
||||
cell ->
|
||||
cell.getIdSectionCell()
|
||||
.equals(otherProjectCell.getIdSectionCell())),
|
||||
"Should not contain cells from other projects"); // Add assertion message
|
||||
}
|
||||
|
||||
/*
|
||||
* _____ _ ____ _ ____ _ _ ____
|
||||
* |_ _|__ ___| |_ / ___| ___| |_| _ \ _ __ ___ (_) ___ ___| |_| __ ) _ _
|
||||
* | |/ _ \/ __| __| | _ / _ \ __| |_) | '__/ _ \| |/ _ \/ __| __| _ \| | | |
|
||||
* | | __/\__ \ |_| |_| | __/ |_| __/| | | (_) | | __/ (__| |_| |_) | |_| |
|
||||
* _|_|\___||___/\__|\____|\___|\__|_| |_| \___// |\___|\___|\__|____/ \__, |
|
||||
* |_ _| _ \ |__/ |___/
|
||||
* | || | | |
|
||||
* | || |_| |
|
||||
* |___|____/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tests retrieving entrepreneurs linked to a project when the user is authorized
|
||||
* but no entrepreneurs are linked.
|
||||
* Verifies that an empty list is returned.
|
||||
*/
|
||||
@Test
|
||||
void testGetEntrepreneursByProjectId_Authorized_NotFound() {
|
||||
// Arrange: staticAuthorizedProject has no entrepreneurs linked initially in BeforeAll
|
||||
// Act
|
||||
Iterable<Entrepreneur> result =
|
||||
sharedApiService.getEntrepreneursByProjectId(
|
||||
staticAuthorizedProject.getIdProject(), staticAuthorizedMail);
|
||||
|
||||
List<Entrepreneur> resultList = TestUtils.toList(result);
|
||||
|
||||
// Assert
|
||||
assertTrue(resultList.isEmpty());
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests retrieving entrepreneurs linked to a project when the user is not authorized.
|
||||
* Verifies that an Unauthorized ResponseStatusException is thrown.
|
||||
*/
|
||||
@Test
|
||||
void testGetEntrepreneursByProjectId_Unauthorized() {
|
||||
// Arrange: mockUtilsService configured in BeforeEach
|
||||
// Act & Assert
|
||||
ResponseStatusException exception =
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> {
|
||||
sharedApiService.getEntrepreneursByProjectId(
|
||||
staticAuthorizedProject.getIdProject(), staticUnauthorizedMail);
|
||||
});
|
||||
|
||||
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
|
||||
}
|
||||
|
||||
/*
|
||||
* _____ _ ____ _ _ _ _ ____
|
||||
* |_ _|__ ___| |_ / ___| ___| |_ / \ __| |_ __ ___ (_)_ __ | __ ) _ _
|
||||
* | |/ _ \/ __| __| | _ / _ \ __| / _ \ / _` | '_ ` _ \| | '_ \| _ \| | | |
|
||||
* | | __/\__ \ |_| |_| | __/ |_ / ___ \ (_| | | | | | | | | | | |_) | |_| |
|
||||
* _|_|\___||___/\__|\____|\___|\__/_/ \_\__,_|_| |_| |_|_|_| |_|____/ \__, |
|
||||
* |_ _| _ \ |___/
|
||||
* | || | | |
|
||||
* | || |_| |
|
||||
* |___|____/
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tests retrieving appointments linked to a project's section cells when the user is authorized
|
||||
* but no such appointments exist.
|
||||
* Verifies that an empty list is returned.
|
||||
*/
|
||||
@Test
|
||||
void testGetAppointmentsByProjectId_Authorized_NotFound() {
|
||||
// Arrange: staticAuthorizedProject has no linked section cells or appointments initially
|
||||
// Act
|
||||
Iterable<Appointment> result =
|
||||
sharedApiService.getAppointmentsByProjectId(
|
||||
staticAuthorizedProject.getIdProject(), staticAuthorizedMail);
|
||||
|
||||
List<Appointment> resultList = TestUtils.toList(result);
|
||||
|
||||
// Assert
|
||||
assertTrue(resultList.isEmpty());
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests retrieving the administrator linked to a project when the user is authorized
|
||||
* and an administrator is linked.
|
||||
* Verifies that the correct administrator is returned.
|
||||
*/
|
||||
// Tests getAdminByProjectId
|
||||
@Test
|
||||
void testGetAdminByProjectId_Authorized_Found() {
|
||||
// Arrange: staticAuthorizedProject is created with staticAuthorizedAdmin in BeforeAll
|
||||
// Act
|
||||
Administrator result =
|
||||
sharedApiService.getAdminByProjectId(
|
||||
staticAuthorizedProject.getIdProject(), staticAuthorizedMail);
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(staticAuthorizedAdmin.getIdUser(), result.getIdUser());
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests retrieving the administrator linked to a project when the user is not authorized.
|
||||
* Verifies that an Unauthorized ResponseStatusException is thrown.
|
||||
*/
|
||||
@Test
|
||||
void testGetAdminByProjectId_Unauthorized() {
|
||||
// Arrange: mockUtilsService configured in BeforeEach
|
||||
// Act & Assert
|
||||
ResponseStatusException exception =
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> {
|
||||
sharedApiService.getAdminByProjectId(
|
||||
staticAuthorizedProject.getIdProject(), staticUnauthorizedMail);
|
||||
});
|
||||
|
||||
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
|
||||
}
|
||||
|
||||
/*
|
||||
* _____ _
|
||||
* |_ _|__ ___| |_
|
||||
* | |/ _ \/ __| __|
|
||||
* | | __/\__ \ |_
|
||||
* |_|\___||___/\__| _ _ _
|
||||
* / \ _ __ _ __ ___ (_)_ __ | |_ ___ _ __ ___ ___ _ __ | |_ ___
|
||||
* / _ \ | '_ \| '_ \ / _ \| | '_ \| __/ _ \ '_ ` _ \ / _ \ '_ \| __/ __|
|
||||
* / ___ \| |_) | |_) | (_) | | | | | || __/ | | | | | __/ | | | |_\__ \
|
||||
* /_/ \_\ .__/| .__/ \___/|_|_| |_|\__\___|_| |_| |_|\___|_| |_|\__|___/
|
||||
* |_| |_|
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tests retrieving appointments linked to a project's section cells when the user is not authorized.
|
||||
* Verifies that an Unauthorized ResponseStatusException is thrown.
|
||||
*/
|
||||
@Test
|
||||
void testGetAppointmentsByProjectId_Unauthorized() {
|
||||
// Arrange: mockUtilsService configured in BeforeEach
|
||||
// Act & Assert
|
||||
ResponseStatusException exception =
|
||||
assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> {
|
||||
sharedApiService.getAppointmentsByProjectId(
|
||||
staticAuthorizedProject.getIdProject(), staticUnauthorizedMail);
|
||||
});
|
||||
|
||||
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
|
||||
}
|
||||
|
||||
@PersistenceContext // Inject EntityManager
|
||||
private EntityManager entityManager;
|
||||
|
||||
// Assume these static variables are defined elsewhere in your test class
|
||||
// private static Project staticAuthorizedProject;
|
||||
// private static String staticAuthorizedMail;
|
||||
// private static Administrator staticAuthorizedAdmin;
|
||||
|
||||
// Assume getTestSectionCell, getTestProject, getTestAdmin, getTestAppointment, TestUtils.toList
|
||||
// are defined elsewhere
|
||||
|
||||
@Test
|
||||
void testGetAppointmentsByProjectId_Authorized_Found() {
|
||||
// Arrange: Create specific SectionCells and Appointments for this test
|
||||
SectionCell cell1 =
|
||||
sectionCellService.addNewSectionCell(
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject, 1L, "Cell 1 Test", LocalDateTime.now()));
|
||||
SectionCell cell2 =
|
||||
sectionCellService.addNewSectionCell(
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject, 2L, "Cell 2 Test", LocalDateTime.now()));
|
||||
Project otherProject =
|
||||
projectService.addNewProject(
|
||||
getTestProject(
|
||||
"other_project_app_test",
|
||||
administratorService.addAdministrator(
|
||||
getTestAdmin("other_admin_app_test"))));
|
||||
SectionCell otherProjectCell =
|
||||
sectionCellService.addNewSectionCell(
|
||||
getTestSectionCell(
|
||||
otherProject,
|
||||
1L,
|
||||
"Other Project Cell App Test",
|
||||
LocalDateTime.now()));
|
||||
|
||||
// Create Appointments with SectionCells lists (Owning side)
|
||||
Appointment app1 =
|
||||
getTestAppointment(
|
||||
LocalDate.now().plusDays(10),
|
||||
LocalTime.NOON,
|
||||
LocalTime.of(0, 30),
|
||||
"Place 1 App Test",
|
||||
"Subject 1 App Test",
|
||||
List.of(cell1), // This links Appointment to SectionCell
|
||||
null);
|
||||
Appointment savedApp1 = appointmentService.addNewAppointment(app1);
|
||||
|
||||
Appointment app2 =
|
||||
getTestAppointment(
|
||||
LocalDate.now().plusDays(11),
|
||||
LocalTime.NOON.plusHours(1),
|
||||
LocalTime.of(1, 0),
|
||||
"Place 2 App Test",
|
||||
"Subject 2 App Test",
|
||||
List.of(cell1, cell2), // This links Appointment to SectionCells
|
||||
null);
|
||||
Appointment savedApp2 = appointmentService.addNewAppointment(app2);
|
||||
|
||||
Appointment otherApp =
|
||||
getTestAppointment(
|
||||
LocalDate.now().plusDays(12),
|
||||
LocalTime.MIDNIGHT,
|
||||
LocalTime.of(0, 15),
|
||||
"Other Place App Test",
|
||||
"Other Subject App Test",
|
||||
List.of(otherProjectCell), // This links Appointment to SectionCell
|
||||
null);
|
||||
Appointment savedOtherApp =
|
||||
appointmentService.addNewAppointment(otherApp); // Capture saved entity
|
||||
|
||||
// --- IMPORTANT DEBUGGING STEPS ---
|
||||
// Flush pending changes to the database (including join table inserts)
|
||||
entityManager.flush();
|
||||
// Clear the persistence context cache to ensure entities are loaded fresh from the database
|
||||
entityManager.clear();
|
||||
// --- END IMPORTANT DEBUGGING STEPS ---
|
||||
|
||||
// --- Add Debug Logging Here ---
|
||||
// Re-fetch cells to see their state after saving Appointments and flushing/clearing cache
|
||||
// These fetches should load from the database due to entityManager.clear()
|
||||
SectionCell fetchedCell1_postPersist =
|
||||
sectionCellService.getSectionCellById(cell1.getIdSectionCell());
|
||||
SectionCell fetchedCell2_postPersist =
|
||||
sectionCellService.getSectionCellById(cell2.getIdSectionCell());
|
||||
SectionCell fetchedOtherCell_postPersist =
|
||||
sectionCellService.getSectionCellById(otherProjectCell.getIdSectionCell());
|
||||
|
||||
// Access the lazy collections to see if they are populated from the DB
|
||||
// This access should trigger lazy loading if the data is in the DB
|
||||
List<Appointment> cell1Apps_postPersist =
|
||||
fetchedCell1_postPersist.getAppointmentSectionCell();
|
||||
List<Appointment> cell2Apps_postPersist =
|
||||
fetchedCell2_postPersist.getAppointmentSectionCell();
|
||||
List<Appointment> otherCellApps_postPersist =
|
||||
fetchedOtherCell_postPersist.getAppointmentSectionCell();
|
||||
|
||||
// Ensure logging is enabled in SharedApiService and SectionCellService methods called below
|
||||
Iterable<Appointment> result =
|
||||
sharedApiService.getAppointmentsByProjectId(
|
||||
staticAuthorizedProject.getIdProject(), // Use static project ID
|
||||
staticAuthorizedMail); // Use static authorized mail
|
||||
|
||||
List<Appointment> resultList = TestUtils.toList(result);
|
||||
|
||||
// Assert
|
||||
assertEquals(2, resultList.size());
|
||||
|
||||
assertTrue(
|
||||
resultList.stream()
|
||||
.anyMatch(a -> a.getIdAppointment().equals(savedApp1.getIdAppointment())));
|
||||
assertTrue(
|
||||
resultList.stream()
|
||||
.anyMatch(a -> a.getIdAppointment().equals(savedApp2.getIdAppointment())));
|
||||
|
||||
assertFalse(
|
||||
resultList.stream()
|
||||
.anyMatch(
|
||||
a ->
|
||||
a.getIdAppointment()
|
||||
.equals(savedOtherApp.getIdAppointment())));
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests creating a new appointment request when the user is authorized
|
||||
* for the project linked to the appointment's section cell.
|
||||
* Verifies that the appointment and its relationships are saved correctly in the database.
|
||||
*/
|
||||
// Tests createAppointmentRequest
|
||||
@Test
|
||||
// Commenting out failing test
|
||||
void testCreateAppointmentRequest_Authorized_Success() {
|
||||
// Arrange: Create transient appointment linked to a cell in the static authorized project
|
||||
LocalDate date = LocalDate.parse("2026-01-01");
|
||||
LocalTime time = LocalTime.parse("10:00:00");
|
||||
LocalTime duration = LocalTime.parse("00:30:00");
|
||||
String place = "Meeting Room Integrated";
|
||||
String subject = "Discuss Project Integrated";
|
||||
|
||||
SectionCell linkedCell =
|
||||
sectionCellService.addNewSectionCell(
|
||||
getTestSectionCell(
|
||||
staticAuthorizedProject,
|
||||
0L,
|
||||
"Related Section Content Integrated",
|
||||
LocalDateTime.now()));
|
||||
|
||||
Report newReport = null; // getTestReport(reportContent); // Uses no-arg constructor
|
||||
|
||||
Appointment newAppointment =
|
||||
getTestAppointment(
|
||||
date, time, duration, place, subject, List.of(linkedCell), newReport);
|
||||
|
||||
// mockUtilsService is configured in BeforeEach to allow staticAuthorizedMail for
|
||||
// staticAuthorizedProject
|
||||
|
||||
// Act
|
||||
// Allow the service method to call the actual appointmentService.addNewAppointment
|
||||
assertDoesNotThrow(
|
||||
() ->
|
||||
sharedApiService.createAppointmentRequest(
|
||||
newAppointment, staticAuthorizedMail));
|
||||
|
||||
// Assert: Retrieve the appointment from the DB and verify it and its relationships were
|
||||
// saved
|
||||
// We find it by looking for appointments linked to the authorized project's cells
|
||||
Iterable<SectionCell> projectCells =
|
||||
sectionCellService.getSectionCellsByProject(
|
||||
staticAuthorizedProject, linkedCell.getSectionId()); // Fetch relevant cells
|
||||
List<Appointment> projectAppointmentsList = new ArrayList<>();
|
||||
projectCells.forEach(
|
||||
cell ->
|
||||
projectAppointmentsList.addAll(
|
||||
sectionCellService.getAppointmentsBySectionCellId(
|
||||
cell.getIdSectionCell()))); // Get appointments for
|
||||
// those cells
|
||||
|
||||
Optional<Appointment> createdAppointmentOpt =
|
||||
projectAppointmentsList.stream()
|
||||
.filter(
|
||||
a ->
|
||||
a.getAppointmentDate().equals(date)
|
||||
&& a.getAppointmentTime().equals(time)
|
||||
&& a.getAppointmentPlace().equals(place)
|
||||
&& a.getAppointmentSubject().equals(subject))
|
||||
.findFirst();
|
||||
|
||||
assertTrue(createdAppointmentOpt.isPresent());
|
||||
Appointment createdAppointment = createdAppointmentOpt.get();
|
||||
|
||||
// FIX: Corrected bidirectional link check
|
||||
assertEquals(1, createdAppointment.getAppointmentListSectionCell().size());
|
||||
assertTrue(
|
||||
createdAppointment.getAppointmentListSectionCell().stream()
|
||||
.anyMatch(
|
||||
sc -> sc.getIdSectionCell().equals(linkedCell.getIdSectionCell())));
|
||||
|
||||
List<Appointment> appointmentsLinkedToCell =
|
||||
TestUtils.toList(
|
||||
sectionCellService.getAppointmentsBySectionCellId(
|
||||
linkedCell.getIdSectionCell()));
|
||||
assertTrue(
|
||||
appointmentsLinkedToCell.stream()
|
||||
.anyMatch(
|
||||
a ->
|
||||
a.getIdAppointment()
|
||||
.equals(createdAppointment.getIdAppointment())));
|
||||
}
|
||||
}
|
@ -48,4 +48,4 @@ services:
|
||||
# container_name: MyINPulse-back
|
||||
# ports:
|
||||
# - "8081:8080"
|
||||
#
|
||||
|
@ -16,7 +16,7 @@ BACKEND_PASSWORD=backend_db_user_password
|
||||
DATABASE_URL=localhost:5433
|
||||
|
||||
VITE_KEYCLOAK_URL=http://localhost:7080
|
||||
VITE_KEYCLOAK_CLIENT_ID=myinpulse-dev
|
||||
VITE_KEYCLOAK_REALM=test
|
||||
VITE_KEYCLOAK_CLIENT_ID=MyINPulse-vite
|
||||
VITE_KEYCLOAK_REALM=MyINPulse
|
||||
VITE_APP_URL=http://localhost:5173
|
||||
VITE_BACKEND_URL=http://localhost:8081/
|
||||
|
@ -42,11 +42,11 @@ services:
|
||||
# ports:
|
||||
# - "8080:80"
|
||||
|
||||
#back:
|
||||
# build:
|
||||
# context: ./MyINPulse-back/
|
||||
# dockerfile: Dockerfile
|
||||
# container_name: MyINPulse-back
|
||||
# ports:
|
||||
# - "8081:8080"
|
||||
back:
|
||||
build:
|
||||
context: ./MyINPulse-back/
|
||||
dockerfile: Dockerfile
|
||||
container_name: MyINPulse-back
|
||||
ports:
|
||||
- "8081:8080"
|
||||
|
@ -45,11 +45,11 @@ services:
|
||||
ports:
|
||||
- "8080:80"
|
||||
|
||||
#back:
|
||||
# build:
|
||||
# context: ./MyINPulse-back/
|
||||
# dockerfile: Dockerfile
|
||||
# container_name: MyINPulse-back
|
||||
# #ports:
|
||||
# # - "8081:8080"
|
||||
back:
|
||||
build:
|
||||
context: ./MyINPulse-back/
|
||||
dockerfile: Dockerfile
|
||||
container_name: MyINPulse-back
|
||||
#ports:
|
||||
# - "8081:8080"
|
||||
|
@ -5,43 +5,9 @@
|
||||
- `/entrepreneur/lcsection/modify/{sectionId}` → `/entrepreneur/sectionCell/modify/{sectionId}`
|
||||
|
||||
### Admin api
|
||||
- `/admin/appointments/upcoming`: is shared not admin
|
||||
- `/admin/projects/decision`: instanciates classes with `adminId` instead of taking the id from the token
|
||||
- `/admin/project/add`:
|
||||
- point 1: the doc has this `projects` everywhere this should be `/admin/projects/add` to avoid confusion I think
|
||||
- point 2: this doesn't assiociate users with a project I need to add other endopint for that
|
||||
- `/admin/appoitements/report/{appointmentId}`:
|
||||
- typo: `appoitements` → `appointments`
|
||||
- `/admin/projects/remove/{projectId}`, `/admin/project/add`, `/admin/projects/decision`, `/admin/projects/pending`:
|
||||
- should need token to delete or add project
|
||||
- `/admin/appointments/report/{appointmentId}` has no PUT and DELETE
|
||||
- `/admin/request-join` and `/admin/request-join/decision/{joinRequestId}` have not yet been implemented
|
||||
|
||||
### Entrepreneur api
|
||||
- `/entrepreneur/sectionCell/modify/{sectionId}`:
|
||||
- the section-id because of the definition of `sectionCell` schema the `sectionId` is given twice possibly leading to inconsistency. Which is why the path var to be removed:
|
||||
- → `/entrepreneur/sectionCell/modify`
|
||||
|
||||
### Shared api
|
||||
- `/shared/project/sectionCell/{projectId}/{sectionId}/{date}`:
|
||||
- point 1:
|
||||
same point for `project` → `projects`
|
||||
- point 2:
|
||||
have yet to read `sharedApiService` to see how dates are handled and to see if we agree on values of `date` to make it so it gets the version relative to current date
|
||||
- `/shared/entrepreneurs/{projectId}`:
|
||||
- maybe change to `/shared/projects/entrepreneurs/{projectId}` to match other similair endpoints like `/shared/projects/admin/{projectId}`
|
||||
- `/shared/appointment/request`:
|
||||
- creates the apointement but don't know how it associates other users, potentially multiple classes in one request body, is that possible ?
|
||||
|
||||
## TODOs for me
|
||||
|
||||
### list 1:
|
||||
- add back-end server links (backend and auth) for interacting with api through swagger
|
||||
- get config for that set up in the project
|
||||
|
||||
### list 2:
|
||||
- see what to do about logo img
|
||||
- see format for date and add it in examples
|
||||
- ask the form of return of the json of iterables, for now I have put array
|
||||
- add endpoint for adding users to a project
|
||||
- update endpoint descriptions
|
||||
- add examples for values in schemas
|
||||
### Unauth api
|
||||
- `/unauth/request-join/{projectId}` has not yet been implemented
|
||||
|
||||
|
@ -1,214 +1,387 @@
|
||||
# _ ____ __ __ ___ _ _ _ ____ ___
|
||||
# / \ | _ \| \/ |_ _| \ | | / \ | _ \_ _|
|
||||
# / _ \ | | | | |\/| || || \| | / _ \ | |_) | |
|
||||
# / ___ \| |_| | | | || || |\ | / ___ \| __/| |
|
||||
# /_/ \_\____/|_| |_|___|_| \_| /_/ \_\_| |___|
|
||||
#
|
||||
# Admin API Endpoints
|
||||
paths:
|
||||
/admin/projects:
|
||||
get:
|
||||
summary: Retourne la liste of projets associés à l'admin
|
||||
tags:
|
||||
- Admin API
|
||||
operationId: getAdminProjects
|
||||
summary: Get projects associated with the admin
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
description:
|
||||
JSON array of who's elements are objects containing necessary information for the view
|
||||
(project name, entrepreneur names, etc..)
|
||||
of the projects an admin is watching over.
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
description: Retrieves a list of projects managed by the requesting admin, including details for overview.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
description: OK - List of projects returned successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "main.yaml#/components/schemas/project"
|
||||
$ref: "./main.yaml#/components/schemas/project"
|
||||
"400":
|
||||
description: Bad request
|
||||
description: Bad Request - Invalid project data provided (e.g., missing required fields).
|
||||
"401":
|
||||
description: Authorization information is missing or invalid
|
||||
description: Unauthorized - Authentication required or invalid token.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
post:
|
||||
operationId: addProjectManually
|
||||
summary: Manually add a new project
|
||||
description: Creates a new project with the provided details. (NOTE that this meant for manually inserting projects, for example importing already existing projects).
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
requestBody:
|
||||
required: true
|
||||
description: Project details to create. `idProject` and `creationDate` will be ignored if sent and set by the server.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "./main.yaml#/components/schemas/project"
|
||||
responses:
|
||||
"200": # Use 200 Created for successful creation
|
||||
description: Created - Project added successfully. Returns the created project.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "./main.yaml#/components/schemas/project"
|
||||
"409":
|
||||
description: Bad Request - Project already exists.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
|
||||
/admin/projects/pending:
|
||||
get:
|
||||
operationId: getPendingProjects
|
||||
summary: Get projects awaiting validation
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
description: Retrieves a list of projects submitted by entrepreneurs that are pending admin approval.
|
||||
responses:
|
||||
"200":
|
||||
description: OK - List of pending projects returned.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "./main.yaml#/components/schemas/project" # Assuming pending projects use the same schema
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/admin/request-join:
|
||||
get:
|
||||
operationId: getPendingProjects
|
||||
summary: Get entrepreneurs project join requests
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
description: Retrieves a list of pending requests from entrepreneurs to join an existing project.
|
||||
responses:
|
||||
"200":
|
||||
description: OK - List of pending project join requests.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "./main.yaml#/components/schemas/joinRequest"
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/admin/request-join/decision/{joinRequestId}:
|
||||
post:
|
||||
summary: Approve or reject a pending project join request
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
parameters:
|
||||
- in: path
|
||||
name: joinRequestId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: The ID of the pending join request to decide upon.
|
||||
|
||||
description: |-
|
||||
Allows an admin to make a decision on an ebtrepreneur's request to join an existing project awaiting validation.
|
||||
If approved (isAccepted=true), the entrepreneur is linked to the project with ID joinRequestId.
|
||||
If rejected (isAccepted=false), the pending request data might be archived or deleted based on business logic.
|
||||
responses:
|
||||
"200":
|
||||
description: OK - No Content, decision processed successfully..
|
||||
content:
|
||||
application/json:
|
||||
$ref: "./main.yaml#/components/schemas/joinRequestDecision"
|
||||
"400":
|
||||
description: Bad Request - Invalid input (e.g., missing decision).
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
|
||||
/admin/projects/pending/decision:
|
||||
post:
|
||||
summary: valider un projet en attente de validation
|
||||
operationId: decidePendingProject
|
||||
summary: Approve or reject a pending project
|
||||
tags:
|
||||
- Admin API
|
||||
description:
|
||||
if the request is accepted the status of the
|
||||
project is changed to ongoing, entrepreneur
|
||||
account is confirmed and the project is linked
|
||||
to the admin accepting the request and the
|
||||
entrepreneur requesting it. Else the pending
|
||||
project and user info are deleted.
|
||||
description: |-
|
||||
Allows an admin to make a decision on a project awaiting validation.
|
||||
If approved (isAccepted=true), the project status changes, and it's linked to the involved users.
|
||||
If rejected (isAccepted=false), the pending project data might be archived or deleted based on business logic.
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
requestBody:
|
||||
required: true
|
||||
description: Decision payload.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
pedingProjectId:
|
||||
type: integer
|
||||
decision:
|
||||
type: boolean
|
||||
|
||||
$ref: './main.yaml#/components/schemas/projectDecision'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"200": # Use 200 No Content for successful action with no body
|
||||
description: No Content - Decision processed successfully.
|
||||
"400":
|
||||
description: Bad request
|
||||
description: Bad Request - Invalid input (e.g., missing decision).
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
|
||||
/admin/projects/add:
|
||||
post:
|
||||
summary: Ajout manuel d'un projet
|
||||
description:
|
||||
Adds a project with the
|
||||
inputed details
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
|
||||
/admin/pending-accounts: # Path updated
|
||||
get:
|
||||
operationId: getPendingAccounts
|
||||
summary: Get accounts awaiting validation
|
||||
description: Retrieves a list of entrepreneur user accounts that are pending admin validation.
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "main.yaml#/components/schemas/project"
|
||||
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad request
|
||||
"200":
|
||||
description: OK - List of pending accounts returned.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "./main.yaml#/components/schemas/user-entrepreneur"
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/admin/accounts/validate/{userId}:
|
||||
post: # Changed to POST as it changes state
|
||||
operationId: validateUserAccount
|
||||
summary: Validate a pending user account
|
||||
description: Marks the user account specified by userId as validated/active.
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
parameters:
|
||||
- in: path
|
||||
name: userId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: The ID of the user account to validate.
|
||||
example: 102
|
||||
responses:
|
||||
"200":
|
||||
description: No Content - Account validated successfully.
|
||||
"400":
|
||||
description: Bad Request - Invalid user ID format.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
|
||||
/admin/appointments/upcoming:
|
||||
get:
|
||||
operationId: getUpcomingAppointments
|
||||
summary: Get upcoming appointments for an admin
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
description: Retrieves a list of appointments scheduled for an admin in the future.
|
||||
responses:
|
||||
"200":
|
||||
description: OK - List of upcoming appointments.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "./main.yaml#/components/schemas/appointment"
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"404":
|
||||
description: no appointments found.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
|
||||
/admin/appointments/report/{appointmentId}:
|
||||
put:
|
||||
summary: enregistrer un rapport du rendez-vous
|
||||
description:
|
||||
Generate a PDF file formatted
|
||||
from input text and links it
|
||||
to the appointement.
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
parameters:
|
||||
- in: path
|
||||
name: appointmentId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "main.yaml#/components/schemas/report"
|
||||
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
post:
|
||||
summary: modifier un rapport déja éxistant du rendez-vous
|
||||
description:
|
||||
Modifies the report file to input
|
||||
text and links it to the appointement.
|
||||
operationId: createAppointmentReport
|
||||
summary: Create a report for an appointment
|
||||
description: Creates and links a new report (e.g., meeting minutes) to the specified appointment using the provided content.
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
parameters:
|
||||
- in: path
|
||||
name: appointmentId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: ID of the appointment to add a report to.
|
||||
example: 303
|
||||
requestBody:
|
||||
required: true
|
||||
description: Report content. `idReport` will be ignored if sent.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "main.yaml#/components/schemas/report"
|
||||
|
||||
$ref: "./main.yaml#/components/schemas/report"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"200":
|
||||
description: Created - Report created and linked successfully. Returns the created report.
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "./main.yaml#/components/schemas/report" }
|
||||
"400":
|
||||
description: Bad request
|
||||
description: Bad Request - Invalid input (e.g., missing content, invalid appointment ID format).
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
|
||||
|
||||
/admin/projects/remove/{projectId}:
|
||||
delete:
|
||||
summary: supression d'un project
|
||||
description:
|
||||
Removes the project
|
||||
with the inputed id projectId
|
||||
description: Unauthorized.
|
||||
|
||||
put: # Changed to PUT for update/replacement
|
||||
operationId: updateAppointmentReport
|
||||
summary: Update an existing appointment report
|
||||
description: Updates the content of an existing report linked to the specified appointment. Replaces the entire report content.
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
parameters:
|
||||
- in: path
|
||||
name: appointmentId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: ID of the appointment whose report needs updating.
|
||||
example: 303
|
||||
requestBody:
|
||||
required: true
|
||||
description: New report content. `idReport` in the body should match the existing report's ID or will be ignored.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "./main.yaml#/components/schemas/report"
|
||||
responses:
|
||||
"200":
|
||||
description: OK - Report updated successfully. Returns the updated report.
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "./main.yaml#/components/schemas/report" }
|
||||
"400":
|
||||
description: Bad Request - Invalid input (e.g., missing content).
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
|
||||
|
||||
/admin/projects/{projectId}:
|
||||
delete:
|
||||
operationId: removeProject
|
||||
summary: Remove a project
|
||||
description: Permanently removes the project specified by projectId and potentially related data (use with caution).
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
|
||||
|
||||
/admin/projects/pending:
|
||||
get:
|
||||
summary: Retourne la liste des projets en attente de validation
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
description:
|
||||
JSON array of who's elements are objects containing
|
||||
necessary information for the view (project name, etc..)
|
||||
of all pending projects.
|
||||
description: The ID of the project to remove.
|
||||
example: 12
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "main.yaml#/components/schemas/project"
|
||||
description: No Content - Project removed successfully.
|
||||
"400":
|
||||
description: Bad request
|
||||
description: Bad Request - Invalid project ID format.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"401":
|
||||
description: Authorization information is missing or invalid
|
||||
description: Unauthorized.
|
||||
|
||||
|
||||
|
||||
/admin/make-admin/{userId}:
|
||||
post:
|
||||
operationId: grantAdminRights
|
||||
summary: Grant admin rights to a user
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
description: Elevates the specified user to also have administrator privileges. Assumes the user already exists.
|
||||
parameters:
|
||||
- in: path
|
||||
name: userId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: The ID of the user to grant admin rights.
|
||||
example: 103
|
||||
responses:
|
||||
"200": # Use 200 No Content
|
||||
description: No Content - Admin rights granted successfully.
|
||||
"400":
|
||||
description: Bad Request - Invalid user ID format or user is already an admin.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
|
||||
/admin/create-account:
|
||||
post:
|
||||
summary: Creates Admin out Jwt Token
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-admin]
|
||||
description: Create an admin instance in the MyINPulse DB of the information provided from the authenticated user's keycloack token.
|
||||
The information required in the token are `userSurname`, `username`, `primaryMail`, `secondaryMail`, `phoneNumber`.
|
||||
responses:
|
||||
"200":
|
||||
description: No Content - Admin user created successfully.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
@ -1,600 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: MyInpulse Backend Api
|
||||
description: this document servers as a documentation for the backend api.
|
||||
version: 0.2.0
|
||||
tags:
|
||||
- name: Entrepreneurs API
|
||||
description: La partie de l'api dédiée aux entrepreneurs
|
||||
- name: Admin API
|
||||
description: La partie de l'api dédiée aux entrepreneurs
|
||||
- name: Shared API
|
||||
description: La partie de l'api dédiée aux entrepreneurs et admins
|
||||
components:
|
||||
schemas:
|
||||
user:
|
||||
type: object
|
||||
properties:
|
||||
idUser:
|
||||
type: integer
|
||||
userSurname:
|
||||
type: string
|
||||
userName:
|
||||
type: string
|
||||
primaryMail:
|
||||
type: string
|
||||
example: example@exmaple.com
|
||||
secondaryMail:
|
||||
type: string
|
||||
example: example@exmaple.com
|
||||
phoneNumber:
|
||||
type: string
|
||||
example: 0612345678
|
||||
user-entrepreneur:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/user'
|
||||
- type: object
|
||||
properties:
|
||||
school:
|
||||
type: string
|
||||
example: enseirb
|
||||
course:
|
||||
type: string
|
||||
example: info
|
||||
sneeStatus:
|
||||
type: boolean
|
||||
example: false
|
||||
user-admin:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/user'
|
||||
sectionCell:
|
||||
type: object
|
||||
properties:
|
||||
idSectionCell:
|
||||
type: integer
|
||||
example: this the cell (postit id)
|
||||
sectionId:
|
||||
type: integer
|
||||
contentSectionCell:
|
||||
type: string
|
||||
modificationDate:
|
||||
type: string
|
||||
example: 02-05-2025
|
||||
project:
|
||||
type: object
|
||||
properties:
|
||||
idProject:
|
||||
type: integer
|
||||
projectName:
|
||||
type: string
|
||||
creationDate:
|
||||
type: string
|
||||
example: 02-05-2025
|
||||
logo:
|
||||
example: to be discussed not yet fixed
|
||||
type: string
|
||||
format: binary
|
||||
report:
|
||||
type: object
|
||||
properties:
|
||||
idReport:
|
||||
type: integer
|
||||
reportContent:
|
||||
type: string
|
||||
appointement:
|
||||
type: object
|
||||
properties:
|
||||
appointmentDate:
|
||||
type: string
|
||||
example: 02-05-2025
|
||||
appointmentTime:
|
||||
type: string
|
||||
example: '10:15:30'
|
||||
appointmentDuration:
|
||||
type: string
|
||||
appointmentPlace:
|
||||
type: string
|
||||
appointmentSubject:
|
||||
type: string
|
||||
securitySchemes:
|
||||
MyINPulse:
|
||||
type: oauth2
|
||||
flows:
|
||||
implicit:
|
||||
authorizationUrl: 'http://localhost:7080'
|
||||
scopes:
|
||||
MyINPulse-admin: Administrateur
|
||||
MyINPulse-entrepreneur: Utilisateur
|
||||
servers:
|
||||
- url: 'http://localhost:8081/'
|
||||
description: Backend server
|
||||
paths:
|
||||
/admin/projects:
|
||||
get:
|
||||
summary: Retourne la liste of projets associés à l'admin
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
description: 'JSON array of who''s elements are objects containing necessary information for the view (project name, entrepreneur names, etc..) of the projects an admin is watching over.'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/project'
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
/admin/projects/pending/decision:
|
||||
post:
|
||||
summary: valider un projet en attente de validation
|
||||
tags:
|
||||
- Admin API
|
||||
description: 'if the request is accepted the status of the project is changed to ongoing, entrepreneur account is confirmed and the project is linked to the admin accepting the request and the entrepreneur requesting it. Else the pending project and user info are deleted.'
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
pedingProjectId:
|
||||
type: integer
|
||||
decision:
|
||||
type: boolean
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
/admin/projects/add:
|
||||
post:
|
||||
summary: Ajout manuel d'un projet
|
||||
description: Adds a project with the inputed details
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/project'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
'/admin/appointments/report/{appointmentId}':
|
||||
put:
|
||||
summary: enregistrer un rapport du rendez-vous
|
||||
description: Generate a PDF file formatted from input text and links it to the appointement.
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
parameters:
|
||||
- in: path
|
||||
name: appointmentId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/report'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
post:
|
||||
summary: modifier un rapport déja éxistant du rendez-vous
|
||||
description: Modifies the report file to input text and links it to the appointement.
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
parameters:
|
||||
- in: path
|
||||
name: appointmentId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/report'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
'/admin/projects/remove/{projectId}':
|
||||
delete:
|
||||
summary: supression d'un project
|
||||
description: Removes the project with the inputed id projectId
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
/admin/projects/pending:
|
||||
get:
|
||||
summary: Retourne la liste des projets en attente de validation
|
||||
tags:
|
||||
- Admin API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
description: 'JSON array of who''s elements are objects containing necessary information for the view (project name, etc..) of all pending projects.'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/project'
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
/shared/appointments/upcoming:
|
||||
get:
|
||||
summary: Retourne la list des prochains rendez-vous de l'utilisateur
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description: 'JSON array of upcoming appointment data (name, date, time etc..) for a user.'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/appointement'
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
'/shared/projects/sectionCell/{projectId}/{sectionId}/{date}':
|
||||
get:
|
||||
summary: Retourne la liste de sections de LC avec un titre donné
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description: JSON array containing Lean Canvas section data with a title for the current date (or given date if the date parameter is passed)
|
||||
parameters:
|
||||
- in: path
|
||||
required: true
|
||||
name: projectId
|
||||
schema:
|
||||
type: integer
|
||||
- in: path
|
||||
required: true
|
||||
description: 'this number can be 1, 2,...,8. It is associated with the title of the sectionCell'
|
||||
name: sectionId
|
||||
schema:
|
||||
type: integer
|
||||
enum:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
- 8
|
||||
- in: path
|
||||
required: true
|
||||
name: date
|
||||
description: the date corresponding to the wanted version of lc section. "Nan" for the latest version
|
||||
example: NaN
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/sectionCell'
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
'/shared/projects/entrepreneurs/{projectId}':
|
||||
get:
|
||||
summary: Retourne la liste d'entrepreneurs associée à un projet donné
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description: JSON array of entrepreneur names associated with a project
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/user-entrepreneur'
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
'/shared/projects/admin/{projectId}':
|
||||
get:
|
||||
summary: Retourne les informations de l'admin qui accompagne le projet
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description: 'JSON object containing information (name, gmail, tel, etc..) the admin supervising the project with id projectID.'
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/user-admin'
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
'/shared/projects/appointments/{projectId}':
|
||||
get:
|
||||
summary: Retourne les rendez-vous du projet
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description: JSON array of upcoming and past appointment data for the project with id projectID.
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/appointement'
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
'/shared/projects/appointments/report/{appointmentId}':
|
||||
get:
|
||||
summary: Retourne le rapport pdf du rendez-vous
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description: PDF file containing the ap- pointment report
|
||||
parameters:
|
||||
- in: path
|
||||
name: apointementId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/pdf:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
/shared/appointments/request:
|
||||
post:
|
||||
summary: demander un rendez-vous
|
||||
description: will add an appointement request request by the applicant to have an appointment to be confirmed or denied by the specified participants of the appointement.
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
- MyINPulse-admin
|
||||
requestBody:
|
||||
description: \"participants\" property is an array containing userids of the participants in the appointement
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
start_time:
|
||||
type: string
|
||||
end_time:
|
||||
type: string
|
||||
place:
|
||||
type: string
|
||||
applicantId:
|
||||
type: integer
|
||||
participants:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
/entrepreneur/projects/request:
|
||||
post:
|
||||
summary: demander la création et validation d'un projet
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
description: Adds project to pending projects to then be accepted or rejected by an admin
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
founder:
|
||||
$ref: '#/components/schemas/user-entrepreneur'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
/entrepreneur/sectionCell/add:
|
||||
post:
|
||||
summary: ajouter une sections au LC
|
||||
description: Adds input data to the user's LC with a specified title.
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/sectionCell'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
/entrepreneur/sectionCell/modify:
|
||||
put:
|
||||
summary: modifier les données d'une section LC
|
||||
description: Modifies input Lean Canvas section by changing it to the information in the request body and changes the time stamp.
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/sectionCell'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
||||
'/entrepreneur/sectionCell/remove/{sectionCellId}':
|
||||
delete:
|
||||
summary: supprimer une section LC.
|
||||
description: Deletes section from Lean Canvas
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
parameters:
|
||||
- in: path
|
||||
name: sectionCellId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad request
|
||||
'401':
|
||||
description: Authorization information is missing or invalid
|
@ -1,121 +1,197 @@
|
||||
# _____ _ _ _____ ____ _____ ____ ____ _____ _ _ _____ _ _ ____
|
||||
# | ____| \ | |_ _| _ \| ____| _ \| _ \| ____| \ | | ____| | | | _ \
|
||||
# | _| | \| | | | | |_) | _| | |_) | |_) | _| | \| | _| | | | | |_) |
|
||||
# | |___| |\ | | | | _ <| |___| __/| _ <| |___| |\ | |___| |_| | _ <
|
||||
# |_____|_|_\_| |_| |_| \_\_____|_| |_| \_\_____|_| \_|_____|\___/|_| \_\
|
||||
# / \ | _ \_ _|
|
||||
# / _ \ | |_) | |
|
||||
# / ___ \| __/| |
|
||||
# /_/ \_\_| |___|
|
||||
#
|
||||
|
||||
# Entrepreneur API Endpoints
|
||||
paths:
|
||||
/entrepreneur/projects/request:
|
||||
post:
|
||||
summary: demander la création et validation d'un projet
|
||||
operationId: requestProjectCreation
|
||||
summary: Request creation and validation of a new project
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
description:
|
||||
Adds project to pending projects
|
||||
to then be accepted or rejected by
|
||||
an admin
|
||||
description: |-
|
||||
Submits a request for a new project. The project details are provided in the request body.
|
||||
The requesting entrepreneur (identified by the token) will be associated to it.
|
||||
The project is created with a 'pending' status, awaiting admin approval.
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
requestBody:
|
||||
required: true
|
||||
description: Project details for the request. `status`, `creationDate` are required by the model when being sent but is ignored by the server;
|
||||
primarily expects a valid `projectId`, `name`, `logo`.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
founder:
|
||||
$ref: "main.yaml#/components/schemas/user-entrepreneur"
|
||||
$ref: "./main.yaml#/components/schemas/project"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"200":
|
||||
description: Accepted - Project creation request received and is pending validation.
|
||||
"400":
|
||||
description: Bad request
|
||||
description: Bad Request - Invalid input (e.g., missing name).
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
|
||||
|
||||
/entrepreneur/sectionCell/add:
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/entrepreneur/sectionCells: # Base path
|
||||
post:
|
||||
summary: ajouter une sections au LC
|
||||
description:
|
||||
Adds input data to the user's LC
|
||||
with a specified title.
|
||||
operationId: addSectionCell
|
||||
summary: Add a cell to a Lean Canvas section
|
||||
description: Adds a new cell (like a sticky note) with the provided content to a specific section of the entrepreneur's project's Lean Canvas. Assumes project context is known based on user's token.
|
||||
`idSectionCell` and `modificationDate` are server-generated so they're values in the request are ignored by the server.
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
requestBody:
|
||||
required: true
|
||||
description: Section cell details. `idSectionCell` and `modificationDate` will be ignored if sent.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "main.yaml#/components/schemas/sectionCell"
|
||||
$ref: "./main.yaml#/components/schemas/sectionCell"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"200":
|
||||
description: Created - Section cell added successfully. Returns the created cell.
|
||||
"400":
|
||||
description: Bad request
|
||||
description: Bad Request - Invalid input (e.g., missing content or sectionId).
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
/entrepreneur/sectionCell/modify:
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/entrepreneur/sectionCells/{sectionCellId}:
|
||||
put:
|
||||
summary: modifier les données d'une section LC
|
||||
description:
|
||||
Modifies input Lean Canvas section by changing it to
|
||||
the information in the request body and changes the
|
||||
time stamp.
|
||||
operationId: modifySectionCell
|
||||
summary: Modify data in a Lean Canvas section cell
|
||||
description: Updates the content of an existing Lean Canvas section cell specified by `sectionCellId`. The server "updates" (it keeps a record of the previous version to keep a history of all the sectionCells and creates a new ones with the specified modifications) the `modificationDate`.
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "main.yaml#/components/schemas/sectionCell"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
|
||||
/entrepreneur/sectionCell/remove/{sectionCellId}:
|
||||
delete:
|
||||
summary: supprimer une section LC.
|
||||
description:
|
||||
Deletes section from Lean Canvas
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
parameters:
|
||||
- in: path
|
||||
name: sectionCellId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
description: The ID of the section cell to modify.
|
||||
example: 508
|
||||
requestBody:
|
||||
required: true
|
||||
description: Updated section cell details. `sectionCellId` "the path parameter" is the only id that's consideredn the `sectionCellId` id in the request body is ignored. `modificationDate` should be updated by the server.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "./main.yaml#/components/schemas/sectionCell"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad request
|
||||
"200":
|
||||
description: OK - Section cell updated successfully. Returns the updated cell.
|
||||
"404":
|
||||
description: Bad Request - Invalid input or ID mismatch.
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
delete:
|
||||
operationId: removeSectionCell
|
||||
summary: Remove a Lean Canvas section cell
|
||||
description: Deletes the Lean Canvas section cell specified by `sectionCellId`.
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
parameters:
|
||||
- in: path
|
||||
name: sectionCellId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: The ID of the section cell to remove.
|
||||
example: 509
|
||||
responses:
|
||||
"200":
|
||||
description: No Content - Section cell removed successfully.
|
||||
"400":
|
||||
description: Bad Request - Invalid ID format.
|
||||
"404":
|
||||
description: Bad Request - sectionCell not found.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
|
||||
/entrepreneur/projects:
|
||||
get:
|
||||
summary: gets the projectId of the project associated with the entrepreneur
|
||||
description: returns a list of projectIds of the projects associated with the entrepreneur
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
parameters:
|
||||
responses:
|
||||
"200":
|
||||
description: OK - Section cell updated successfully. Returns the updated cell.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "./main.yaml#/components/schemas/project"
|
||||
"404":
|
||||
description: Bad Request - Invalid input or ID mismatch.
|
||||
"401":
|
||||
description: Unauthorized or identity not found
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
|
||||
/entrepreneur/projects/project-is-active:
|
||||
get:
|
||||
summary: checks if the project associated with an entrepreneur is active
|
||||
description: returns a boolean if the project associated with an entrepreneur has an active status
|
||||
(i.e has been validated by an admin). The user should be routed to LeanCanvas. any other response code
|
||||
should be treated as false
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
parameters:
|
||||
responses:
|
||||
"200":
|
||||
description: OK - got the value successfully any other response code should be treated as false.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
"404":
|
||||
description: Bad Request - Invalid input or ID mismatch.
|
||||
"401":
|
||||
description: Unauthorized or identity not found
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/entrepreneur/projects/has-pending-request:
|
||||
get:
|
||||
summary: checks if the user has a pending projectRequest
|
||||
description: returns a boolean if the project associated with an entrepreneur has a pending status
|
||||
(i.e has not yet been validated by an admin). The user should be routed to a page telling him that he should
|
||||
wait for admin validation. any other response code should be treated as false.
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
parameters:
|
||||
responses:
|
||||
"200":
|
||||
description: OK - got the value successfully any other response code should be treated as false.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
"404":
|
||||
description: Bad Request - Invalid input or ID mismatch.
|
||||
"401":
|
||||
description: Unauthorized or identity not found
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
@ -1,17 +1,18 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: MyInpulse Backend Api
|
||||
description: this document servers as a documentation for the backend api.
|
||||
version: 0.2.0
|
||||
title: MyInpulse Backend API
|
||||
description: This serves as an OpenAPI documentation for the MyInpulse backend service, covering operations for Entrepreneurs, Admins, and shared functionalities.
|
||||
version: 0.2.1
|
||||
|
||||
tags:
|
||||
- name: Entrepreneurs API
|
||||
description: La partie de l'api dédiée aux entrepreneurs
|
||||
description: API endpoints primarily for Entrepreneur users.
|
||||
- name: Admin API
|
||||
description: La partie de l'api dédiée aux entrepreneurs
|
||||
description: API endpoints restricted to Admin users for management tasks.
|
||||
- name: Shared API
|
||||
description: La partie de l'api dédiée aux entrepreneurs et admins
|
||||
|
||||
description: API endpoints accessible by both Entrepreneurs and Admins.
|
||||
- name: Unauth API
|
||||
description: API endpoints related to user account management.
|
||||
|
||||
components:
|
||||
schemas:
|
||||
@ -27,88 +28,132 @@ components:
|
||||
$ref: "models.yaml#/project"
|
||||
report:
|
||||
$ref: "models.yaml#/report"
|
||||
appointement:
|
||||
$ref: "models.yaml#/appointement"
|
||||
|
||||
appointment:
|
||||
$ref: "models.yaml#/appointment"
|
||||
joinRequest:
|
||||
$ref: "models.yaml#/joinRequest"
|
||||
projectDecision:
|
||||
$ref: "models.yaml#/projectDecision"
|
||||
joinRequestDecision:
|
||||
$ref: "models.yaml#/joinRequestDecision"
|
||||
|
||||
securitySchemes:
|
||||
MyINPulse:
|
||||
type: oauth2
|
||||
description: OAuth2 authentication using Keycloak.
|
||||
flows:
|
||||
implicit:
|
||||
authorizationUrl: http://localhost:7080
|
||||
authorizationUrl: '{keycloakBaseUrl}/realms/{keycloakRealm}/protocol/openid-connect/auth'
|
||||
scopes:
|
||||
MyINPulse-admin: Administrateur
|
||||
MyINPulse-entrepreneur: Utilisateur
|
||||
MyINPulse-admin: Grants administrator access.
|
||||
MyINPulse-entrepreneur: Grants standard entrepreneur user access.
|
||||
|
||||
servers:
|
||||
- url: http://localhost:8081/
|
||||
description: Backend server
|
||||
|
||||
|
||||
- url: '{serverProtocol}://{serverHost}:{serverPort}'
|
||||
description: API Server
|
||||
variables:
|
||||
serverProtocol:
|
||||
enum: [http, https]
|
||||
default: http
|
||||
serverHost:
|
||||
default: localhost
|
||||
serverPort:
|
||||
enum: ['8081']
|
||||
default: '8081'
|
||||
keycloakBaseUrl:
|
||||
default: http://localhost:7080
|
||||
description: Base URL for the Keycloak server.
|
||||
keycloakRealm:
|
||||
default: MyInpulseRealm
|
||||
description: Keycloak realm name.
|
||||
|
||||
paths:
|
||||
# _ ____ __ __ ___ _ _ _ ____ ___
|
||||
# _ _ _ _ _ _
|
||||
# | | | |_ __ __ _ _ _| |_| |__ / \ _ __ (_)
|
||||
# | | | | '_ \ / _` | | | | __| '_ \ / _ \ | '_ \| |
|
||||
# | |_| | | | | (_| | |_| | |_| | | |/ ___ \| |_) | |
|
||||
# \___/|_| |_|\__,_|\__,_|\__|_| |_/_/ \_\ .__/|_|
|
||||
# |_|
|
||||
|
||||
/unauth/finalize:
|
||||
$ref: "./unauthApi.yaml#/paths/~1unauth~1finalize"
|
||||
/unauth/request-join/{projectId}:
|
||||
$ref: "./unauthApi.yaml#/paths/~1unauth~1request-join~1{projectId}"
|
||||
/unauth/request-admin-role:
|
||||
$ref: "./unauthApi.yaml#/paths/~1unauth~1request-admin-role"
|
||||
/unauth/check-if-not-pending:
|
||||
$ref: "./unauthApi.yaml#/paths/~1unauth~1check-if-not-pending"
|
||||
|
||||
# _ ____ __ __ ___ _ _ _ ____ ___
|
||||
# / \ | _ \| \/ |_ _| \ | | / \ | _ \_ _|
|
||||
# / _ \ | | | | |\/| || || \| | / _ \ | |_) | |
|
||||
# / ___ \| |_| | | | || || |\ | / ___ \| __/| |
|
||||
# / _ \ | | | | |\/| || || \| | / _ \ | |_) | |
|
||||
# / ___ \| |_| | | | || || |\ | / ___ \| __/| |
|
||||
# /_/ \_\____/|_| |_|___|_| \_| /_/ \_\_| |___|
|
||||
#
|
||||
/admin/pending-accounts:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1pending-accounts"
|
||||
/admin/accounts/validate/{userId}:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1accounts~1validate~1{userId}"
|
||||
/admin/request-join:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1request-join"
|
||||
/admin/request-join/decision/{joinRequestId}:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1request-join~1decision~1{joinRequestId}"
|
||||
/admin/projects:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1projects"
|
||||
/admin/projects/pending/decision:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1projects~1pending~1decision"
|
||||
/admin/projects/add:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1projects~1add"
|
||||
/admin/appointments/report/{appointmentId}:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1appointments~1report~1{appointmentId}"
|
||||
/admin/projects/remove/{projectId}:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1projects~1remove~1{projectId}"
|
||||
/admin/projects/pending:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1projects~1pending"
|
||||
/admin/projects/pending/decision:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1projects~1pending~1decision"
|
||||
/admin/appointments/report/{appointmentId}:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1appointments~1report~1{appointmentId}"
|
||||
/admin/appointments/upcoming:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1appointments~1upcoming"
|
||||
/admin/projects/{projectId}:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1projects~1{projectId}"
|
||||
/admin/make-admin/{userId}:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1make-admin~1{userId}"
|
||||
/admin/create-account:
|
||||
$ref: "./adminApi.yaml#/paths/~1admin~1create-account"
|
||||
|
||||
# ____ _ _ _ ____ ___
|
||||
# ____ _ _ _ ____ ___
|
||||
# / ___|| |__ __ _ _ __ ___ __| | / \ | _ \_ _|
|
||||
# \___ \| '_ \ / _` | '__/ _ \/ _` | / _ \ | |_) | |
|
||||
# ___) | | | | (_| | | | __/ (_| | / ___ \| __/| |
|
||||
# \___ \| '_ \ / _` | '__/ _ \/ _` | / _ \ | |_) | |
|
||||
# ___) | | | | (_| | | | __/ (_| | / ___ \| __/| |
|
||||
# |____/|_| |_|\__,_|_| \___|\__,_| /_/ \_\_| |___|
|
||||
#
|
||||
/shared/appointments/upcoming:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1appointments~1upcoming"
|
||||
/shared/projects/sectionCell/{projectId}/{sectionId}/{date}:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1projects~1sectionCell~1{projectId}~1{sectionId}~1{date}"
|
||||
#
|
||||
/shared/projects/sectionCells/{projectId}/{sectionId}/{date}:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1projects~1sectionCells~1{projectId}~1{sectionId}~1{date}"
|
||||
/shared/projects/entrepreneurs/{projectId}:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1projects~1entrepreneurs~1{projectId}"
|
||||
/shared/projects/admin/{projectId}:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1projects~1admin~1{projectId}"
|
||||
/shared/projects/appointments/{projectId}:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1projects~1appointments~1{projectId}"
|
||||
/shared/projects/appointments/report/{appointmentId}:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1projects~1appointments~1report~1{appointmentId}"
|
||||
|
||||
/shared/appointments/report/{appointmentId}:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1appointments~1report~1{appointmentId}"
|
||||
/shared/appointments/request:
|
||||
$ref: "./sharedApi.yaml#/paths/~1shared~1appointments~1request"
|
||||
|
||||
# _____ _ _ _____ ____ _____ ____ ____ _____ _ _ _____ _ _ ____
|
||||
# | ____| \ | |_ _| _ \| ____| _ \| _ \| ____| \ | | ____| | | | _ \
|
||||
# _____ _ _ _____ ____ _____ ____ ____ _____ _ _ _____ _ _ ____
|
||||
# | ____| \ | |_ _| _ \| ____| _ \| _ \| ____| \ | | ____| | | | _ \
|
||||
# | _| | \| | | | | |_) | _| | |_) | |_) | _| | \| | _| | | | | |_) |
|
||||
# | |___| |\ | | | | _ <| |___| __/| _ <| |___| |\ | |___| |_| | _ <
|
||||
# | |___| |\ | | | | _ <| |___| __/| _ <| |___| |\ | |___| |_| | _ <
|
||||
# |_____|_|_\_| |_| |_| \_\_____|_| |_| \_\_____|_| \_|_____|\___/|_| \_\
|
||||
# / \ | _ \_ _|
|
||||
# / _ \ | |_) | |
|
||||
# / ___ \| __/| |
|
||||
# /_/ \_\_| |___|
|
||||
# / \ | _ \_ _|
|
||||
# / _ \ | |_) | |
|
||||
# / ___ \| __/| |
|
||||
# /_/ \_\_| |___|
|
||||
#
|
||||
|
||||
/entrepreneur/projects:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1projects"
|
||||
/entrepreneur/projects/request:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1projects~1request"
|
||||
/entrepreneur/sectionCell/add:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1sectionCell~1add"
|
||||
/entrepreneur/sectionCell/modify:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1sectionCell~1modify"
|
||||
/entrepreneur/sectionCell/remove/{sectionCellId}:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1sectionCell~1remove~1{sectionCellId}"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/entrepreneur/sectionCells:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1sectionCells"
|
||||
/entrepreneur/sectionCells/{sectionCellId}:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1sectionCells~1{sectionCellId}"
|
||||
/entrepreneur/projects/project-is-active:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1projects~1project-is-active"
|
||||
/entrepreneur/projects/has-pending-request:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1projects~1has-pending-request"
|
@ -1,92 +1,210 @@
|
||||
# models.yaml
|
||||
|
||||
user:
|
||||
type: object
|
||||
properties:
|
||||
idUser:
|
||||
type: integer
|
||||
userSurname:
|
||||
type: string
|
||||
userName:
|
||||
type: string
|
||||
primaryMail:
|
||||
type: string
|
||||
example: "example@exmaple.com"
|
||||
secondaryMail:
|
||||
type: string
|
||||
example: "example@exmaple.com"
|
||||
phoneNumber:
|
||||
type: string
|
||||
example: "0612345678"
|
||||
|
||||
type: object
|
||||
properties:
|
||||
idUser:
|
||||
type: integer
|
||||
description: Unique identifier for the user.
|
||||
#readOnly: true # Typically generated by the server
|
||||
example: 101
|
||||
userSurname:
|
||||
type: string
|
||||
description: User's surname (last name).
|
||||
example: "Doe"
|
||||
userName:
|
||||
type: string
|
||||
description: User's given name (first name).
|
||||
example: "John"
|
||||
primaryMail:
|
||||
type: string
|
||||
format: email
|
||||
description: User's primary email address.
|
||||
example: "john.doe@example.com"
|
||||
secondaryMail:
|
||||
type: string
|
||||
format: email
|
||||
description: User's secondary email address (optional).
|
||||
example: "j.doe@personal.com"
|
||||
phoneNumber:
|
||||
type: string
|
||||
description: User's phone number.
|
||||
example: "+33612345678" # Example using international format
|
||||
|
||||
user-entrepreneur:
|
||||
allOf:
|
||||
- $ref: "#/user"
|
||||
- type: object
|
||||
properties:
|
||||
school:
|
||||
properties:
|
||||
school:
|
||||
type: string
|
||||
example: "enseirb"
|
||||
description: The school the entrepreneur attends/attended.
|
||||
example: "ENSEIRB-MATMECA"
|
||||
course:
|
||||
type: string
|
||||
example: "info"
|
||||
description: The specific course or program of study.
|
||||
example: "Electronics"
|
||||
sneeStatus:
|
||||
type: boolean
|
||||
example: false
|
||||
description: Indicates if the user has SNEE status (Statut National d'Étudiant-Entrepreneur).
|
||||
example: true
|
||||
example: # Added full object example
|
||||
idUser: 101
|
||||
userSurname: "Doe"
|
||||
userName: "John"
|
||||
primaryMail: "john.doe@example.com"
|
||||
secondaryMail: "j.doe@personal.com"
|
||||
phoneNumber: "+33612345678"
|
||||
school: "ENSEIRB-MATMECA"
|
||||
course: "Electronics"
|
||||
sneeStatus: true
|
||||
|
||||
user-admin:
|
||||
allOf:
|
||||
- $ref: "#/user"
|
||||
# No additional properties needed for this example
|
||||
example: # Added full object example
|
||||
idUser: 55
|
||||
userSurname: "Admin"
|
||||
userName: "Super"
|
||||
primaryMail: "admin@myinpulse.com"
|
||||
phoneNumber: "+33512345678"
|
||||
|
||||
sectionCell:
|
||||
type: object
|
||||
description: Represents a cell (like a sticky note) within a specific section of a project's Lean Canvas.
|
||||
properties:
|
||||
idSectionCell:
|
||||
type: integer
|
||||
example: this the cell (postit id)
|
||||
description: Unique identifier for the section cell.
|
||||
#readOnly: true # Generated by server
|
||||
example: 508
|
||||
sectionId:
|
||||
type: integer
|
||||
description: Identifier of the Lean Canvas section this cell belongs to (e.g., 1 for Problem, 2 for Solution).
|
||||
example: 1
|
||||
contentSectionCell:
|
||||
type: string
|
||||
description: The text content of the section cell.
|
||||
example: "Users find it hard to track project progress."
|
||||
modificationDate:
|
||||
type: string
|
||||
example: "02-05-2025"
|
||||
format: date # Using Java LocalDate -> YYYY-MM-DD
|
||||
description: The date when this cell was last modified.
|
||||
#readOnly: true # Typically updated by the server on modification
|
||||
example: "yyyy-MM-dd HH:mm"
|
||||
|
||||
project:
|
||||
type: object
|
||||
description: Represents a project being managed or developed.
|
||||
properties:
|
||||
idProject:
|
||||
type: integer
|
||||
description: Unique identifier for the project.
|
||||
#readOnly: true # Generated by server
|
||||
example: 12
|
||||
projectName:
|
||||
type: string
|
||||
description: The name of the project.
|
||||
example: "MyInpulse Mobile App"
|
||||
creationDate:
|
||||
type: string
|
||||
example: "02-05-2025"
|
||||
format: date # Using Java LocalDate -> YYYY-MM-DD
|
||||
description: The date when the project was created in the system.
|
||||
#readOnly: true # Set by server
|
||||
example: "yyyy-MM-dd HH:mm"
|
||||
logo:
|
||||
example: to be discussed not yet fixed
|
||||
type: string
|
||||
format: binary
|
||||
format: byte
|
||||
description: Base64 encoded string representing the project logo image.
|
||||
example: "/*Base64 encoded string representing the project logo image*/"
|
||||
status:
|
||||
type: string
|
||||
enum: [PENDING, ACTIVE, ENDED, ABORTED, REJECTED]
|
||||
description: Corresponds to a status enum internal to the backend, it's value in in requests
|
||||
incoming to the server should be ignored as the client shouldn't be specifying them.
|
||||
example: "NaN"
|
||||
|
||||
joinRequest:
|
||||
type: object
|
||||
description: Represents a request from an entrepreneur to join an already existing project.
|
||||
properties:
|
||||
idProject:
|
||||
type: integer
|
||||
description: the ID of the project the entrepreneur wants to join.
|
||||
example: 42
|
||||
entrepreneur:
|
||||
$ref: "#/user-entrepreneur"
|
||||
|
||||
|
||||
report:
|
||||
type: object
|
||||
description: Represents a report associated with an appointment.
|
||||
properties:
|
||||
idReport:
|
||||
type: integer
|
||||
description: Unique identifier for the report.
|
||||
#readOnly: true # Generated by server
|
||||
example: 987
|
||||
reportContent:
|
||||
type: string
|
||||
|
||||
appointement:
|
||||
description: The textual content of the report. Could be plain text or Markdown (specify if known).
|
||||
example: "Discussed roadmap milestones for Q3. Agreed on preliminary UI mockups."
|
||||
|
||||
appointment: # Corrected typo
|
||||
type: object
|
||||
description: Represents a scheduled meeting or appointment.
|
||||
properties:
|
||||
idAppointment: # Assuming there's an ID
|
||||
type: integer
|
||||
description: Unique identifier for the appointment.
|
||||
#readOnly: true
|
||||
example: 303
|
||||
appointmentDate:
|
||||
type: string
|
||||
example: "02-05-2025"
|
||||
format: date # Using Java LocalDate -> YYYY-MM-DD
|
||||
description: The date of the appointment.
|
||||
example: "2025-05-10"
|
||||
appointmentTime:
|
||||
type: string
|
||||
example: "10:15:30"
|
||||
format: time # Using Java LocalTime -> HH:mm:ss
|
||||
description: The time of the appointment (local time).
|
||||
example: "14:30:00"
|
||||
appointmentDuration:
|
||||
type: string
|
||||
description: Duration of the appointment in ISO 8601 duration format (e.g., PT1H30M for 1 hour 30 minutes).
|
||||
example: "PT1H" # Example for 1 hour
|
||||
appointmentPlace:
|
||||
type: string
|
||||
description: Location or meeting link for the appointment.
|
||||
example: "Meeting Room 3 / https://meet.example.com/abc-def-ghi"
|
||||
appointmentSubject:
|
||||
type: string
|
||||
type: string
|
||||
description: The main topic or subject of the appointment.
|
||||
example: "Q3 Roadmap Planning"
|
||||
# Consider adding project ID or user IDs if relevant association exists
|
||||
|
||||
projectDecision:
|
||||
type: object
|
||||
description: Represents a decision from an admin to accept a pending project.
|
||||
properties:
|
||||
projectId:
|
||||
type: integer
|
||||
description: The ID of the project the entrepreneur wants to join.
|
||||
example: 12
|
||||
adminId:
|
||||
type: integer
|
||||
description: The ID of the project the admin who will supervise the project in case of admission.
|
||||
example: 2
|
||||
isAccepted:
|
||||
type: boolean
|
||||
description: The boolean value of the decision.
|
||||
example: "true"
|
||||
|
||||
joinRequestDecision:
|
||||
type: object
|
||||
description: Represents a decision from an admin to accept a pending project join request.
|
||||
properties:
|
||||
isAccepted:
|
||||
type: boolean
|
||||
description: The boolean value of the decision.
|
||||
example: "true"
|
@ -1,254 +1,193 @@
|
||||
# ____ _ _ _ ____ ___
|
||||
# / ___|| |__ __ _ _ __ ___ __| | / \ | _ \_ _|
|
||||
# \___ \| '_ \ / _` | '__/ _ \/ _` | / _ \ | |_) | |
|
||||
# ___) | | | | (_| | | | __/ (_| | / ___ \| __/| |
|
||||
# |____/|_| |_|\__,_|_| \___|\__,_| /_/ \_\_| |___|
|
||||
#
|
||||
paths:
|
||||
/shared/appointments/upcoming:
|
||||
get:
|
||||
summary: Retourne la list des prochains rendez-vous de l'utilisateur
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description:
|
||||
JSON array of upcoming appointment data (name, date, time etc..) for a user.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "main.yaml#/components/schemas/appointement"
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is missing or invalid
|
||||
# Shared API Endpoints
|
||||
paths:
|
||||
|
||||
/shared/projects/sectionCell/{projectId}/{sectionId}/{date}:
|
||||
get:
|
||||
summary: Retourne la liste de sections de LC avec un titre donné
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description:
|
||||
JSON array containing Lean Canvas
|
||||
section data with a title for the
|
||||
current date (or given date if the
|
||||
date parameter is passed)
|
||||
parameters:
|
||||
- in: path
|
||||
required: true
|
||||
name: projectId
|
||||
schema:
|
||||
type: integer
|
||||
- in: path
|
||||
required: true
|
||||
description: this number can be 1, 2,...,8. It is associated with the title of the sectionCell
|
||||
name: sectionId
|
||||
schema:
|
||||
type: integer
|
||||
enum: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
- in: path
|
||||
required: true
|
||||
name: date
|
||||
description: the date corresponding to the wanted version of lc section. "Nan" for the latest version
|
||||
example: "NaN"
|
||||
schema:
|
||||
type: string
|
||||
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "main.yaml#/components/schemas/sectionCell"
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is missing or invalid
|
||||
|
||||
/shared/projects/entrepreneurs/{projectId}:
|
||||
/shared/projects/sectionCells/{projectId}/{sectionId}/{date}:
|
||||
get:
|
||||
summary: Retourne la liste d'entrepreneurs associée à un projet donné
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description:
|
||||
JSON array of entrepreneur
|
||||
names associated with a project
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "main.yaml#/components/schemas/user-entrepreneur"
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is missing or invalid
|
||||
|
||||
/shared/projects/admin/{projectId}:
|
||||
get:
|
||||
summary: Retourne les informations de l'admin qui accompagne le projet
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description:
|
||||
JSON object containing information (name, gmail, tel, etc..)
|
||||
the admin supervising the project with id projectID.
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "main.yaml#/components/schemas/user-admin"
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
|
||||
/shared/projects/appointments/{projectId}:
|
||||
get:
|
||||
summary: Retourne les rendez-vous du projet
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description:
|
||||
JSON array of upcoming and past appointment
|
||||
data for the project with id projectID.
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "main.yaml#/components/schemas/appointement"
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
/shared/projects/appointments/report/{appointmentId}:
|
||||
get:
|
||||
summary: Retourne le rapport pdf du rendez-vous
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-admin
|
||||
- MyINPulse-entrepreneur
|
||||
description:
|
||||
PDF file containing the ap-
|
||||
pointment report
|
||||
parameters:
|
||||
- in: path
|
||||
name: apointementId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/pdf:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
|
||||
/shared/appointments/request:
|
||||
post:
|
||||
summary: demander un rendez-vous
|
||||
description:
|
||||
will add an appointement request request by the applicant
|
||||
to have an appointment to be confirmed or denied by the
|
||||
specified participants of the appointement.
|
||||
operationId: getSectionCellsByDate
|
||||
summary: Get project section cells modified on a specific date
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse:
|
||||
- MyINPulse-entrepreneur
|
||||
- MyINPulse-admin
|
||||
- MyINPulse: [MyINPulse-entrepreneur, MyINPulse-admin]
|
||||
description: Retrieves section cells belonging to a specific section of a project, filtered by the last modification date. Requires user to have access to the project.
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
required: true
|
||||
schema: { type: integer }
|
||||
description: ID of the project.
|
||||
- in: path
|
||||
name: sectionId
|
||||
required: true
|
||||
schema: { type: integer }
|
||||
description: ID of the Lean Canvas section.
|
||||
- in: path
|
||||
name: date
|
||||
required: true
|
||||
schema: { type: string, format: date } # Expect YYYY-MM-DD
|
||||
description: The modification date to filter by (YYYY-MM-DD HH:mm).
|
||||
responses:
|
||||
"200":
|
||||
description: OK - List of section cells matching the criteria.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "./main.yaml#/components/schemas/sectionCell"
|
||||
"400":
|
||||
description: Bad Request - Invalid parameter format.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
|
||||
|
||||
/shared/projects/entrepreneurs/{projectId}:
|
||||
get:
|
||||
operationId: getProjectEntrepreneurs
|
||||
summary: Get entrepreneurs associated with a project
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur, MyINPulse-admin]
|
||||
description: Retrieves a list of entrepreneur users associated with the specified project. Requires access to the project.
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
required: true
|
||||
schema: { type: integer }
|
||||
description: ID of the project.
|
||||
responses:
|
||||
"200":
|
||||
description: OK - List of entrepreneurs.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "./main.yaml#/components/schemas/user-entrepreneur"
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"404":
|
||||
description: Not Found - Project not found.
|
||||
|
||||
/shared/projects/admin/{projectId}: # Path updated
|
||||
get:
|
||||
operationId: getProjectAdmin
|
||||
summary: Get admin associated with a project
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur, MyINPulse-admin]
|
||||
description: Retrieves a list of admin users associated with the specified project. Requires access to the project.
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
required: true
|
||||
schema: { type: integer }
|
||||
description: ID of the project.
|
||||
responses:
|
||||
"200":
|
||||
description: OK - admin.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "./main.yaml#/components/schemas/user-admin"
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"404":
|
||||
description: Not Found - Project not found.
|
||||
|
||||
|
||||
/shared/projects/appointments/{projectId}:
|
||||
get:
|
||||
operationId: getProjectAppointments
|
||||
summary: Get appointments related to a project
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur, MyINPulse-admin]
|
||||
description: Retrieves a list of appointments associated with the specified project. Requires access to the project.
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
required: true
|
||||
schema: { type: integer }
|
||||
description: ID of the project.
|
||||
responses:
|
||||
"200":
|
||||
description: OK - List of appointments.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "./main.yaml#/components/schemas/appointment"
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
|
||||
|
||||
/shared/appointments/report/{appointmentId}: # Path updated
|
||||
get:
|
||||
operationId: getAppointmentReport # Shared endpoint implies read-only access might be possible
|
||||
summary: Get the report for an appointment
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur, MyINPulse-admin]
|
||||
description: Retrieves the report associated with a specific appointment. Requires user to have access to the appointment/project.
|
||||
parameters:
|
||||
- in: path
|
||||
name: appointmentId
|
||||
required: true
|
||||
schema: { type: integer }
|
||||
description: ID of the appointment.
|
||||
responses:
|
||||
"200":
|
||||
description: OK - Report PDF returned.
|
||||
content:
|
||||
application/pdf:
|
||||
schema:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
|
||||
/shared/appointments/request:
|
||||
post:
|
||||
operationId: requestAppointment
|
||||
summary: Request a new appointment
|
||||
tags:
|
||||
- Shared API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur, MyINPulse-admin]
|
||||
description: Allows a user (entrepreneur or admin) to request a new appointment, potentially with another user or regarding a project. Details in the body. The request might need confirmation or create a pending appointment.
|
||||
requestBody:
|
||||
description: \"participants\" property is an array containing userids of the participants in the appointement
|
||||
required: true
|
||||
description: Details of the appointment request.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
start_time:
|
||||
type: string
|
||||
end_time:
|
||||
type: string
|
||||
place:
|
||||
type: string
|
||||
applicantId:
|
||||
type: integer
|
||||
participants:
|
||||
#/* */
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
|
||||
$ref: "./main.yaml#/components/schemas/appointment" # Assuming request uses same model structure
|
||||
# Potentially add projectId or targetUserId here
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"200": # Accepted seems appropriate for a request
|
||||
description: Accepted - Appointment request submitted.
|
||||
"400":
|
||||
description: Bad request
|
||||
description: Bad Request - Invalid appointment details.
|
||||
"401":
|
||||
description: Authorization information is
|
||||
missing or invalid
|
||||
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
90
documentation/openapi/src/unauthApi.yaml
Normal file
90
documentation/openapi/src/unauthApi.yaml
Normal file
@ -0,0 +1,90 @@
|
||||
|
||||
# _ _ _ _ _ _
|
||||
# | | | |_ __ __ _ _ _| |_| |__ / \ _ __ (_)
|
||||
# | | | | '_ \ / _` | | | | __| '_ \ / _ \ | '_ \| |
|
||||
# | |_| | | | | (_| | |_| | |_| | | |/ ___ \| |_) | |
|
||||
# \___/|_| |_|\__,_|\__,_|\__|_| |_/_/ \_\ .__/|_|
|
||||
# |_|
|
||||
|
||||
paths:
|
||||
/unauth/finalize:
|
||||
post:
|
||||
summary: Finalize account setup using authentication token
|
||||
description: |-
|
||||
Completes the user account creation/setup process in the MyInpulse system.
|
||||
This endpoint requires the user to be authenticated via Keycloak (e.g., after initial login).
|
||||
User details (name, email, etc.) are extracted from the authenticated user's token (e.g., Keycloak JWT).
|
||||
No request body is needed. The account is marked as pending admin validation upon successful finalization.
|
||||
tags:
|
||||
- Unauth API
|
||||
responses:
|
||||
"200":
|
||||
description: Created - Account finalized and pending admin validation. Returns the user profile.
|
||||
"400":
|
||||
description: Bad Request - Problem processing the token or user data derived from it.
|
||||
"401":
|
||||
description: Unauthorized - Valid authentication token required.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
/unauth/request-join/{projectId}:
|
||||
post:
|
||||
summary: Request to join an existing project
|
||||
description: Submits a request for the authenticated user (keycloack authenticated) to join the project specified by projectId. Their role is then changed to entrepreneur in server and Keycloak. This requires approval from a project admin.
|
||||
tags:
|
||||
- Unauth API
|
||||
parameters:
|
||||
- in: path
|
||||
name: projectId
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: The ID of the project to request joining.
|
||||
example: 15
|
||||
responses: # Moved responses block to correct level
|
||||
"200":
|
||||
description: Accepted - Join request submitted and pending approval.
|
||||
"400":
|
||||
description: Bad Request - Invalid project ID format
|
||||
"409":
|
||||
description: Already member/request pending.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
/unauth/request-admin-role:
|
||||
post:
|
||||
summary: Request to become an admin
|
||||
description: Submits a request for the authenticated user (keycloack authenticated) to become an admin. Their role is then changed to admin in server and Keycloak. This requires approval from a project admin.
|
||||
tags:
|
||||
- Unauth API
|
||||
responses:
|
||||
"200":
|
||||
description: Accepted - Become admin request submitted and pending approval.
|
||||
"400":
|
||||
description: Bad Request - Invalid project ID format or already member/request pending.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/unauth/check-if-not-pending:
|
||||
get:
|
||||
summary: Returns a boolean of whether the user's account is not pending
|
||||
description: Returns a boolean with value `true` if the user's account is not pending and `false` if it is.
|
||||
tags:
|
||||
- Unauth API
|
||||
responses:
|
||||
"200":
|
||||
description: Accepted - Become admin request submitted and pending approval.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
"400":
|
||||
description: Bad Request - Invalid project ID format or already member/request pending.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"404":
|
||||
description: Bad Request - User not found in database.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
@ -1947,7 +1947,6 @@
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/swagger-cli/-/swagger-cli-4.0.4.tgz",
|
||||
"integrity": "sha512-Cp8YYuLny3RJFQ4CvOBTaqmOOgYsem52dPx1xM5S4EUWFblIh2Q8atppMZvXKUr1e9xH5RwipYpmdUzdPcxWcA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-cli": "4.0.4"
|
||||
},
|
||||
|
@ -4,6 +4,7 @@ import { callApi } from "@/services/api.ts";
|
||||
import { ref } from "vue";
|
||||
|
||||
const CustomRequest = ref("");
|
||||
const USERID = ref("");
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -34,30 +35,7 @@ const CustomRequest = ref("");
|
||||
<td>Current refresh token</td>
|
||||
<td>{{ store.user.refreshToken }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Entrepreneur API call</td>
|
||||
<td>
|
||||
<button @click="callApi('random')">call</button>
|
||||
</td>
|
||||
<td>res</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Admin API call</td>
|
||||
<td>
|
||||
<button @click="callApi('random2')">call</button>
|
||||
</td>
|
||||
<td>res</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unauth API call</td>
|
||||
<td>
|
||||
<button @click="callApi('unauth/dev')">call</button>
|
||||
</td>
|
||||
<td>res</td>
|
||||
<td id="3"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<input v-model="CustomRequest" placeholder="edit me" />
|
||||
@ -66,6 +44,83 @@ const CustomRequest = ref("");
|
||||
<button @click="callApi(CustomRequest)">call</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Create an account</td>
|
||||
<td>
|
||||
<button @click="callApi('unauth/create_account')">
|
||||
call
|
||||
</button>
|
||||
</td>
|
||||
<td>res</td>
|
||||
<td id="4"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Get Pending Accounts</td>
|
||||
<td>
|
||||
<button @click="callApi('/admin/pending-accounts')">
|
||||
call
|
||||
</button>
|
||||
</td>
|
||||
<td>res</td>
|
||||
<td id="6"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>admin/validate_user_account/{id}</td>
|
||||
<td>
|
||||
<button
|
||||
@click="
|
||||
callApi('admin/validate_user_account/' + USERID)
|
||||
"
|
||||
>
|
||||
call
|
||||
</button>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input v-model="USERID" placeholder="user ID" />
|
||||
</td>
|
||||
|
||||
<td id="5"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>admin/setadmin/{uid}</td>
|
||||
<td>
|
||||
<button @click="callApi('admin/setadmin/' + USERID)">
|
||||
call
|
||||
</button>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input v-model="USERID" placeholder="user ID" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unauth API call</td>
|
||||
<td>
|
||||
<button @click="callApi('unauth/dev')">call</button>
|
||||
</td>
|
||||
<td>res</td>
|
||||
<td id="8"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unauth API call</td>
|
||||
<td>
|
||||
<button @click="callApi('unauth/dev')">call</button>
|
||||
</td>
|
||||
<td>res</td>
|
||||
<td id="9"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Unauth API call</td>
|
||||
<td>
|
||||
<button @click="callApi('unauth/dev')">call</button>
|
||||
</td>
|
||||
<td>res</td>
|
||||
<td id="10"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
2638
keycloak/realm.json
Normal file
2638
keycloak/realm.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user