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