diff --git a/.env.template b/.env.template index 5800894c09bc9a930fd39f24ef64a1a734693a99..232b90483e02b29d1af95058c1b5990cf8c98710 100644 --- a/.env.template +++ b/.env.template @@ -5,7 +5,8 @@ SSL_KEY_FILE=key.pem # Common settings HOSTNAME=localhost -ADMIN_ROLE= +ANIMATOR_ROLE=ANIMATORS +ADMIN_ROLE=ADMINS DEBUG_MODE= MOCK_OAUTH2= HTTPS_PORT= diff --git a/README.md b/README.md index a2557edd61b1f181469c910ccdef35559de42686..13d5863a8411a5a3b01002a9fcbd8447a554eff9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # Ecolyo Agent Client -[check documentation here](https://doc.self-data.alpha.grandlyon.com/ecolyo-agent/technical/getting_started/#local-usage) +[check documentation here](https://doc-self-data.apps.grandlyon.com/ecolyo-agent/technical/getting_started/#local-usage) diff --git a/docker-compose.local.yml b/docker-compose.local.yml index 1a357781a4670cb0902fc0650c123ec89e93071c..2bef82fe26ceb9c216e01b0c94be4daa80a50471 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -54,6 +54,7 @@ services: environment: - HOSTNAME=${HOSTNAME} - HTTPS_PORT=${HTTPS_PORT} + - ANIMATOR_ROLE=${ANIMATOR_ROLE} - ADMIN_ROLE=${ADMIN_ROLE} - REDIRECT_URL=${REDIRECT_URL} - CLIENT_ID=${CLIENT_ID} diff --git a/docker-compose.yml b/docker-compose.yml index 1f99f5a07a52ee39ee7b0e7c2df69db4149187c9..b0754887ab409ffaeaa8cb2da996f9d2d2380ffc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -52,6 +52,7 @@ services: environment: - HOSTNAME=${HOSTNAME} - HTTPS_PORT=${HTTPS_PORT} + - ANIMATOR_ROLE=${ANIMATOR_ROLE} - ADMIN_ROLE=${ADMIN_ROLE} - REDIRECT_URL=${REDIRECT_URL} - CLIENT_ID=${CLIENT_ID} diff --git a/nginx/site.conf b/nginx/site.conf index 998e42faf52ab6b4197943f67c0fdcd41e89ab08..127a83107dca5dd2fcb8afa776d737c6975dd649 100644 --- a/nginx/site.conf +++ b/nginx/site.conf @@ -25,7 +25,7 @@ server { proxy_pass https://backend:1443/doc; } location /imageNames { - proxy_pass https://backend:1443/api/admin/imageNames; + proxy_pass https://backend:1443/api/animator/imageNames; } location /assets { proxy_pass https://backend:1443/assets; diff --git a/nginx/site.prod.conf b/nginx/site.prod.conf index b03177f15d2ef1df2ae184b1c5331b55df63036b..bb5c70180ecd8282348efa8f1f8e2fc1dbcd2a57 100644 --- a/nginx/site.prod.conf +++ b/nginx/site.prod.conf @@ -20,7 +20,7 @@ server { proxy_pass https://backend:1443/Logout; } location /imageNames { - proxy_pass https://backend:1443/api/admin/imageNames; + proxy_pass https://backend:1443/api/animator/imageNames; } location /assets { proxy_pass https://backend:1443/assets; diff --git a/src/components/Navigation/BottomBar.tsx b/src/components/Navigation/BottomBar.tsx index ec7cf5f4a1453c04eb1c32f8898fad4b5e476ab0..0129a6363413b96f77688ef1183969f4b233bd69 100644 --- a/src/components/Navigation/BottomBar.tsx +++ b/src/components/Navigation/BottomBar.tsx @@ -12,11 +12,19 @@ const BottomBar: React.FC = () => { return ( <div className="navbar"> <div className="menu-list"> - {routes.map((route) => ( - <NavLink key={route.label} to={route.path} activeClassName="active"> - {route.label} - </NavLink> - ))} + {user && + routes.map( + (route) => + (!route.adminOnly || user?.isAdmin) && ( + <NavLink + key={route.label} + to={route.path} + activeClassName="active" + > + {route.label} + </NavLink> + ) + )} {process.env.NODE_ENV === 'development' && ( <a href="/doc/" target="_blank"> Swagger doc diff --git a/src/components/Navigation/SideBar.tsx b/src/components/Navigation/SideBar.tsx index c134495a62ab80f1984b733c8407a6b97c0526be..301ac19b2ef555924f449633fda66eec864bb065 100644 --- a/src/components/Navigation/SideBar.tsx +++ b/src/components/Navigation/SideBar.tsx @@ -16,11 +16,19 @@ const SideBar: React.FC = () => { <img src={logo} alt="Ecolyo logo" className="logo" /> </div> <div className="menu-list"> - {routes.map((route) => ( - <NavLink key={route.label} to={route.path} activeClassName="active"> - {route.label} - </NavLink> - ))} + {user && + routes.map( + (route) => + (!route.adminOnly || user.isAdmin) && ( + <NavLink + key={route.label} + to={route.path} + activeClassName="active" + > + {route.label} + </NavLink> + ) + )} {process.env.NODE_ENV === 'development' && ( <a href="/doc/" target="_blank"> Swagger doc diff --git a/src/components/Routes/Router.tsx b/src/components/Routes/Router.tsx index c48694e54b6f2ffb7e6165f2bd7ef621789aec16..a1fe6c0d2b971d07b8950128c2260ae408afa6f0 100644 --- a/src/components/Routes/Router.tsx +++ b/src/components/Routes/Router.tsx @@ -7,7 +7,9 @@ import Newsletter from '../Newsletter/Newsletter' import Popups from '../Popups/Popups' import Prices from '../Prices/Prices' -export const links: { [key: string]: { label: string; path: string } } = { +export const links: { + [key: string]: { label: string; path: string; adminOnly?: boolean } +} = { newsletter: { label: 'Newsletter', path: '/newsletter', @@ -23,17 +25,18 @@ export const links: { [key: string]: { label: string; path: string } } = { consents: { label: 'Consentements', path: '/consents', + adminOnly: true, }, } export const routes = Object.keys(links).map((key) => ({ label: links[key].label, path: links[key].path, + adminOnly: links[key].adminOnly, })) const Router: React.FC = () => { const { user } = useContext(UserContext) - console.log(user) return ( <Switch> @@ -42,7 +45,9 @@ const Router: React.FC = () => { <Route exact path={links.newsletter.path} component={Newsletter} /> <Route exact path={links.prices.path} component={Prices} /> <Route exact path={links.popups.path} component={Popups} /> - <Route exact path={links.consents.path} component={Consents} /> + {user.isAdmin && ( + <Route exact path={links.consents.path} component={Consents} /> + )} <Redirect path="*" to={links.newsletter.path} /> </> ) : ( diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts index f7df8af3276d2ca619b6fa2c7558704bd5122570..6f57d463e9384d19c25871045d2b5165d73a7878 100644 --- a/src/hooks/useAuth.ts +++ b/src/hooks/useAuth.ts @@ -1,8 +1,8 @@ -import { useContext, useState } from 'react' import axios from 'axios' -import { UserContext } from './userContext' +import { useContext, useState } from 'react' import { useHistory } from 'react-router-dom' import { links } from '../components/Routes/Router' +import { UserContext } from './userContext' export interface Auth { loginUser: () => Promise<void> diff --git a/src/hooks/useFindUser.ts b/src/hooks/useFindUser.ts index b76d2a1145652a49d9bf0abdbfd4ead40172a872..201bd31a45e281591bc5f6b69d20051cbe45f8de 100644 --- a/src/hooks/useFindUser.ts +++ b/src/hooks/useFindUser.ts @@ -1,7 +1,7 @@ -import { useState, useEffect } from 'react' import axios from 'axios' -import { User } from '../models/user.model' +import { useEffect, useState } from 'react' import { toast } from 'react-toastify' +import { User } from '../models/user.model' const useFindUser = () => { const [user, setUser] = useState<User | null>(null) @@ -16,7 +16,7 @@ const useFindUser = () => { setLoading(false) } } catch (error) { - toast.error('Access denied, please login') + toast.error('Accès refusé, veuillez vous connecter') } } findUser() diff --git a/src/services/consent.service.ts b/src/services/consent.service.ts index a474ca4ca533dacedc4aae5cbc76bf2330f81bb9..8f41655a3ea11f4286cbebeaca0da807561bed15 100644 --- a/src/services/consent.service.ts +++ b/src/services/consent.service.ts @@ -1,11 +1,11 @@ +import axios, { AxiosRequestConfig } from 'axios' +import { DateTime } from 'luxon' +import { toast } from 'react-toastify' +import { ConsentEntity, IConsent } from '../models/consent.model' import { ConsentPaginationEntity, IConsentPagination, } from './../models/consent.model' -import axios, { AxiosRequestConfig } from 'axios' -import { ConsentEntity, IConsent } from '../models/consent.model' -import { toast } from 'react-toastify' -import { DateTime } from 'luxon' export class ConsentService { /** @@ -30,11 +30,9 @@ export class ConsentService { return this.parseConsentPagination(consentPagination) } catch (e: any) { if (e.response.status === 403) { - toast.error( - "Unauthorized : You don't have the rights to do this operation" - ) + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") } else { - toast.error('Failed to get consents') + toast.error('Erreur lors de la récupération des consentements') } console.error(e) return null diff --git a/src/services/customPopup.service.ts b/src/services/customPopup.service.ts index 2ce4086a04f59ef1193916f264be9d2328c9ae02..4379356c3e73a34e2ae68aabcd53ed1a2e4370fb 100644 --- a/src/services/customPopup.service.ts +++ b/src/services/customPopup.service.ts @@ -14,7 +14,7 @@ export class CustomPopupService { ): Promise<void> => { try { await axios.put( - `/api/admin/customPopup`, + `/api/animator/customPopup`, { ...customPopup, }, diff --git a/src/services/newsletter.service.ts b/src/services/newsletter.service.ts index 660a21afc2d2f8bb07677ef0a85f589f523514da..2a2791eca2a8886ac03c3ca45797af5d72cd7bf4 100644 --- a/src/services/newsletter.service.ts +++ b/src/services/newsletter.service.ts @@ -18,7 +18,7 @@ export class NewsletterService { ): Promise<void> => { try { await axios.put( - `/api/admin/mailSubject`, + `/api/animator/mailSubject`, { month: date.getMonth() + 1, year: date.getFullYear(), @@ -26,14 +26,14 @@ export class NewsletterService { }, axiosHeaders ) - toast.success('Mail subject successfully saved !') + toast.success('Objet de la newsletter enregistré !') } catch (e: any) { if (e.response.status === 403) { + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") + } else { toast.error( - "Unauthorized : You don't have the rights to do this operation" + "Erreur lors de l’enregistrement de l'objet de la newsletter" ) - } else { - toast.error('Failed to create mail subject') } console.error(e) } @@ -50,7 +50,9 @@ export class NewsletterService { ): Promise<IMailSubject | null> => { try { const { data } = await axios.get( - `/api/admin/mailSubject/${date.getFullYear()}/${date.getMonth() + 1}`, + `/api/animator/mailSubject/${date.getFullYear()}/${ + date.getMonth() + 1 + }`, axiosHeaders ) return data as IMailSubject @@ -71,17 +73,17 @@ export class NewsletterService { ): Promise<void> => { try { await axios.delete( - `/api/admin/mailSubject/${date.getFullYear()}/${date.getMonth() + 1}`, + `/api/animator/mailSubject/${date.getFullYear()}/${ + date.getMonth() + 1 + }`, axiosHeaders ) - toast.success('Mail subject successfully deleted !') + toast.success('Objet de la newsletter supprimé !') } catch (e: any) { if (e.response.status === 403) { - toast.error( - "Unauthorized : You don't have the rights to do this operation" - ) + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") } else { - toast.error('Failed to delete mail subject') + toast.error("Erreur lors de la suppression de l'objet de la newsletter") } console.error(e) } @@ -100,7 +102,7 @@ export class NewsletterService { ): Promise<void> => { try { await axios.put( - `/api/admin/monthlyInfo`, + `/api/animator/monthlyInfo`, { month: date.getMonth() + 1, year: date.getFullYear(), @@ -109,14 +111,12 @@ export class NewsletterService { }, axiosHeaders ) - toast.success('Monthly info successfully saved !') + toast.success('Information du mois enregistrée !') } catch (e: any) { if (e.response.status === 403) { - toast.error( - "Unauthorized : You don't have the rights to do this operation" - ) + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") } else { - toast.error('Failed to create monthly info') + toast.error('Erreur lors de l’enregistrement des informations du mois') } console.error(e) } @@ -133,7 +133,9 @@ export class NewsletterService { ): Promise<IMonthlyInfo | null> => { try { const { data } = await axios.get( - `/api/admin/monthlyInfo/${date.getFullYear()}/${date.getMonth() + 1}`, + `/api/animator/monthlyInfo/${date.getFullYear()}/${ + date.getMonth() + 1 + }`, axiosHeaders ) return data as IMonthlyInfo @@ -154,17 +156,17 @@ export class NewsletterService { ): Promise<void> => { try { await axios.delete( - `/api/admin/monthlyInfo/${date.getFullYear()}/${date.getMonth() + 1}`, + `/api/animator/monthlyInfo/${date.getFullYear()}/${ + date.getMonth() + 1 + }`, axiosHeaders ) - toast.success('Monthly info successfully deleted !') + toast.success('Informations du mois supprimées !') } catch (e: any) { if (e.response.status === 403) { - toast.error( - "Unauthorized : You don't have the rights to do this operation" - ) + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") } else { - toast.error('Failed to delete monthly info') + toast.error('Erreur lors de la suppression des informations du mois') } console.error(e) } @@ -184,7 +186,7 @@ export class NewsletterService { ): Promise<void> => { try { await axios.put( - `/api/admin/monthlyNews`, + `/api/animator/monthlyNews`, { month: date.getMonth() + 1, year: date.getFullYear(), @@ -193,14 +195,12 @@ export class NewsletterService { }, axiosHeaders ) - toast.success('Monthly news successfully saved !') + toast.success('Nouveautés du mois enregistrés !') } catch (e: any) { if (e.response.status === 403) { - toast.error( - "Unauthorized : You don't have the rights to do this operation" - ) + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") } else { - toast.error('Failed to save monthly news') + toast.error('Erreur lors de l’enregistrement des nouveautés du mois') } console.error(e) } @@ -217,7 +217,9 @@ export class NewsletterService { ): Promise<IMonthlyNews | null> => { try { const { data } = await axios.get( - `/api/admin/monthlyNews/${date.getFullYear()}/${date.getMonth() + 1}`, + `/api/animator/monthlyNews/${date.getFullYear()}/${ + date.getMonth() + 1 + }`, axiosHeaders ) return data as IMonthlyNews @@ -238,17 +240,17 @@ export class NewsletterService { ): Promise<void> => { try { await axios.delete( - `/api/admin/monthlyNews/${date.getFullYear()}/${date.getMonth() + 1}`, + `/api/animator/monthlyNews/${date.getFullYear()}/${ + date.getMonth() + 1 + }`, axiosHeaders ) - toast.success('Monthly news successfully deleted !') + toast.success('Nouveautés du mois supprimées !') } catch (e: any) { if (e.response.status === 403) { - toast.error( - "Unauthorized : You don't have the rights to do this operation" - ) + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") } else { - toast.error('Failed to delete monthly news') + toast.error('Erreur lors de la suppression des nouveautés du mois') } console.error(e) } @@ -268,7 +270,7 @@ export class NewsletterService { ): Promise<void> => { try { await axios.put( - `/api/admin/poll`, + `/api/animator/poll`, { month: date.getMonth() + 1, year: date.getFullYear(), @@ -277,14 +279,12 @@ export class NewsletterService { }, axiosHeaders ) - toast.success('Poll successfully saved !') + toast.success('Sondage enregistré !') } catch (e: any) { if (e.response.status === 403) { - toast.error( - "Unauthorized : You don't have the rights to do this operation" - ) + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") } else { - toast.error('Failed to create poll') + toast.error('Erreur lors de l’enregistrement du sondage') } console.error(e) } @@ -301,7 +301,7 @@ export class NewsletterService { ): Promise<IPoll | null> => { try { const { data } = await axios.get( - `/api/admin/poll/${date.getFullYear()}/${date.getMonth() + 1}`, + `/api/animator/poll/${date.getFullYear()}/${date.getMonth() + 1}`, axiosHeaders ) return data as IPoll @@ -322,17 +322,15 @@ export class NewsletterService { ): Promise<void> => { try { await axios.delete( - `/api/admin/poll/${date.getFullYear()}/${date.getMonth() + 1}`, + `/api/animator/poll/${date.getFullYear()}/${date.getMonth() + 1}`, axiosHeaders ) - toast.success('Poll successfully deleted !') + toast.success('Sondage supprimé !') } catch (e: any) { if (e.response.status === 403) { - toast.error( - "Unauthorized : You don't have the rights to do this operation" - ) + toast.error("Accès refusé : vous n'avez pas les droits nécessaires") } else { - toast.error('Failed to delete poll') + toast.error('Erreur lors de la suppression du sondage') } console.error(e) } @@ -346,7 +344,7 @@ export class NewsletterService { ): Promise<string[]> => { try { const { data: imageNames } = await axios.get( - `/api/admin/imageNames`, + `/api/animator/imageNames`, axiosHeaders ) if (imageNames && imageNames !== null) { diff --git a/src/services/partnersInfo.service.ts b/src/services/partnersInfo.service.ts index dfa14f863425b37accdd32cb8903f2f402ac8224..0f9a5174b0066df6ec598adb7695c982fc11a3f9 100644 --- a/src/services/partnersInfo.service.ts +++ b/src/services/partnersInfo.service.ts @@ -1,6 +1,6 @@ import axios, { AxiosRequestConfig } from 'axios' -import { IPartnersInfo } from '../models/partnersInfo.model' import { toast } from 'react-toastify' +import { IPartnersInfo } from '../models/partnersInfo.model' export class PartnersInfoService { /** * Save the partnersInfo @@ -13,7 +13,7 @@ export class PartnersInfoService { ): Promise<void> => { try { await axios.put( - `/api/admin/partnersInfo`, + `/api/animator/partnersInfo`, { grdf_failure: partnersInfo.grdf_failure, enedis_failure: partnersInfo.enedis_failure, @@ -24,7 +24,9 @@ export class PartnersInfoService { ) toast.success('Information des partenaires mises à jour !') } catch (e) { - toast.error('Failed to save partners info') + toast.error( + 'Erreur lors de la mise à jour des information des partenaires' + ) console.error(e) } } diff --git a/src/services/prices.service.ts b/src/services/prices.service.ts index c53d38e35ece0c758762b5e7f0a3cbdada5d4b7e..616979c14fe619794df853822078d08503df0223 100644 --- a/src/services/prices.service.ts +++ b/src/services/prices.service.ts @@ -12,10 +12,10 @@ export class PricesService { axiosHeaders: AxiosRequestConfig ): Promise<void> => { try { - await axios.put(`/api/admin/prices`, price, axiosHeaders) - toast.success('Price successfully saved !') + await axios.put(`/api/animator/prices`, price, axiosHeaders) + toast.success('Prix des fluides mis à jour !') } catch (e) { - toast.error('Failed to save price') + toast.error('Erreur lors de la mise à jour des prix des fluides') console.error(e) } }