permissions review
This commit is contained in:
@@ -45,7 +45,6 @@ export default function Footer(){
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* TODO : mettre nos noms dans un fichier de configuration */}
|
||||
<Modal title={"Réalisé par"} open={isCopyrightModal} onClose={() => setIsCopyrightModal(false)}>
|
||||
<section className={styles.section}>
|
||||
<div className={styles.inputContainer}>
|
||||
|
||||
@@ -9,7 +9,6 @@ import getUserNotifications from "../../utils/notifications/getUserNotifications
|
||||
import deleteNotificationUser from "../../utils/notifications/deleteNotificationUser.js";
|
||||
import initEcho from "../../utils/echo/initEcho.js"
|
||||
import readNotifications from "../../utils/notifications/readNotifications.js";
|
||||
import getUser from "../../utils/getUser.js";
|
||||
import { userCreatedListener } from "../../utils/echo/listeners/userCreatedListener";
|
||||
import { userNotificationsListener } from "../../utils/echo/listeners/userNotificationsListener.js";
|
||||
import NotificationCard from "../NotificationCard/NotificationCard.jsx";
|
||||
@@ -28,10 +27,7 @@ function Header() {
|
||||
|
||||
async function initializeHeader() {
|
||||
try {
|
||||
const [userData, notifData] = await Promise.all([
|
||||
getUser(),
|
||||
getUserNotifications()
|
||||
]);
|
||||
const notifData = await getUserNotifications();
|
||||
|
||||
const data = notifData || [];
|
||||
setNotifications(data);
|
||||
@@ -42,8 +38,8 @@ function Header() {
|
||||
echoInstance = echo;
|
||||
|
||||
const activeChannels = [
|
||||
userCreatedListener(echo, userData, setNotifications, setunreadNotification),
|
||||
userNotificationsListener(echo, userData, setNotifications, setunreadNotification),
|
||||
userCreatedListener(echo, user, setNotifications, setunreadNotification),
|
||||
userNotificationsListener(echo, user, setNotifications, setunreadNotification),
|
||||
];
|
||||
channelsToLeave = activeChannels.filter(name => name !== null);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import styles from "./PendingMembers.module.css";
|
||||
import getUserToValidate from "../../utils/users/getUserToValidate";
|
||||
import getUserById from "../../utils/users/getUserById";
|
||||
import validateUser from "../../utils/users/validateUser";
|
||||
import deleteUser from "../../utils/users/deleteUser";
|
||||
import deleteOtherUser from "../../utils/users/deleteOtherUser.js";
|
||||
|
||||
function PendingMembers() {
|
||||
const [pendingMembers, setPendingMembers] = useState([]);
|
||||
@@ -55,7 +55,7 @@ function PendingMembers() {
|
||||
setActionLoading(id);
|
||||
setError(null);
|
||||
try {
|
||||
const result = await deleteUser(id);
|
||||
const result = await deleteOtherUser(id);
|
||||
if (result.success) {
|
||||
removeMember(id);
|
||||
} else {
|
||||
|
||||
@@ -65,7 +65,7 @@ function SearchBar() {
|
||||
<div className={styles.elementList}>
|
||||
{searchResults.map((result, i) => (
|
||||
(location.pathname.includes("events")) ? (
|
||||
<Link to={`/event/` + result.id}>
|
||||
<Link to={`/events/` + result.id}>
|
||||
<div className={styles.searchedEvent} key={i}>
|
||||
<div className={`${styles.eventImageDiv}`}>
|
||||
{result.image == null ? (
|
||||
|
||||
@@ -6,6 +6,7 @@ import ThemeSwitcher from "../ui/themeSwitcher/ThemeSwitcher.jsx";
|
||||
import { AuthContext } from "../../contexts/auth/AuthContext.js";
|
||||
import TextInput from "../ui/input/input.jsx";
|
||||
import updateUser from "../../utils/users/updateUser.js";
|
||||
import deleteUser from "../../utils/users/deleteUser.js";
|
||||
|
||||
|
||||
export default function SettingsModal() {
|
||||
@@ -13,6 +14,7 @@ export default function SettingsModal() {
|
||||
const { user, logout, update } = useContext(AuthContext);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [isDelete, setIsDelete] = useState(false);
|
||||
|
||||
const [name, setName] = useState(user?.name);
|
||||
const [lastname, setLastName] = useState(user?.lastname);
|
||||
@@ -27,6 +29,11 @@ export default function SettingsModal() {
|
||||
update();
|
||||
}
|
||||
|
||||
const handleDelete = async () => {
|
||||
await deleteUser();
|
||||
update();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant={"transparent"} onClick={() => setOpen(!open)}>
|
||||
@@ -39,6 +46,7 @@ export default function SettingsModal() {
|
||||
<div className={styles.section}>
|
||||
<h3>Compte</h3>
|
||||
<Button variant={"danger"} onClick={handleLogout}> Déconnexion </Button>
|
||||
<Button variant={"danger"} onClick={() => setIsDelete(true)}> Supprimer le compte </Button>
|
||||
|
||||
<div className={styles.section}>
|
||||
<h4>Changer de Prénom</h4>
|
||||
@@ -65,6 +73,14 @@ export default function SettingsModal() {
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
|
||||
<Modal title={"Validation"} open={isDelete} onClose={() => setIsDelete(false)}>
|
||||
<div className={styles.section}>
|
||||
<p className={styles.alignText}> Êtes vous vraiment sûr de vouloir supprimer votre compte ?</p>
|
||||
<Button variant={"danger"} className={styles.submitBtn} onClick={handleDelete}>Confirmer</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -21,3 +21,8 @@
|
||||
.submitBtn {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
|
||||
.alignText{
|
||||
text-align: center;
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
import styles from "./ToolBar.module.css"
|
||||
import Filter from "../Filter/Filter.jsx";
|
||||
import {useEffect, useState} from "react";
|
||||
import {useContext, useEffect, useState} from "react";
|
||||
import SearchBar from "../SearchBar/SearchBar.jsx";
|
||||
import CreateEventBtn from "../createEventBtn/CreateEventBtn.jsx";
|
||||
import Button from "../ui/button/button.jsx";
|
||||
|
||||
import {AuthContext} from "../../contexts/auth/AuthContext.js";
|
||||
|
||||
function ToolBar({setFilters, filters, showCreate = true}) {
|
||||
const { user } = useContext(AuthContext);
|
||||
const [isFilterVisible, setIsFilterVisible] = useState(false);
|
||||
const [isSearchVisible, setIsSearchVisible] = useState(false);
|
||||
const toggleFilters = () => {
|
||||
@@ -37,7 +38,7 @@ function ToolBar({setFilters, filters, showCreate = true}) {
|
||||
</div>
|
||||
) : null}
|
||||
<div className={styles.eventsButtons}>
|
||||
{showCreate ? (
|
||||
{showCreate && user.isAdmin ? (
|
||||
<CreateEventBtn />
|
||||
) : null}
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import Button from "../ui/button/button.jsx";
|
||||
import Modal from "../ui/modal/modal.jsx";
|
||||
import { useState } from "react";
|
||||
import {useContext, useState} from "react";
|
||||
import styles from "./manageMember.module.css"
|
||||
import DeleteMemberBtn from "./deleteMember/deleteMemberBtn.jsx";
|
||||
import DeactivateMemberBtn from "./deactivateMember/deactivateMemberBtn.jsx";
|
||||
import ModifyRole from "./modifyrole/ModifyRole.jsx";
|
||||
import {AuthContext} from "../../contexts/auth/AuthContext.js";
|
||||
|
||||
export default function ManageMember({ user }) {
|
||||
|
||||
export default function ManageMember({ userToManage }) {
|
||||
|
||||
const { user } = useContext(AuthContext);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
|
||||
@@ -16,16 +19,18 @@ export default function ManageMember({ user }) {
|
||||
<p>Gérer</p>
|
||||
</Button>
|
||||
|
||||
<Modal open={open} onClose={() => setOpen(false)} title={`Gestion de l'utilisateur ${user.name}`}>
|
||||
<Modal open={open} onClose={() => setOpen(false)} title={`Gestion de l'utilisateur ${userToManage.name}`}>
|
||||
|
||||
{(user.id != userToManage.id) ? (
|
||||
<div className={styles.manageSection}>
|
||||
<h3>Supprimer le compte</h3>
|
||||
<DeleteMemberBtn name={user.name} id={user.id} className={styles.manageBlockContent} />
|
||||
<h3>Désactiver le compte</h3>
|
||||
<DeactivateMemberBtn name={userToManage.name} id={userToManage.id} className={styles.manageBlockContent} />
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className={styles.manageSection}>
|
||||
<h3>Modifier le rôle</h3>
|
||||
<ModifyRole user={user} />
|
||||
<ModifyRole user={userToManage} />
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
|
||||
+7
-7
@@ -1,16 +1,16 @@
|
||||
import Button from "../../ui/button/button.jsx";
|
||||
import Modal from "../../ui/modal/modal.jsx";
|
||||
import { useState } from "react";
|
||||
import deleteUser from "../../../utils/users/deleteUser.js"
|
||||
import deactivateUser from "../../../utils/users/deactivateUser.js"
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
export default function DeleteMemberBtn({ name, id, ...props }) {
|
||||
export default function DeactivateMemberBtn({ name, id, ...props }) {
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const delMember = async () => {
|
||||
const result = await deleteUser(id);
|
||||
const deactivateMember = async () => {
|
||||
const result = await deactivateUser(id);
|
||||
|
||||
if (result.status === 200 || result.status === 204) {
|
||||
setOpen(false);
|
||||
@@ -19,12 +19,12 @@ export default function DeleteMemberBtn({ name, id, ...props }) {
|
||||
}
|
||||
|
||||
return <div {...props}>
|
||||
<Button variant={"danger"} onClick={() => setOpen(true)}>Supprimer</Button>
|
||||
<Button variant={"danger"} onClick={() => setOpen(true)}>Désactiver</Button>
|
||||
|
||||
<Modal open={open} onClose={() => setOpen(false)} title={"Supprimer"}>
|
||||
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 15 }}>
|
||||
<p>Etes-vous sur de vouloir supprimer le compte {name} ?</p>
|
||||
<Button variant={"danger"} onClick={delMember}>Supprimer</Button>
|
||||
<p>Etes-vous sur de vouloir désactiver le compte {name} ?</p>
|
||||
<Button variant={"danger"} onClick={deactivateMember}>Désactiver</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
@@ -45,7 +45,7 @@ export default function VolunteerProfilePage() {
|
||||
<div className={styles.description}>
|
||||
<div className={styles.headerProfile}>
|
||||
<h2> {user.name} {user.lastname} </h2>
|
||||
{currentUser?.isAdmin && <ManageMember user={user} />}
|
||||
{currentUser?.isAdmin && <ManageMember userToManage={user} />}
|
||||
</div>
|
||||
<div className={styles.topDescription}>
|
||||
<div className={`${styles.infoBlock} glassBorder`}>
|
||||
|
||||
@@ -3,7 +3,7 @@ import Background from "../../components/background/background.jsx";
|
||||
import Button from "../../components/ui/button/button.jsx";
|
||||
import { useContext } from "react";
|
||||
import { AuthContext } from "../../contexts/auth/AuthContext.js";
|
||||
import { Navigate, useNavigate } from "react-router";
|
||||
import { Navigate, useNavigate, Link } from "react-router";
|
||||
|
||||
export default function ValidationErrorPage() {
|
||||
|
||||
@@ -22,7 +22,11 @@ export default function ValidationErrorPage() {
|
||||
<h1 className={styles.title}> Votre compte n'a pas été validé </h1>
|
||||
<div className={`${styles.container} glassCard`}>
|
||||
<p> Votre compte n'a pas encore été validé, veuillez attendre la vérification de votre compte par un membre autorisé. </p>
|
||||
<p> Contact : contact@example.com </p>
|
||||
<p> Contact :
|
||||
<Link to={"https://comite.beaupont.fr/contactez-nous"} className={styles.link}>
|
||||
https://comite.beaupont.fr/contactez-nous
|
||||
</Link>
|
||||
</p>
|
||||
<Button variant={"danger"} onClick={handleLogout}> Déconnexion </Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export const userCreatedListener = (echo, userData, setNotifications, setunreadNotification) => {
|
||||
if (userData.isAdmin || userData.role === "Gérant") {
|
||||
if (userData.isAdmin) {
|
||||
const channelName = "users.registration";
|
||||
echo.private(channelName)
|
||||
.listen(".users.registration", (event) => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export const userNotificationsListener = (echo, userData, setNotifications, setunreadNotification) => {
|
||||
if (!userData?.id) return null;
|
||||
|
||||
const channelName = `user.${userData.id}`;
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import getXSRFToken from "../getXSRF.js";
|
||||
|
||||
export default async function deactivateUser(userId) {
|
||||
const csrfToken = await getXSRFToken();
|
||||
|
||||
try {
|
||||
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/users/${userId}/deactivate`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-XSRF-TOKEN': csrfToken,
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: userId
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
return {
|
||||
status: response.status,
|
||||
errors: data.errors || data.message
|
||||
};
|
||||
}
|
||||
|
||||
return { status: response.status, data };
|
||||
|
||||
} catch (error) {
|
||||
return { status: 500, error };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import getXSRFToken from "../getXSRF.js";
|
||||
|
||||
export default async function deleteOtherUser(userId) {
|
||||
const csrfToken = await getXSRFToken();
|
||||
|
||||
try {
|
||||
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/users/${userId}`, {
|
||||
method: 'DELETE',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-XSRF-TOKEN': csrfToken,
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: userId
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
return {
|
||||
status: response.status,
|
||||
errors: data.errors || data.message
|
||||
};
|
||||
}
|
||||
|
||||
return { status: response.status, data };
|
||||
|
||||
} catch (error) {
|
||||
return { status: 500, error };
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,17 @@
|
||||
import getXSRFToken from "../getXSRF.js";
|
||||
|
||||
export default async function deleteUser(userId) {
|
||||
export default async function deleteUser() {
|
||||
const csrfToken = await getXSRFToken();
|
||||
|
||||
try {
|
||||
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/users/${userId}`, {
|
||||
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/users`, {
|
||||
method: 'DELETE',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-XSRF-TOKEN': csrfToken,
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: userId
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
Reference in New Issue
Block a user