52 Commits

Author SHA1 Message Date
d31bf259dd Merge branch 'main' into backend-test
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 40s
CI / build (push) Successful in 11s
Format / formatting (pull_request) Successful in 6s
2025-05-07 11:06:30 +02:00
43b40c9432 feat: just added 403 response
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 40s
CI / build (push) Successful in 10s
Format / formatting (pull_request) Successful in 5s
2025-05-07 11:04:24 +02:00
e84f69c21a fix: unused imports
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 11s
2025-05-07 11:02:08 +02:00
c76e83f2bf feat: changed endpoints
Some checks failed
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 41s
CI / build (push) Failing after 8s
2025-05-07 11:00:15 +02:00
1f0f9196c4 feat: fixed 403 errors
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 40s
CI / build (push) Successful in 11s
2025-05-07 10:45:38 +02:00
40e577ef07 Merge pull request 'backend-test' (#10) from backend-test into main
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 11s
Reviewed-on: #10
Reviewed-by: adnane <adnane.alami@bordeaux-inp.fr>
Reviewed-by: anas <anas.maillal@bordeaux-inp.fr>
Reviewed-by: omar <omar.el_alaoui_el_ismaili@bordeaux-inp.fr>
2025-05-07 10:43:30 +02:00
13845394e3 feat: added doc for endpoint make-admin
All checks were successful
Format / formatting (push) Successful in 25s
Build / build (push) Successful in 44s
CI / build (push) Successful in 13s
Format / formatting (pull_request) Successful in 6s
2025-05-04 20:15:03 +02:00
f4589c6306 fix: bug on CORS discussed before
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 46s
CI / build (push) Successful in 13s
Format / formatting (pull_request) Successful in 6s
2025-05-01 21:03:23 +02:00
6004bce4e8 Merge branch 'main' into backend-test
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 42s
CI / build (push) Successful in 11s
2025-05-01 20:53:18 +02:00
0730275e75 feat: added create-account
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 44s
CI / build (push) Successful in 11s
2025-05-01 20:51:10 +02:00
5183a088e7 fix: forgot to remove a pram in an endpoint in docs
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 45s
CI / build (push) Successful in 13s
2025-04-29 21:41:25 +02:00
b503cae235 fix: styling
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 1m33s
CI / build (push) Successful in 11s
2025-04-29 21:25:03 +02:00
fcf4e1c01d feat: added an endpoint for fething the project an entrepreneur is associated with
Some checks failed
Format / formatting (push) Failing after 6s
Build / build (push) Successful in 1m28s
CI / build (push) Successful in 11s
2025-04-29 21:22:13 +02:00
3f18304028 formatting works time in and time out, empty commit to fix
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 42s
CI / build (push) Successful in 11s
2025-04-29 19:31:28 +02:00
bbb4debcd8 fix: changed the data structure used in getAllSectionCells for processing the latest version of sectioneCells as it gave some exception (it doesn't like being iterated and modified at the same time)
Some checks failed
Format / formatting (push) Failing after 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 11s
2025-04-29 19:18:12 +02:00
6f7fc70c4c didn't use the correct function for seting ids, test fixed
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 16s
2025-04-29 18:50:25 +02:00
3d57ecb01a fix: fixed some sectionCell fetching logic (previously wasn't grouping by idReference), found out that idRefrence in sectionCell is always being incremented at inserion still looking for a fix
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 11s
2025-04-29 13:59:05 +02:00
3673aa379c formatting
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 40s
CI / build (push) Successful in 11s
2025-04-23 12:21:56 +02:00
b672b2e9f9 just changed test location in file, hope these commits don't diverge
Some checks failed
Format / formatting (push) Failing after 6s
Build / build (push) Successful in 42s
CI / build (push) Successful in 11s
2025-04-23 12:11:57 +02:00
193876e51c I forgot to push the package-lock.json probably gonna need it since half the stuff used for swagger-ui is old unfortunately 2025-04-23 12:11:57 +02:00
b8c7c6f587 feat: spotted some responses on post requests I forgot to remove 2025-04-23 12:11:57 +02:00
bee47473d5 feat: finsihed tests for EntrepreneurApiService
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 40s
CI / build (push) Successful in 13s
2025-04-23 11:54:18 +02:00
e7739af80b feat: more tests
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 11s
2025-04-23 11:52:08 +02:00
32557f8f87 forgot to format
Some checks failed
Format / formatting (push) Successful in 6s
Build / build (push) Failing after 39s
CI / build (push) Successful in 11s
2025-04-23 11:50:48 +02:00
8ee06b93a6 fix: added null check in sharedService and updated test
Some checks failed
Format / formatting (push) Failing after 5s
Build / build (push) Failing after 39s
CI / build (push) Successful in 11s
2025-04-23 11:47:41 +02:00
6861d07dfc tests ?
Some checks failed
Format / formatting (push) Successful in 6s
Build / build (push) Failing after 39s
CI / build (push) Successful in 14s
2025-04-23 10:48:40 +02:00
8403bc0592 fixing formatting: sure is fun
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 40s
CI / build (push) Successful in 10s
2025-04-22 09:51:31 +02:00
5edcf9ffc8 fix: fixed formatting to be compatible with workflow
Some checks failed
Format / formatting (push) Failing after 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 11s
2025-04-22 09:46:07 +02:00
5615b0fb11 fix: update doc to encompose all response codes hopefully
Some checks failed
Format / formatting (push) Failing after 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 10s
2025-04-22 00:21:08 +02:00
8a13993d8a fix: made endpoints match documentation naming conventions 'just the mapping' and noted endpoints not yet implemented in documentation/openapi/notes.md
Some checks failed
Format / formatting (push) Failing after 6s
Build / build (push) Successful in 40s
CI / build (push) Successful in 11s
2025-04-21 23:55:14 +02:00
561f6d16b3 tests: implemented some tests, overall percentage of coverage is 40%, still trying to find a way arround class comparaison
Some checks failed
Format / formatting (push) Failing after 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 11s
2025-04-21 23:17:32 +02:00
832539f43b feat: added doc for upcoming endpoints to finish up entrepreneur join, response codes remaining to update
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 39s
CI / build (push) Successful in 10s
2025-04-21 10:54:50 +02:00
dfea20b9c4 fix: aadded changes, doc is ssomewhat coherent still need to change some endpoint names in controller and some minor changes
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 38s
CI / build (push) Successful in 10s
2025-04-16 12:31:00 +02:00
f96872fb6b fix: not red anymore
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 38s
CI / build (push) Successful in 11s
2025-04-16 11:55:54 +02:00
0140672812 why is cache enabled again ??
Some checks failed
Format / formatting (push) Successful in 5s
Build / build (push) Failing after 38s
CI / build (push) Successful in 11s
2025-04-16 11:29:25 +02:00
7df2c768c8 fix : tests
Some checks failed
CI / build (push) Waiting to run
Format / formatting (push) Successful in 5s
Build / build (push) Has been cancelled
2025-04-16 11:26:25 +02:00
6029457735 fix: more tests working, still need fixes
Some checks failed
Format / formatting (push) Failing after 4s
Build / build (push) Failing after 5m8s
CI / build (push) Successful in 10s
2025-04-16 10:36:59 +02:00
55112c8508 test: added initial test file mainly definitions and descritions of tests haven't finshed
Some checks failed
Format / formatting (push) Failing after 6s
Build / build (push) Failing after 5m6s
CI / build (push) Successful in 11s
2025-04-16 10:15:13 +02:00
676f1204cb feat: updated doc to reflect details of server, still not done editing it
Some checks failed
CI / build (push) Waiting to run
Format / formatting (push) Successful in 7s
Build / build (push) Has been cancelled
2025-04-16 10:12:16 +02:00
66be0baca6 feat: created a better account creation flow
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 5m20s
CI / build (push) Successful in 11s
2025-04-09 17:39:43 +02:00
7e1271cfe2 Merge pull request 'fix: reverted previous commit, cache juste does not work' (#8) from fix_cache into main
All checks were successful
Format / formatting (push) Successful in 5s
Build / build (push) Successful in 44s
CI / build (push) Successful in 11s
Reviewed-on: #8
2025-04-06 20:56:39 +02:00
801ecb3817 Merge branch 'main' into fix_cache
All checks were successful
Format / formatting (push) Successful in 5s
Build / build (push) Successful in 46s
CI / build (push) Successful in 11s
Format / formatting (pull_request) Successful in 6s
2025-04-06 20:56:22 +02:00
cc89d4c79f fix: reverted previous commit, cache juste does not work
Some checks are pending
Format / formatting (push) Waiting to run
Build / build (push) Waiting to run
CI / build (push) Waiting to run
Format / formatting (pull_request) Successful in 6s
2025-04-06 20:55:35 +02:00
adf9a93e2e Merge pull request 'feat: enabled graddle cache. Subsequent actions should be fasters' (#7) from fix_cache into main
Some checks failed
CI / build (push) Waiting to run
Format / formatting (push) Successful in 5s
Build / build (push) Has been cancelled
Reviewed-on: #7
2025-04-06 20:41:13 +02:00
37d8bcc719 feat: enabled graddle cache. Subsequent actions should be fasters
Some checks failed
Format / formatting (push) Successful in 5s
Build / build (push) Has been cancelled
CI / build (push) Successful in 12s
Format / formatting (pull_request) Successful in 6s
2025-04-06 20:39:45 +02:00
385c5cd8d0 fix: added back the cache since the action ran once on the main branch
All checks were successful
Format / formatting (push) Successful in 5s
Build / build (push) Successful in 5m16s
CI / build (push) Successful in 12s
2025-04-06 20:32:45 +02:00
b672dd200c fix: name coherence + test logic
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 43s
CI / build (push) Successful in 13s
2025-04-06 20:30:29 +02:00
9e1f568ea4 fix: comparaison between two projects instead of their IDs
Some checks failed
Format / formatting (push) Successful in 6s
Build / build (push) Failing after 38s
CI / build (push) Successful in 14s
2025-04-06 20:14:43 +02:00
aaa6e46d0c fix (kinda) : refactored update of data, still trying to fix bug
Some checks failed
Format / formatting (push) Successful in 6s
Build / build (push) Failing after 39s
CI / build (push) Successful in 11s
from EntrepreneurApiServiceTests (code is a bit messy with prints and comments dw)
2025-04-06 19:22:18 +02:00
9b9cfbdb2e merged openapi with backend-test
Some checks failed
Format / formatting (push) Successful in 6s
Build / build (push) Failing after 37s
CI / build (push) Successful in 13s
2025-04-02 11:17:28 +02:00
5b6b647697 feat: started test for EntrepreneurServiceApi
Some checks failed
Format / formatting (push) Successful in 5s
Build / build (push) Failing after 37s
CI / build (push) Successful in 11s
2025-04-02 10:25:50 +02:00
ead11215ba Merge pull request 'backend-api' (#6) from backend-api into main
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 38s
CI / build (push) Successful in 10s
Reviewed-on: #6
Reviewed-by: Theo <tlelez@enseirb-matmeca.fr>
Reviewed-by: adnane <adnane.alami@bordeaux-inp.fr>
Reviewed-by: mohamed_maoulainine <mohamed_maoulainine.maoulainine@bordeaux-inp.fr>
2025-03-26 19:04:08 +01:00
44 changed files with 6249 additions and 240 deletions

View File

@ -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

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
.env
.idea
keycloak/CAS/target
keycloak/.installed
docker-compose.yaml
node_modules
.vscode

View File

@ -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

View File

@ -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(

View File

@ -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);
}
}

View File

@ -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,7 +90,7 @@ 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"));

View File

@ -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"));

View File

@ -0,0 +1,51 @@
package enseirb.myinpulse.controller;
import enseirb.myinpulse.model.Entrepreneur;
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.*;
@SpringBootApplication
@RestController
public class UnauthApi {
private final EntrepreneurApiService entrepreneurApiService;
@Autowired
UnauthApi(EntrepreneurApiService entrepreneurApiService) {
this.entrepreneurApiService = entrepreneurApiService;
}
@GetMapping("/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);
}
}

View File

@ -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() {

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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(); */

View File

@ -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);
}
}

View File

@ -2,10 +2,10 @@ package enseirb.myinpulse.service;
import static enseirb.myinpulse.model.ProjectDecisionValue.PENDING;
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.service.database.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -14,6 +14,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 +26,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 +74,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 +121,113 @@ 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;
}
}

