From cc7d4ceddf2e42f58508c115dc22b2cc0a117c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Pailharey?= <rpailharey@grandlyon.com> Date: Wed, 30 Aug 2023 17:27:26 +0200 Subject: [PATCH] feat: added animator role and permissions --- .env.template | 1 + README.md | 2 +- docker-compose.local.yml | 1 + docker-compose.yml | 1 + nginx/site.conf | 2 +- nginx/site.prod.conf | 2 +- src/components/Navigation/BottomBar.tsx | 18 ++++++++---- src/components/Navigation/SideBar.tsx | 18 ++++++++---- src/components/Routes/Router.tsx | 10 +++++-- src/hooks/useAuth.ts | 4 +-- src/services/consent.service.ts | 12 ++++---- src/services/customPopup.service.ts | 2 +- src/services/newsletter.service.ts | 38 ++++++++++++++++--------- src/services/partnersInfo.service.ts | 4 +-- src/services/prices.service.ts | 2 +- 15 files changed, 76 insertions(+), 41 deletions(-) diff --git a/.env.template b/.env.template index 5800894c..62833326 100644 --- a/.env.template +++ b/.env.template @@ -5,6 +5,7 @@ SSL_KEY_FILE=key.pem # Common settings HOSTNAME=localhost +ANIMATOR_ROLE= ADMIN_ROLE= DEBUG_MODE= MOCK_OAUTH2= diff --git a/README.md b/README.md index a2557edd..13d5863a 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 1a357781..2bef82fe 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 1f99f5a0..b0754887 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 998e42fa..127a8310 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 b03177f1..bb5c7018 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 ec7cf5f4..0129a636 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 c134495a..301ac19b 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 c48694e5..e14083f0 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,12 +25,14 @@ 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 = () => { @@ -42,7 +46,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 f7df8af3..6f57d463 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/services/consent.service.ts b/src/services/consent.service.ts index a474ca4c..e2a4f010 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,9 +30,7 @@ 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') } diff --git a/src/services/customPopup.service.ts b/src/services/customPopup.service.ts index 2ce4086a..4379356c 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 660a21af..be6a111f 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(), @@ -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,7 +73,9 @@ 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 !') @@ -100,7 +104,7 @@ export class NewsletterService { ): Promise<void> => { try { await axios.put( - `/api/admin/monthlyInfo`, + `/api/animator/monthlyInfo`, { month: date.getMonth() + 1, year: date.getFullYear(), @@ -133,7 +137,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,7 +160,9 @@ 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 !') @@ -184,7 +192,7 @@ export class NewsletterService { ): Promise<void> => { try { await axios.put( - `/api/admin/monthlyNews`, + `/api/animator/monthlyNews`, { month: date.getMonth() + 1, year: date.getFullYear(), @@ -217,7 +225,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,7 +248,9 @@ 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 !') @@ -268,7 +280,7 @@ export class NewsletterService { ): Promise<void> => { try { await axios.put( - `/api/admin/poll`, + `/api/animator/poll`, { month: date.getMonth() + 1, year: date.getFullYear(), @@ -301,7 +313,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,7 +334,7 @@ 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 !') @@ -346,7 +358,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 dfa14f86..ca4ec52b 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, diff --git a/src/services/prices.service.ts b/src/services/prices.service.ts index c53d38e3..294ed15b 100644 --- a/src/services/prices.service.ts +++ b/src/services/prices.service.ts @@ -12,7 +12,7 @@ export class PricesService { axiosHeaders: AxiosRequestConfig ): Promise<void> => { try { - await axios.put(`/api/admin/prices`, price, axiosHeaders) + await axios.put(`/api/animator/prices`, price, axiosHeaders) toast.success('Price successfully saved !') } catch (e) { toast.error('Failed to save price') -- GitLab