diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..f36e43750f66aa7e9921645912501ac74e65203e
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,22 @@
+{
+    "workbench.colorCustomizations": {
+        "activityBar.activeBackground": "#65f4ff",
+        "activityBar.activeBorder": "#ff40f1",
+        "activityBar.background": "#65f4ff",
+        "activityBar.foreground": "#15202b",
+        "activityBar.inactiveForeground": "#15202b99",
+        "activityBarBadge.background": "#ff40f1",
+        "activityBarBadge.foreground": "#15202b",
+        "sash.hoverBorder": "#65f4ff",
+        "statusBar.background": "#32f0ff",
+        "statusBar.foreground": "#15202b",
+        "statusBarItem.hoverBackground": "#00ebfe",
+        "statusBarItem.remoteBackground": "#32f0ff",
+        "statusBarItem.remoteForeground": "#15202b",
+        "titleBar.activeBackground": "#32f0ff",
+        "titleBar.activeForeground": "#15202b",
+        "titleBar.inactiveBackground": "#32f0ff99",
+        "titleBar.inactiveForeground": "#15202b99"
+    },
+    "peacock.color": "#32f0ff"
+}
\ No newline at end of file
diff --git a/internal/auth/oauth2.go b/internal/auth/oauth2.go
index 870b2dee6acb81fd25308d0aac196b7f88b825cf..01657b0056414750a326ddf1227a51dc9d591988 100644
--- a/internal/auth/oauth2.go
+++ b/internal/auth/oauth2.go
@@ -125,6 +125,17 @@ func (m Manager) HandleOAuth2Callback() http.Handler {
 		for key, role := range user.Roles {
 			user.Roles[key] = strings.TrimPrefix(strings.Split(role, ",")[0], "CN=")
 		}
+
+		// Check if user has the correct role
+		err = checkUserHasRole(TokenData{User: user}, []string{AdminRole})
+
+		if err != nil {
+			// Log the connexion attempt
+			log.Printf("| %v (%v %v) | Login failed (Unauthorized user) | %v", user.Login, user.Name, user.Surname, req.RemoteAddr)
+			http.Redirect(w, r, "/", http.StatusFound)
+			return
+		}
+
 		// Store the user in cookie
 		// Generate
 		xsrfToken, err := common.GenerateRandomString(16)
diff --git a/internal/file/file.go b/internal/file/file.go
index dba702c99bb34f643fa9a30221f599c7a8e200eb..846627974d257ba0e72d4d925f27feafbe6d057c 100644
--- a/internal/file/file.go
+++ b/internal/file/file.go
@@ -10,10 +10,12 @@ import (
 	"forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/common"
 )
 
-var imageFolder = common.StringValueFromEnv("IMAGE_FOLDER", "")
+var (
+	imageFolder = common.StringValueFromEnv("IMAGE_FOLDER", "")
+)
 
 func GetEcogestureImages(w http.ResponseWriter, r *http.Request) {
-	filenames, err := fileNamesFromFolder(imageFolder)
+	filenames, err := fileNamesFromFolder(imageFolder + "/ecogesture")
 	jsondata, err := json.Marshal(filenames)
 	if err != nil {
 		fmt.Printf("Error: %s", err.Error())
diff --git a/internal/models/models.go b/internal/models/models.go
index fc72cf87c0c4407da254bf480685d2845457d28d..d2b690f70dc0fdfbd133c5456f6f49492cf0f9f5 100644
--- a/internal/models/models.go
+++ b/internal/models/models.go
@@ -41,5 +41,15 @@ func NewDataHandler() *DataHandler {
 	db.AutoMigrate(&MonthlyInfo{})
 	db.AutoMigrate(&MonthlyNews{})
 	db.AutoMigrate(&Poll{})
+	db.AutoMigrate(&PartnersInfo{})
+
+	// Create default partner status
+	db.Create(&PartnersInfo{
+		GRDFFailure:           false,
+		EnedisFailure:         false,
+		EGLFailure:            false,
+		NotificationActivated: false,
+	})
+
 	return &DataHandler{db: db}
 }
diff --git a/internal/models/monthlyReport.go b/internal/models/monthlyReport.go
index eb8816b95b15aae5e2929ee2cd8cda6ff0a0af24..fca176d2c6a44cc44ca83a1ead3d2dfd02b24aa8 100644
--- a/internal/models/monthlyReport.go
+++ b/internal/models/monthlyReport.go
@@ -3,6 +3,7 @@ package models
 import (
 	"encoding/json"
 	"net/http"
+	"strconv"
 	"time"
 
 	"forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/common"
@@ -32,8 +33,16 @@ type MonthlyReport struct {
 func (dh *DataHandler) GetMonthlyReport(w http.ResponseWriter, r *http.Request) {
 	year, month, err := common.YearMonthFromRequest(r)
 	if err != nil {
-		http.Error(w, err.Error(), http.StatusBadRequest)
-		return
+		year, err = strconv.Atoi(r.URL.Query().Get("year"))
+		if err != nil {
+			http.Error(w, "year in query is not an integer", http.StatusBadRequest)
+			return
+		}
+		month, err = strconv.Atoi(r.URL.Query().Get("month"))
+		if err != nil {
+			http.Error(w, "month in query is not an integer", http.StatusBadRequest)
+			return
+		}
 	}
 
 	monthlyReport, err := dh.getMonthlyReport(year, month)
@@ -58,7 +67,7 @@ func (dh *DataHandler) GetCurrentMonthlyReport(w http.ResponseWriter, r *http.Re
 
 	year, month, _ := time.Now().Date()
 
-	monthlyReport, err := dh.getMonthlyReport(year, int(month)-1)
+	monthlyReport, err := dh.getMonthlyReport(year, int(month))
 	if err != nil {
 		w.WriteHeader(http.StatusNotFound)
 		return
diff --git a/internal/models/partnersInfo.go b/internal/models/partnersInfo.go
new file mode 100644
index 0000000000000000000000000000000000000000..35652e7cdf9ed941b72140b7f383a82b4598608a
--- /dev/null
+++ b/internal/models/partnersInfo.go
@@ -0,0 +1,86 @@
+package models
+
+import (
+	"encoding/json"
+	"errors"
+	"log"
+	"net/http"
+
+	"gorm.io/gorm"
+)
+
+type PartnersInfo struct {
+	ID                    uint   `gorm:"<-:create"`
+	GRDFFailure           bool   `json:"grdf_failure"`
+	EnedisFailure         bool   `json:"enedis_failure"`
+	EGLFailure            bool   `json:"egl_failure"`
+	NotificationActivated bool   `json:"notification_activated"`
+}
+
+// GetPartnersInfo godoc
+// @Summary Give status of partners' services
+// @Description Give status of partners' services
+// @Tags partnersInfo
+// @Produce  json
+// @Success 200 {object} PartnersInfo
+// @Failure 404 {string} string "Not found"
+// @Router /api/common/partnersInfo [get]
+func (dh *DataHandler) GetPartnersInfo(w http.ResponseWriter, r *http.Request) {
+	var partnersInfo PartnersInfo
+	err := dh.db.First(&partnersInfo).Error
+
+	if errors.Is(err, gorm.ErrRecordNotFound) {
+		http.Error(w, "partners status not found", http.StatusNotFound)
+		return
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(partnersInfo)
+	log.Printf("| get partnersInfo | %v", r.RemoteAddr)
+}
+
+// SavePartnersInfo godoc
+// @Summary Update partnersInfo' content
+// @Description Update partnersInfo' content
+// @Tags partnersInfo
+// @Accept json
+// @Produce json
+// @Success 200 {object} PartnersInfo "Updated successfully"
+// @Failure 400 {string} string "Bad Request"
+// @Failure 500 {string} string "Internal server error"
+// @Param partnersInfo body PartnersInfo true "PartnersInfo to create/update with new content"
+// @Router /api/admin/partnersInfo [put]
+func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request) {
+	if r.Body == http.NoBody {
+		http.Error(w, "request body is empty", http.StatusBadRequest)
+		return
+	}
+
+	decoder := json.NewDecoder(r.Body)
+	var partnersInfo PartnersInfo
+	err := decoder.Decode(&partnersInfo)
+	if err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	var updatedPartnersInfo PartnersInfo
+
+	err = dh.db.First(&updatedPartnersInfo).Error
+	if err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	updatedPartnersInfo.GRDFFailure = partnersInfo.GRDFFailure
+	updatedPartnersInfo.EnedisFailure = partnersInfo.EnedisFailure
+	updatedPartnersInfo.EGLFailure = partnersInfo.EGLFailure
+	updatedPartnersInfo.NotificationActivated = partnersInfo.NotificationActivated
+
+	dh.db.Save(&updatedPartnersInfo)
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(partnersInfo)
+	log.Printf("| updated partnersInfo | %v", r.RemoteAddr)
+
+}
diff --git a/internal/rootmux/rootmux.go b/internal/rootmux/rootmux.go
index 84307853fc0f8bb6e6803b2f4674d3625708fabd..6264fbf04e703022ae8694e927a9773b14816869 100644
--- a/internal/rootmux/rootmux.go
+++ b/internal/rootmux/rootmux.go
@@ -5,12 +5,15 @@ import (
 
 	_ "forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/docs"
 	"forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/auth"
+	"forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/common"
 	"forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/file"
 	"forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/models"
 	"github.com/gorilla/mux"
 	httpSwagger "github.com/swaggo/http-swagger"
 )
 
+var imageFolder = common.StringValueFromEnv("IMAGE_FOLDER", "")
+
 type RootMux struct {
 	Router  *mux.Router
 	Manager *auth.Manager
@@ -35,9 +38,11 @@ func CreateRootMux() RootMux {
 	r.Handle("/OAuth2Callback", m.HandleOAuth2Callback())
 	r.HandleFunc("/Logout", m.HandleLogout)
 	r.Handle("/api/common/WhoAmI", auth.ValidateAuthMiddleware(auth.WhoAmI(), []string{"*"}, false))
+	r.PathPrefix("/assets/").Handler(http.StripPrefix("/assets/", http.FileServer(http.Dir("./"+imageFolder+"/"))))
 
-	r.HandleFunc("/api/common/monthlyReport", dh.GetCurrentMonthlyReport).Methods(http.MethodGet)
+	r.HandleFunc("/api/common/monthlyReport", dh.GetMonthlyReport).Methods(http.MethodGet)
 	r.HandleFunc("/api/common/monthlyReport/{year}/{month}", dh.GetMonthlyReport).Methods(http.MethodGet)
+	r.HandleFunc("/api/common/partnersInfo", dh.GetPartnersInfo).Methods(http.MethodGet)
 
 	apiAdmin := r.PathPrefix("/api/admin").Subrouter()
 	apiAdmin.Use(auth.AdminAuthMiddleware)
@@ -57,6 +62,8 @@ func CreateRootMux() RootMux {
 	apiAdmin.HandleFunc("/poll", dh.SavePoll).Methods(http.MethodPut)
 	apiAdmin.HandleFunc("/poll/{year}/{month}", dh.DeletePoll).Methods(http.MethodDelete)
 
+	apiAdmin.HandleFunc("/partnersInfo", dh.SavePartnersInfo).Methods(http.MethodPut)
+
 	apiAdmin.HandleFunc("/imageNames", file.GetEcogestureImages).Methods(http.MethodGet)
 
 	// Swagger
diff --git a/internal/rootmux/rootmux_test.go b/internal/rootmux/rootmux_test.go
index 9fa492dc35d827089db7d6e0023fa7ff99e3260b..c52e2a1deacf81322268e73e611134be9d9afa3a 100644
--- a/internal/rootmux/rootmux_test.go
+++ b/internal/rootmux/rootmux_test.go
@@ -17,14 +17,16 @@ import (
 )
 
 var (
-	oAuth2Server   *httptest.Server
-	monthlyInfo    = models.MonthlyInfo{Year: 2021, Month: 0, Info: "Informations du mois", Image: "imagebase64"}
-	monthlyInfoStr string
-	monthlyNews    = models.MonthlyNews{Year: 2021, Month: 0, Title: "", Content: "Nouvelles fonctionnalités"}
-	monthlyNewsStr string
-	newPoll        = models.Poll{Year: 2021, Month: 0, Question: "pollQuestion", Link: "pollLink"}
-	newPollStr     string
-	noH            map[string]string
+	oAuth2Server    *httptest.Server
+	monthlyInfo     = models.MonthlyInfo{Year: 2021, Month: 0, Info: "Informations du mois", Image: "imagebase64"}
+	monthlyInfoStr  string
+	monthlyNews     = models.MonthlyNews{Year: 2021, Month: 0, Title: "", Content: "Nouvelles fonctionnalités"}
+	monthlyNewsStr  string
+	newPoll         = models.Poll{Year: 2021, Month: 0, Question: "pollQuestion", Link: "pollLink"}
+	newPollStr      string
+	partnersInfo    = models.PartnersInfo{ID: 1, GRDFFailure: false, EnedisFailure: false, EGLFailure: true, NotificationActivated: true}
+	partnersInfoStr string
+	noH             map[string]string
 )
 
 func TestMain(m *testing.M) {
@@ -51,6 +53,8 @@ func TestMain(m *testing.M) {
 	monthlyNewsStr = string(monthlyNewsBytes)
 	monthlyInfoBytes, _ := json.Marshal(monthlyInfo)
 	monthlyInfoStr = string(monthlyInfoBytes)
+	partnersInfoBytes, _ := json.Marshal(partnersInfo)
+	partnersInfoStr = string(partnersInfoBytes)
 	newPollBytes, _ := json.Marshal(newPoll)
 	newPollStr = string(newPollBytes)
 
@@ -94,8 +98,12 @@ func unloggedTests(t *testing.T) {
 
 	// Try to create a monthlyNews (must fail)
 	do("PUT", "/api/admin/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "error extracting token")
-	// Try to get the most recent monthlyReport (must fail because not found)
-	do("GET", "/api/common/monthlyReport", noH, "", http.StatusNotFound, "")
+	// Try to get a monthlyReport (must fail because no parameters are given)
+	do("GET", "/api/common/monthlyReport", noH, "", http.StatusBadRequest, "")
+	// Try to get a monthlyReport (must fail because not found)
+	do("GET", "/api/common/monthlyReport?year=2021&month=12", noH, "", http.StatusNotFound, "")
+	// Try to get partnersInfo (must pass)
+	do("GET", "/api/common/partnersInfo", noH, "", http.StatusOK, `{"ID":1,"grdf_failure":false,"enedis_failure":false,"egl_failure":false,"notification_activated":false}`)
 }
 
 /**
@@ -156,6 +164,11 @@ func adminTests(t *testing.T) {
 		// Try to get the monthlyReport (must pass)
 		do("GET", "/api/common/monthlyReport/2021/0", noH, "", http.StatusOK, `{"year":2021,"month":0,"info":"Informations du mois","image":"imagebase64","newsTitle":"Les nouveautés du service","newsContent":"Nouvelles fonctionnalités","question":"pollQuestion","link":"pollLink"`)
 
+		// Try to update the partnersInfo (must pass)
+		do("PUT", "/api/admin/partnersInfo", xsrfHeader, partnersInfoStr, http.StatusOK, partnersInfoStr)
+		// Try to get the monthlyInfo created (must pass)
+		do("GET", "/api/common/partnersInfo", xsrfHeader, "", http.StatusOK, partnersInfoStr)
+
 		// Try to delete the monthlyNews created (must pass)
 		do("DELETE", "/api/admin/monthlyNews/2021/0", xsrfHeader, "", http.StatusOK, "successful delete")
 		// Try to get a monthlyNews after it is deleted (must fail because not found)