View File

@ -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();
}
/**

View File

@ -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,17 @@ 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.List;
import java.util.Map;
@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 +51,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 +80,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)) {
@ -247,6 +302,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);
}
}
}

View File

@ -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,18 +46,29 @@ 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;
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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);
}

View File

@ -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());
}
}

View File

@ -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,9 @@ import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Service
@ -50,22 +53,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());
}
@ -90,4 +134,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();
}
}

View File

@ -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);
}
}

View File

@ -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}

View File

@ -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()));
}
}

View File

@ -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());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -48,4 +48,4 @@ services:
# container_name: MyINPulse-back
# ports:
# - "8081:8080"
#

View File

@ -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/

View File

@ -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"

View File

@ -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"

View File

@ -22,6 +22,8 @@ paths:
description: Bad Request - Invalid project data provided (e.g., missing required fields).
"401":
description: Unauthorized - Authentication required or invalid token.
"403":
description: Bad Token - Invalid Keycloack configuration.
post:
operationId: addProjectManually
@ -39,7 +41,7 @@ paths:
schema:
$ref: "./main.yaml#/components/schemas/project"
responses:
"201": # Use 201 Created for successful creation
"200": # Use 200 Created for successful creation
description: Created - Project added successfully. Returns the created project.
content:
application/json:
@ -49,6 +51,8 @@ paths:
description: Bad Request - Project already exists.
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/admin/projects/pending:
@ -70,7 +74,9 @@ paths:
items:
$ref: "./main.yaml#/components/schemas/project" # Assuming pending projects use the same schema
"401":
description: Unauthorized.
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/admin/request-join:
get:
@ -92,6 +98,8 @@ paths:
$ref: "./main.yaml#/components/schemas/joinRequest"
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/admin/request-join/decision/{joinRequestId}:
post:
@ -121,7 +129,9 @@ paths:
"400":
description: Bad Request - Invalid input (e.g., missing decision).
"401":
description: Unauthorized.
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/admin/projects/pending/decision:
@ -136,14 +146,6 @@ paths:
If rejected (isAccepted=false), the pending project data might be archived or deleted based on business logic.
security:
- MyINPulse: [MyINPulse-admin]
parameters:
- in: path
name: pendingProjectId # Corrected typo and name change
required: true
schema:
type: integer
description: The ID of the pending project to decide upon.
example: 7
requestBody:
required: true
description: Decision payload.
@ -152,12 +154,14 @@ paths:
schema:
$ref: './main.yaml#/components/schemas/projectDecision'
responses:
"204": # Use 204 No Content for successful action with no body
"200": # Use 200 No Content for successful action with no body
description: No Content - Decision processed successfully.
"400":
description: Bad Request - Invalid input (e.g., missing decision).
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/admin/pending-accounts: # Path updated
@ -180,6 +184,8 @@ paths:
$ref: "./main.yaml#/components/schemas/user-entrepreneur"
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/admin/accounts/validate/{userId}:
post: # Changed to POST as it changes state
@ -199,11 +205,12 @@ paths:
description: The ID of the user account to validate.
example: 102
responses:
"204":
"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.
@ -225,6 +232,8 @@ paths:
type: array
items:
$ref: "./main.yaml#/components/schemas/appointment"
"403":
description: Bad Token - Invalid Keycloack configuration.
"404":
description: no appointments found.
"401":
@ -255,13 +264,15 @@ paths:
schema:
$ref: "./main.yaml#/components/schemas/report"
responses:
"201":
"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 - Invalid input (e.g., missing content, invalid appointment ID format).
"403":
description: Bad Token - Invalid Keycloack configuration.
"401":
description: Unauthorized.
@ -296,6 +307,8 @@ paths:
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.
@ -318,10 +331,12 @@ paths:
description: The ID of the project to remove.
example: 12
responses:
"204":
"200":
description: No Content - Project removed successfully.
"400":
description: Bad Request - Invalid project ID format.
"403":
description: Bad Token - Invalid Keycloack configuration.
"401":
description: Unauthorized.
@ -345,9 +360,28 @@ paths:
description: The ID of the user to grant admin rights.
example: 103
responses:
"204": # Use 204 No Content
"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.
description: Bad Request - Invalid user ID format or user is already an admin.
"403":
description: Bad Token - Invalid Keycloack configuration.
"401":
description: Unauthorized.
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.

File diff suppressed because it is too large Load Diff

View File

@ -21,12 +21,14 @@ paths:
schema:
$ref: "./main.yaml#/components/schemas/project"
responses:
"202":
"200":
description: Accepted - Project creation request received and is pending validation.
"400":
description: Bad Request - Invalid input (e.g., missing name).
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/entrepreneur/sectionCells: # Base path
post:
@ -46,12 +48,14 @@ paths:
schema:
$ref: "./main.yaml#/components/schemas/sectionCell"
responses:
"201":
"200":
description: Created - Section cell added successfully. Returns the created cell.
"400":
description: Bad Request - Invalid input (e.g., missing content or sectionId).
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/entrepreneur/sectionCells/{sectionCellId}:
put:
@ -84,6 +88,8 @@ paths:
description: Bad Request - Invalid input or ID mismatch.
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
delete:
operationId: removeSectionCell
@ -102,11 +108,39 @@ paths:
description: The ID of the section cell to remove.
example: 509
responses:
"204":
"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.
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.

View File

@ -108,6 +108,8 @@ paths:
$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"
# ____ _ _ _ ____ ___
# / ___|| |__ __ _ _ __ ___ __| | / \ | _ \_ _|
@ -138,6 +140,9 @@ paths:
# / ___ \| __/| |
# /_/ \_\_| |___|
#
/entrepreneur/projects:
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1projects"
/entrepreneur/projects/request:
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1projects~1request"
/entrepreneur/sectionCells:

View File

@ -36,7 +36,9 @@ paths:
items:
$ref: "./main.yaml#/components/schemas/sectionCell"
"400":
description: Bad Request - Invalid parameter format.
description: Bad Request - Invalid parameter format.
"403":
description: Bad Token - Invalid Keycloack configuration.
"401":
description: Unauthorized.
@ -68,7 +70,7 @@ paths:
"401":
description: Unauthorized.
"403":
description: Forbidden - User does not have access to this project.
description: Forbidden - User does not have access to this project or invalid Keycloack configuration.
"404":
description: Not Found - Project not found.
@ -97,7 +99,7 @@ paths:
"401":
description: Unauthorized.
"403":
description: Forbidden - User does not have access to this project.
description: Forbidden - User does not have access to this project or invalid Keycloack configuration.
"404":
description: Not Found - Project not found.
@ -126,6 +128,8 @@ paths:
type: array
items:
$ref: "./main.yaml#/components/schemas/appointment"
"403":
description: Bad Token - Invalid Keycloack configuration.
"401":
description: Unauthorized.
@ -156,6 +160,8 @@ paths:
format: binary
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/shared/appointments/request:
@ -174,24 +180,14 @@ paths:
application/json:
schema:
$ref: "./main.yaml#/components/schemas/appointment" # Assuming request uses same model structure
example:
value:
appointmentDate: "2025-06-01"
appointmentTime: "10:00:00"
appointmentDuration: "PT1H"
appointmentPlace: "Online"
appointmentSubject: "Follow-up on prototype"
# Potentially add projectId or targetUserId here
responses:
"202": # Accepted seems appropriate for a request
"200": # Accepted seems appropriate for a request
description: Accepted - Appointment request submitted.
content:
application/json: # Optionally return the pending appointment data
schema:
$ref: "./main.yaml#/components/schemas/appointment"
"400":
description: Bad Request - Invalid appointment details.
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.

View File

@ -18,12 +18,14 @@ paths:
tags:
- Unauth API
responses:
"201":
"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
@ -39,7 +41,7 @@ paths:
description: The ID of the project to request joining.
example: 15
responses: # Moved responses block to correct level
"202":
"200":
description: Accepted - Join request submitted and pending approval.
"400":
description: Bad Request - Invalid project ID format
@ -47,6 +49,8 @@ paths:
description: Already member/request pending.
"401":
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.
/unauth/request-admin-role:
post:
summary: Request to join an existing project
@ -54,9 +58,11 @@ paths:
tags:
- Unauth API
responses:
"202":
"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.
description: Unauthorized.
"403":
description: Bad Token - Invalid Keycloack configuration.

View File

@ -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"
},

View File

@ -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

File diff suppressed because it is too large Load Diff