Compare commits
26 Commits
695ec5d9b8
...
main
Author | SHA1 | Date | |
---|---|---|---|
a35a423447 | |||
47be7d340b | |||
232d10b164 | |||
bc7ce888ad | |||
ed67a3734a | |||
95eb154556 | |||
19fef63b0e | |||
1fd95265ea | |||
3ef2d8a198 | |||
6b49bbbe57 | |||
4c15cab607 | |||
abfe92bc87 | |||
85b4fe6a4c | |||
f2448a029f | |||
cef4daef15 | |||
f5aba70017 | |||
27adc81ddc | |||
48f14e8a04 | |||
d4533ea725 | |||
7fc06035c7 | |||
1b559f29b7 | |||
63327bc312 | |||
f0cef41e2b | |||
7f16cdc86f | |||
72d6f49995 | |||
d9aaa225aa |
5
Makefile
5
Makefile
@ -23,7 +23,7 @@ keycloak: ./keycloak/.installed
|
||||
|
||||
keycloak/.installed:
|
||||
@echo "running one time install"
|
||||
@cd keycloak/CAS && sh build.sh
|
||||
@cd keycloak/CAS && sudo sh build.sh
|
||||
@touch ./keycloak/.installed
|
||||
|
||||
dev-front: clean vite keycloak
|
||||
@ -33,8 +33,6 @@ dev-front: clean vite keycloak
|
||||
@cp config/frontdev.docker-compose.yaml docker-compose.yaml
|
||||
@docker compose up -d --build
|
||||
@cd ./front/MyINPulse-front/ && npm run dev
|
||||
@echo "cd MyINPulse-back" && echo 'export $$(cat .env | xargs)'
|
||||
@echo "./gradlew bootRun --args='--server.port=8081'"
|
||||
|
||||
prod: clean keycloak
|
||||
@cp config/prod.env front/MyINPulse-front/.env
|
||||
@ -42,7 +40,6 @@ prod: clean keycloak
|
||||
@cp config/prod.env .env
|
||||
@cp config/prod.docker-compose.yaml docker-compose.yaml
|
||||
@docker compose up -d --build
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -95,4 +95,22 @@ public class EntrepreneurApi {
|
||||
@RequestBody Project project, @AuthenticationPrincipal Jwt principal) {
|
||||
entrepreneurApiService.requestNewProject(project, principal.getClaimAsString("email"));
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Endpoint to check if project is has already been validated by an admin
|
||||
*/
|
||||
@GetMapping("/entrepreneur/projects/project-is-active")
|
||||
public Boolean checkIfProjectValidated(@AuthenticationPrincipal Jwt principal) {
|
||||
return entrepreneurApiService.checkIfEntrepreneurProjectActive(
|
||||
principal.getClaimAsString("email"));
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Endpoint to check if a user requested a project (used when project is pending)
|
||||
*/
|
||||
@GetMapping("/entrepreneur/projects/has-pending-request")
|
||||
public Boolean checkIfHasRequested(@AuthenticationPrincipal Jwt principal) {
|
||||
return entrepreneurApiService.entrepreneurHasPendingRequestedProject(
|
||||
principal.getClaimAsString("email"));
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
package enseirb.myinpulse.controller;
|
||||
|
||||
import enseirb.myinpulse.model.Administrator;
|
||||
import enseirb.myinpulse.model.Entrepreneur;
|
||||
import enseirb.myinpulse.service.AdminApiService;
|
||||
import enseirb.myinpulse.service.EntrepreneurApiService;
|
||||
import enseirb.myinpulse.service.UtilsService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@ -16,15 +15,15 @@ import org.springframework.web.bind.annotation.*;
|
||||
public class UnauthApi {
|
||||
|
||||
private final EntrepreneurApiService entrepreneurApiService;
|
||||
private final AdminApiService adminApiService;
|
||||
private final UtilsService utilsService;
|
||||
|
||||
@Autowired
|
||||
UnauthApi(EntrepreneurApiService entrepreneurApiService, AdminApiService administratorService) {
|
||||
UnauthApi(EntrepreneurApiService entrepreneurApiService, UtilsService utilsService) {
|
||||
this.entrepreneurApiService = entrepreneurApiService;
|
||||
this.adminApiService = administratorService;
|
||||
this.utilsService = utilsService;
|
||||
}
|
||||
|
||||
@GetMapping("/unauth/finalize")
|
||||
@PostMapping("/unauth/finalize")
|
||||
public void createAccount(@AuthenticationPrincipal Jwt principal) {
|
||||
boolean sneeStatus;
|
||||
if (principal.getClaimAsString("sneeStatus") != null) {
|
||||
@ -50,21 +49,13 @@ public class UnauthApi {
|
||||
course,
|
||||
sneeStatus,
|
||||
true);
|
||||
|
||||
entrepreneurApiService.createAccount(e);
|
||||
}
|
||||
|
||||
/*
|
||||
* These bottom endpoints are meant for testing only
|
||||
* and should not py merged to main
|
||||
*
|
||||
*/
|
||||
@GetMapping("/unauth/getAllAdmins")
|
||||
public Iterable<Administrator> getEveryAdmin() {
|
||||
return this.adminApiService.getAllAdmins();
|
||||
}
|
||||
|
||||
@GetMapping("/unauth/getAllEntrepreneurs")
|
||||
public Iterable<Entrepreneur> getEveryEntrepreneur() {
|
||||
return this.entrepreneurApiService.getAllEntrepreneurs();
|
||||
@GetMapping("/unauth/check-if-not-pending")
|
||||
public Boolean checkAccountStatus(@AuthenticationPrincipal Jwt principal) {
|
||||
// Throws 404 if user not found
|
||||
return utilsService.checkEntrepreneurNotPending(principal.getClaimAsString("email"));
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
package enseirb.myinpulse.service;
|
||||
|
||||
import static enseirb.myinpulse.model.ProjectDecisionValue.PENDING;
|
||||
import static enseirb.myinpulse.model.ProjectDecisionValue.ACTIVE;
|
||||
|
||||
import enseirb.myinpulse.model.Entrepreneur;
|
||||
import enseirb.myinpulse.model.Project;
|
||||
import enseirb.myinpulse.model.SectionCell;
|
||||
import enseirb.myinpulse.model.User;
|
||||
import enseirb.myinpulse.service.database.*;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -234,4 +236,49 @@ public class EntrepreneurApiService {
|
||||
public Iterable<Entrepreneur> getAllEntrepreneurs() {
|
||||
return entrepreneurService.getAllEntrepreneurs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an entrepreneur with the given email has a project that is ACTIVE.
|
||||
*
|
||||
* @param email The email of the entrepreneur.
|
||||
* @return true if the entrepreneur has an active project, false otherwise.
|
||||
*/
|
||||
public Boolean checkIfEntrepreneurProjectActive(String email) {
|
||||
User user = this.userService.getUserByEmail(email);
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
Long userId = user.getIdUser();
|
||||
|
||||
Entrepreneur entrepreneur = this.entrepreneurService.getEntrepreneurById(userId);
|
||||
if (entrepreneur == null) {
|
||||
return false;
|
||||
}
|
||||
Project proposedProject = entrepreneur.getProjectProposed();
|
||||
return proposedProject != null && proposedProject.getProjectStatus() == ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an entrepreneur with the given email has proposed a project.
|
||||
*
|
||||
* @param email The email of the entrepreneur.
|
||||
* @return true if the entrepreneur has a proposed project, false otherwise.
|
||||
*/
|
||||
public Boolean entrepreneurHasPendingRequestedProject(String email) {
|
||||
User user = this.userService.getUserByEmail(email);
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
Long userId = user.getIdUser();
|
||||
|
||||
Entrepreneur entrepreneur = this.entrepreneurService.getEntrepreneurById(userId);
|
||||
if (entrepreneur == null) {
|
||||
return false;
|
||||
}
|
||||
Project proposedProject = entrepreneur.getProjectProposed();
|
||||
if (entrepreneur.getProjectProposed() == null) {
|
||||
return false;
|
||||
}
|
||||
return proposedProject.getProjectStatus() == PENDING;
|
||||
}
|
||||
}
|
||||
|
@ -72,4 +72,10 @@ public class UtilsService {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean checkEntrepreneurNotPending(String email) {
|
||||
// Throws 404 if user not found
|
||||
User user = userService.getUserByEmail(email);
|
||||
return !user.isPending();
|
||||
}
|
||||
}
|
||||
|
@ -34,19 +34,19 @@ services:
|
||||
depends_on:
|
||||
- postgres
|
||||
|
||||
front:
|
||||
build:
|
||||
context: ./front/
|
||||
dockerfile: Dockerfile
|
||||
container_name: MyINPulse-front
|
||||
ports:
|
||||
- "8080:80"
|
||||
|
||||
#back:
|
||||
#front:
|
||||
# build:
|
||||
# context: ./MyINPulse-back/
|
||||
# context: ./front/
|
||||
# dockerfile: Dockerfile
|
||||
# container_name: MyINPulse-back
|
||||
# container_name: MyINPulse-front
|
||||
# ports:
|
||||
# - "8081:8080"
|
||||
# - "8080:80"
|
||||
|
||||
back:
|
||||
build:
|
||||
context: ./MyINPulse-back/
|
||||
dockerfile: Dockerfile
|
||||
container_name: MyINPulse-back
|
||||
ports:
|
||||
- "8081:8080"
|
||||
|
@ -16,7 +16,7 @@ BACKEND_PASSWORD=backend_db_user_password
|
||||
DATABASE_URL=MyINPulse-DB
|
||||
|
||||
VITE_KEYCLOAK_URL=http://localhost:7080
|
||||
VITE_KEYCLOAK_CLIENT_ID=myinpulse
|
||||
VITE_KEYCLOAK_REALM=MyINPulse
|
||||
VITE_KEYCLOAK_CLIENT_ID=myinpulse-dev
|
||||
VITE_KEYCLOAK_REALM=test
|
||||
VITE_APP_URL=http://localhost:5173
|
||||
VITE_BACKEND_URL=http://localhost:8081/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -142,5 +142,56 @@ paths:
|
||||
description: Bad Request - Invalid input or ID mismatch.
|
||||
"401":
|
||||
description: Unauthorized or identity not found
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
|
||||
/entrepreneur/projects/project-is-active:
|
||||
get:
|
||||
summary: checks if the project associated with an entrepreneur is active
|
||||
description: returns a boolean if the project associated with an entrepreneur has an active status
|
||||
(i.e has been validated by an admin). The user should be routed to LeanCanvas. any other response code
|
||||
should be treated as false
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
parameters:
|
||||
responses:
|
||||
"200":
|
||||
description: OK - got the value successfully any other response code should be treated as false.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
"404":
|
||||
description: Bad Request - Invalid input or ID mismatch.
|
||||
"401":
|
||||
description: Unauthorized or identity not found
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/entrepreneur/projects/has-pending-request:
|
||||
get:
|
||||
summary: checks if the user has a pending projectRequest
|
||||
description: returns a boolean if the project associated with an entrepreneur has a pending status
|
||||
(i.e has not yet been validated by an admin). The user should be routed to a page telling him that he should
|
||||
wait for admin validation. any other response code should be treated as false.
|
||||
tags:
|
||||
- Entrepreneurs API
|
||||
security:
|
||||
- MyINPulse: [MyINPulse-entrepreneur]
|
||||
parameters:
|
||||
responses:
|
||||
"200":
|
||||
description: OK - got the value successfully any other response code should be treated as false.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
"404":
|
||||
description: Bad Request - Invalid input or ID mismatch.
|
||||
"401":
|
||||
description: Unauthorized or identity not found
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
@ -79,6 +79,10 @@ paths:
|
||||
$ref: "./unauthApi.yaml#/paths/~1unauth~1finalize"
|
||||
/unauth/request-join/{projectId}:
|
||||
$ref: "./unauthApi.yaml#/paths/~1unauth~1request-join~1{projectId}"
|
||||
/unauth/request-admin-role:
|
||||
$ref: "./unauthApi.yaml#/paths/~1unauth~1request-admin-role"
|
||||
/unauth/check-if-not-pending:
|
||||
$ref: "./unauthApi.yaml#/paths/~1unauth~1check-if-not-pending"
|
||||
|
||||
# _ ____ __ __ ___ _ _ _ ____ ___
|
||||
# / \ | _ \| \/ |_ _| \ | | / \ | _ \_ _|
|
||||
@ -148,4 +152,8 @@ paths:
|
||||
/entrepreneur/sectionCells:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1sectionCells"
|
||||
/entrepreneur/sectionCells/{sectionCellId}:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1sectionCells~1{sectionCellId}"
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1sectionCells~1{sectionCellId}"
|
||||
/entrepreneur/projects/project-is-active:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1projects~1project-is-active"
|
||||
/entrepreneur/projects/has-pending-request:
|
||||
$ref: "./entrepreneurApi.yaml#/paths/~1entrepreneur~1projects~1has-pending-request"
|
@ -53,7 +53,7 @@ paths:
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
/unauth/request-admin-role:
|
||||
post:
|
||||
summary: Request to join an existing project
|
||||
summary: Request to become an admin
|
||||
description: Submits a request for the authenticated user (keycloack authenticated) to become an admin. Their role is then changed to admin in server and Keycloak. This requires approval from a project admin.
|
||||
tags:
|
||||
- Unauth API
|
||||
@ -65,4 +65,26 @@ paths:
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
||||
/unauth/check-if-not-pending:
|
||||
get:
|
||||
summary: Returns a boolean of whether the user's account is not pending
|
||||
description: Returns a boolean with value `true` if the user's account is not pending and `false` if it is.
|
||||
tags:
|
||||
- Unauth API
|
||||
responses:
|
||||
"200":
|
||||
description: Accepted - Become admin request submitted and pending approval.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
"400":
|
||||
description: Bad Request - Invalid project ID format or already member/request pending.
|
||||
"401":
|
||||
description: Unauthorized.
|
||||
"404":
|
||||
description: Bad Request - User not found in database.
|
||||
"403":
|
||||
description: Bad Token - Invalid Keycloack configuration.
|
||||
|
@ -1,9 +1,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { jwtDecode } from "jwt-decode"; // i hope this doesn't break the code later
|
||||
import { store } from "../main.ts";
|
||||
import { callApi } from "@/services/api.ts";
|
||||
import { checkPending } from "@/services/Apis/Unauth";
|
||||
import Header from "@/components/HeaderComponent.vue";
|
||||
const router = useRouter();
|
||||
|
||||
@ -13,7 +13,7 @@ type TokenPayload = {
|
||||
};
|
||||
};
|
||||
|
||||
const customRequest = ref("");
|
||||
//const customRequest = ref("");
|
||||
|
||||
onMounted(() => {
|
||||
if (store.authenticated && store.user.token) {
|
||||
@ -23,23 +23,44 @@ onMounted(() => {
|
||||
|
||||
if (roles.includes("MyINPulse-admin")) {
|
||||
router.push("/admin");
|
||||
} else if (roles.includes("MyINPulse-entrepreneur")) {
|
||||
router.push("/canvas");
|
||||
return;
|
||||
}
|
||||
|
||||
if (roles.includes("MyINPulse-entrepreneur")) {
|
||||
router.push("/canvas");
|
||||
return;
|
||||
}
|
||||
|
||||
checkPending(
|
||||
(response) => {
|
||||
const isValidated = response.data === true;
|
||||
if (
|
||||
isValidated &&
|
||||
roles.includes("MyINPulse-entrepreneur")
|
||||
) {
|
||||
router.push("/canvas");
|
||||
//router.push("/JorCproject");
|
||||
} else {
|
||||
router.push("/JorCproject");
|
||||
//router.push("/finalize");
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
if (error.response?.status === 403) {
|
||||
router.push("/finalize");
|
||||
} else {
|
||||
console.error(
|
||||
"Unexpected error during checkPending",
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("Failed to decode token", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
/*
|
||||
const loading = ref(false);
|
||||
|
||||
const callApiWithLoading = async (path: string) => {
|
||||
loading.value = true;
|
||||
await callApi(path);
|
||||
loading.value = false;
|
||||
};
|
||||
*/
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -47,7 +68,7 @@ const callApiWithLoading = async (path: string) => {
|
||||
<error-wrapper></error-wrapper>
|
||||
<div class="auth-container">
|
||||
<div class="auth-card">
|
||||
<h1>Bienvenue</h1>
|
||||
<h1>Bienvenue à MyINPulse</h1>
|
||||
|
||||
<div
|
||||
class="status"
|
||||
@ -65,11 +86,12 @@ const callApiWithLoading = async (path: string) => {
|
||||
<div class="actions">
|
||||
<button @click="store.login">Login</button>
|
||||
<button @click="store.logout">Logout</button>
|
||||
<button @click="store.signup">Signup-admin</button>
|
||||
<!--<button @click="store.signup">Signup-admin</button>
|
||||
<button @click="store.signup">Signup-Entrepreneur</button>
|
||||
<button @click="store.refreshUserToken">Refresh Token</button>
|
||||
<button @click="store.refreshUserToken">Refresh Token</button>-->
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div v-if="store.authenticated" class="token-section">
|
||||
<p><strong>Access Token:</strong></p>
|
||||
<pre>{{ store.user.token }}</pre>
|
||||
@ -93,7 +115,7 @@ const callApiWithLoading = async (path: string) => {
|
||||
/>
|
||||
<button @click="callApi(customRequest)">Call</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -110,7 +110,7 @@ const props = defineProps<{
|
||||
isAdmin: boolean;
|
||||
}>();
|
||||
|
||||
const IS_MOCK_MODE = false;
|
||||
const IS_MOCK_MODE = true;
|
||||
const IS_ADMIN = props.isAdmin;
|
||||
|
||||
const expanded = ref(false);
|
||||
|
@ -40,6 +40,18 @@ const router = createRouter({
|
||||
name: "JorCproject",
|
||||
component: () => import("../views/JoinOrCreatProjectForEntrep.vue"),
|
||||
},
|
||||
|
||||
{
|
||||
path: "/finalize",
|
||||
name: "finalize",
|
||||
component: () => import("../views/FinalizeAccount.vue"),
|
||||
},
|
||||
|
||||
{
|
||||
path: "/pending-approval",
|
||||
name: "PendingApproval",
|
||||
component: () => import("@/views/PendingApproval.vue"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -123,10 +123,58 @@ function removeSectionCell(
|
||||
});
|
||||
}
|
||||
|
||||
// Checks if the entrepreneur has a pending project request
|
||||
function checkPendingProjectRequest(
|
||||
onSuccessHandler?: (response: AxiosResponse<boolean>) => void,
|
||||
onErrorHandler?: (error: AxiosError) => void
|
||||
): void {
|
||||
axiosInstance
|
||||
.get("/entrepreneur/projects/has-pending-request")
|
||||
.then((response) => {
|
||||
if (onSuccessHandler) {
|
||||
onSuccessHandler(response);
|
||||
} else {
|
||||
defaultApiSuccessHandler(response);
|
||||
}
|
||||
})
|
||||
.catch((error: AxiosError) => {
|
||||
if (onErrorHandler) {
|
||||
onErrorHandler(error);
|
||||
} else {
|
||||
defaultApiErrorHandler(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Checks if the entrepreneur has an active project
|
||||
function checkIfProjectIsActive(
|
||||
onSuccessHandler?: (response: AxiosResponse<boolean>) => void,
|
||||
onErrorHandler?: (error: AxiosError) => void
|
||||
): void {
|
||||
axiosInstance
|
||||
.get("/entrepreneur/projects/project-is-active")
|
||||
.then((response) => {
|
||||
if (onSuccessHandler) {
|
||||
onSuccessHandler(response);
|
||||
} else {
|
||||
defaultApiSuccessHandler(response);
|
||||
}
|
||||
})
|
||||
.catch((error: AxiosError) => {
|
||||
if (onErrorHandler) {
|
||||
onErrorHandler(error);
|
||||
} else {
|
||||
defaultApiErrorHandler(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
getEntrepreneurProjectId,
|
||||
requestProjectCreation,
|
||||
addSectionCell,
|
||||
modifySectionCell,
|
||||
removeSectionCell,
|
||||
checkPendingProjectRequest,
|
||||
checkIfProjectIsActive,
|
||||
};
|
||||
|
@ -74,8 +74,30 @@ function getAllEntrepreneurs(
|
||||
});
|
||||
}
|
||||
|
||||
function checkPending(
|
||||
onSuccessHandler?: (response: AxiosResponse<boolean>) => void,
|
||||
onErrorHandler?: (error: AxiosError) => void
|
||||
): void {
|
||||
axiosInstance
|
||||
.get("/unauth/check-if-not-pending")
|
||||
.then((response) => {
|
||||
if (onSuccessHandler) {
|
||||
onSuccessHandler(response);
|
||||
} else {
|
||||
defaultApiSuccessHandler(response);
|
||||
}
|
||||
})
|
||||
.catch((error: AxiosError) => {
|
||||
if (onErrorHandler) {
|
||||
onErrorHandler(error);
|
||||
} else {
|
||||
defaultApiErrorHandler(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
finalizeAccount,
|
||||
getAllEntrepreneurs,
|
||||
checkPending,
|
||||
// requestJoinProject, // Not yet implemented [cite: 4]
|
||||
};
|
||||
|
@ -70,7 +70,6 @@ const fallbackProjects = [
|
||||
},
|
||||
];
|
||||
|
||||
/*
|
||||
const createFirstAdmin = () => {
|
||||
createAdmin(
|
||||
(response) => {
|
||||
@ -84,7 +83,8 @@ const createFirstAdmin = () => {
|
||||
}
|
||||
);
|
||||
};
|
||||
*/
|
||||
|
||||
onMounted(createFirstAdmin);
|
||||
|
||||
const fetchProjects = () => {
|
||||
getAdminProjects(
|
||||
|
81
front/MyINPulse-front/src/views/FinalizeAccount.vue
Normal file
81
front/MyINPulse-front/src/views/FinalizeAccount.vue
Normal file
@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<Header />
|
||||
<div class="finalize-page">
|
||||
<div class="loader-container">
|
||||
<button class="return-button" @click="store.logout">Logout</button>
|
||||
<div class="spinner"></div>
|
||||
<p>Finalisation du compte en cours...</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from "vue";
|
||||
//import { useRouter } from "vue-router";
|
||||
import { finalizeAccount } from "@/services/Apis/Unauth";
|
||||
import Header from "@/components/HeaderComponent.vue";
|
||||
import { store } from "@/main.ts";
|
||||
//const router = useRouter();
|
||||
|
||||
onMounted(() => {
|
||||
finalizeAccount(
|
||||
() => {
|
||||
console.log("finalize sended");
|
||||
},
|
||||
(error) => {
|
||||
console.error("Erreur lors de la finalisation :", error);
|
||||
}
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.finalize-page {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 80vh;
|
||||
background-color: #f9fbfd;
|
||||
}
|
||||
|
||||
.loader-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
color: #333;
|
||||
font-size: 1.1rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border: 5px solid #cfd8dc;
|
||||
border-top: 5px solid #3498db;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
.return-button {
|
||||
background-color: #009cde;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s ease;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<Header />
|
||||
<header class="header">
|
||||
<img
|
||||
src="@/components/icons/logo inpulse.png"
|
||||
alt="INPulse Logo"
|
||||
class="logo"
|
||||
/>
|
||||
<button class="return-button" @click="store.logout">Logout</button>
|
||||
</header>
|
||||
|
||||
<div class="choix-projet">
|
||||
@ -39,10 +41,18 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import Project from "@/ApiClasses/Project";
|
||||
import { requestProjectCreation } from "@/services/Apis/Entrepreneurs.ts";
|
||||
import Header from "../components/HeaderComponent.vue";
|
||||
import { store } from "@/main.ts";
|
||||
import {
|
||||
requestProjectCreation,
|
||||
checkIfProjectIsActive,
|
||||
checkPendingProjectRequest,
|
||||
} from "@/services/Apis/Entrepreneurs";
|
||||
|
||||
const router = useRouter();
|
||||
const choix = ref<string | null>(null);
|
||||
const nomProjet = ref("");
|
||||
|
||||
@ -56,21 +66,18 @@ const validerCreation = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Obtenir la date actuelle au format YYYY-MM-DD
|
||||
const today = new Date();
|
||||
const yyyy = today.getFullYear();
|
||||
const mm = String(today.getMonth() + 1).padStart(2, "0");
|
||||
const dd = String(today.getDate()).padStart(2, "0");
|
||||
const formattedDate = `${yyyy}-${mm}-${dd}`;
|
||||
|
||||
// Créer une instance de Project
|
||||
const nouveauProjet = new Project({
|
||||
projectName: nomProjet.value.trim(),
|
||||
creationDate: formattedDate,
|
||||
status: "PENDING",
|
||||
});
|
||||
|
||||
// Appeler l’API
|
||||
requestProjectCreation(
|
||||
nouveauProjet,
|
||||
(response) => {
|
||||
@ -83,6 +90,28 @@ const validerCreation = () => {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
checkIfProjectIsActive(
|
||||
(response) => {
|
||||
if (response.data === true) {
|
||||
router.push("/canvas");
|
||||
}
|
||||
},
|
||||
() => {
|
||||
checkPendingProjectRequest(
|
||||
(response) => {
|
||||
if (response.data === true) {
|
||||
router.push("/pending-approval");
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.warn("No active or pending project:", error);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -140,4 +169,17 @@ input {
|
||||
.logo {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.return-button {
|
||||
background-color: #009cde;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s ease;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
41
front/MyINPulse-front/src/views/PendingApproval.vue
Normal file
41
front/MyINPulse-front/src/views/PendingApproval.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<Header />
|
||||
<div class="pending-container">
|
||||
<h1>Projet en attente de validation</h1>
|
||||
<p>
|
||||
Votre demande de création de projet a bien été reçue.<br />
|
||||
Un administrateur doit valider votre projet avant que vous puissiez
|
||||
continuer.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Header from "@/components/HeaderComponent.vue";
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pending-container {
|
||||
max-width: 600px;
|
||||
margin: 100px auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
background-color: #fffdf8;
|
||||
border: 1px solid #ececec;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
|
||||
font-family: "Inter", sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #f57c00;
|
||||
font-size: 1.8rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.1rem;
|
||||
color: #333;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
</style>
|
1
keycloak/CAS/.gitignore
vendored
Normal file
1
keycloak/CAS/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
keycloak-cas
|
6
keycloak/CAS/Dockerfile
Normal file
6
keycloak/CAS/Dockerfile
Normal file
@ -0,0 +1,6 @@
|
||||
FROM maven:3.8.8-eclipse-temurin-21-alpine
|
||||
|
||||
COPY ./keycloak-cas/ .
|
||||
|
||||
RUN mvn clean package
|
||||
|
15
keycloak/CAS/build.sh
Normal file
15
keycloak/CAS/build.sh
Normal file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d "./keycloak-cas/" ]
|
||||
then
|
||||
git clone https://github.com/RoboJackets/keycloak-cas
|
||||
patch $(find . | grep UrlHelper.java) https_patch
|
||||
fi
|
||||
if [ -d "./target/" ]
|
||||
then
|
||||
rm -r target/
|
||||
fi
|
||||
docker build -t build-dep .
|
||||
docker create -it --name build-dep-container build-dep bash
|
||||
docker cp build-dep-container:/target ./target
|
||||
docker rm -f build-dep-container
|
4
keycloak/CAS/https_patch
Normal file
4
keycloak/CAS/https_patch
Normal file
@ -0,0 +1,4 @@
|
||||
41c41
|
||||
< .queryParam(PROVIDER_PARAMETER_SERVICE, uriInfo.getAbsolutePath().toString());
|
||||
---
|
||||
> .queryParam(PROVIDER_PARAMETER_SERVICE, uriInfo.getAbsolutePath().toString().replace("http://", "https://"));
|
30
keycloak/Dockerfile
Normal file
30
keycloak/Dockerfile
Normal file
@ -0,0 +1,30 @@
|
||||
FROM quay.io/keycloak/keycloak:latest AS builder
|
||||
|
||||
ARG KC_DB
|
||||
ENV KC_DB=$KC_DB
|
||||
|
||||
# Install custom providers
|
||||
|
||||
ADD --chown=keycloak:keycloak --chmod=644 ./CAS/target/*.jar /opt/keycloak/providers/cas-provider.jar
|
||||
|
||||
# build optimized image
|
||||
RUN /opt/keycloak/bin/kc.sh build
|
||||
|
||||
FROM quay.io/keycloak/keycloak:latest
|
||||
|
||||
ARG KC_DB
|
||||
ENV KC_DB=$KC_DB
|
||||
|
||||
ARG KC_DB_URL
|
||||
ENV KC_DB_URL=$KC_DB_URL
|
||||
|
||||
ARG KC_DB_USERNAME
|
||||
ENV KC_DB_USERNAME=$KC_DB_USERNAME
|
||||
|
||||
ARG KC_DB_PASSWORD
|
||||
ENV KC_DB_PASSWORD=$KC_DB_PASSWORD
|
||||
|
||||
COPY --from=builder /opt/keycloak/ /opt/keycloak/
|
||||
WORKDIR /opt/keycloak
|
||||
|
||||
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
|
2638
keycloak/realm.json
Normal file
2638
keycloak/realm.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user