diff --git a/.vscode/settings.json b/.vscode/settings.json index 11a1978e8b65f62fa6d8ce4f9b7fba81a8f0623b..729c384ee9f3e02854db8881d8b48b0d28c353f7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,18 +25,26 @@ "backoffice", "ecogesture", "ecolyo", + "Enedis", "firstname", "fluidtype", "godoc", "gorm", "grandlyon", + "GRDF", + "imagebase", "insee", "lastname", "llle", "mysqldump", "numerique", + "redir", "rootmux", "selfdata", - "uroot" + "Sharedfor", + "Successfull", + "uroot", + "userinfo", + "xsrf" ] } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 7a0ec0fec112bd1e7456912e17c7a0be00c81377..21d3381156fb7154d0b2e9a5609a074f35978c24 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # STEP 1 build executable binary # ################################## -FROM golang as builder +FROM golang AS builder # Install git + SSL ca certificates. # Git is required for fetching the dependencies. diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 2670382e45bcb5ab9aad6b68a1e57b798888e20b..ed83d4e2e732c62a91b125e10ab66c2a2e875e91 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -10,6 +10,7 @@ import ( "strings" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/tokens" ) @@ -76,7 +77,7 @@ func ValidateAuthMiddleware(next http.Handler, allowedRoles []string, checkXSRF if perr == nil { redirectTo += ":" + port } - w.Header().Set("Content-Type", "text/html") + w.Header().Set(constants.ContentType, "text/html") w.WriteHeader(http.StatusUnauthorized) responseContent := fmt.Sprintf("error extracting token: %v<meta http-equiv=\"Refresh\" content=\"0; url=https://%v#login\"/>", err.Error(), redirectTo) fmt.Fprint(w, responseContent) diff --git a/internal/common/common.go b/internal/common/common.go index 3514b4531a5c3e5cb649868e6540efecd34cd913..c2bd4ed727a0cc09aa9b3ee07dbbf230f34665f8 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -18,6 +18,8 @@ import ( "github.com/go-chi/chi/v5" ) +const missingQueryElement = "missing query element" + var ( disableLogFatal = false lock sync.Mutex // Mutex used to lock file writing @@ -156,7 +158,7 @@ func YearMonthFromRequest(r *http.Request) (year int, month int, err error) { monthStr := chi.URLParam(r, "month") if yearStr == "" || monthStr == "" { - return 0, 0, errors.New("missing query element") + return 0, 0, errors.New(missingQueryElement) } year, err = strconv.Atoi(yearStr) @@ -191,7 +193,7 @@ func PageLimitFromRequest(r *http.Request) (page int, limit int, err error) { limitStr := r.URL.Query().Get("limit") if pageStr == "" || limitStr == "" { - return 0, 0, errors.New("missing query element") + return 0, 0, errors.New(missingQueryElement) } page, err = strconv.Atoi(pageStr) @@ -215,12 +217,12 @@ func PageLimitFromRequest(r *http.Request) (page int, limit int, err error) { return page, limit, nil } -//Get fluidType from Request +// Get fluidType from Request func FluidTypeFromRequest(r *http.Request) (fluidtype int, err error) { fluidTypeStr := chi.URLParam(r, "fluidtype") if fluidTypeStr == "" { - return 100, errors.New("missing query element") + return 100, errors.New(missingQueryElement) } fluidtype, err = strconv.Atoi(fluidTypeStr) diff --git a/internal/constants/constants.go b/internal/constants/constants.go new file mode 100644 index 0000000000000000000000000000000000000000..f56f127f6ec8e5325d9bb7990bcddc6660b67c38 --- /dev/null +++ b/internal/constants/constants.go @@ -0,0 +1,7 @@ +package constants + +const ( + ContentType = "Content-Type" + Json = "application/json" + FormUrlEncoded = "application/x-www-form-urlencoded" +) diff --git a/internal/file/file.go b/internal/file/file.go index 53e515b3cc87b4d5722ff2119e4b085862fb962a..050cc01192ded776e9304a53a9847d7107fec9c3 100644 --- a/internal/file/file.go +++ b/internal/file/file.go @@ -8,6 +8,7 @@ import ( "net/http" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" ) var ( @@ -22,7 +23,7 @@ func GetEcogestureImages(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) w.Write(jsondata) log.Printf("| get image names | %v", r.RemoteAddr) } diff --git a/internal/file/file_test.go b/internal/file/file_test.go index d8dcc99b3b5b767933c9633adea7139ece1fab46..28a3feb530eb63fc6e14afd8a578347f7f943c9b 100644 --- a/internal/file/file_test.go +++ b/internal/file/file_test.go @@ -25,13 +25,13 @@ func TestFilenamesFromFolder(t *testing.T) { t.Errorf(`error: %s`, err) return } - jsondata, err := json.Marshal(filenames) + jsonData, err := json.Marshal(filenames) if err != nil { t.Errorf(`error: %s`, err) return } - if string(jsondata) != expected { - t.Errorf(`unexpected answer: got %s want %s`, string(jsondata), expected) + if string(jsonData) != expected { + t.Errorf(`unexpected answer: got %s want %s`, string(jsonData), expected) return } os.RemoveAll("test") diff --git a/internal/mocks/mocks.go b/internal/mocks/mocks.go index 724552d295444b5bbc6b24e095144deb69d79088..41c0663619f46451c9d6e3c43feee50c37dc6c34 100644 --- a/internal/mocks/mocks.go +++ b/internal/mocks/mocks.go @@ -4,6 +4,8 @@ package mocks import ( "fmt" "net/http" + + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" ) var ( @@ -33,7 +35,7 @@ func CreateMockOAuth2() *http.ServeMux { // Returns access token back to the user mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/x-www-form-urlencoded") + w.Header().Set(constants.ContentType, constants.FormUrlEncoded) w.Write([]byte("access_token=mocktoken&scope=user&token_type=bearer")) }) // Returns userinfo back to the user (with an animator user) @@ -51,7 +53,7 @@ func CreateMockOAuth2() *http.ServeMux { }) // Returns userinfo back to the user (with an admin user) mux.HandleFunc("/admininfo", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) w.Write([]byte(`{ "displayName": "Ad MIN", "memberOf": [ diff --git a/internal/models/consent.go b/internal/models/consent.go index 6a79ba09751d117a8421d4b14ab9155e21a3ea4b..88e6a1771e08b6c474226b425181b4608e74f86e 100644 --- a/internal/models/consent.go +++ b/internal/models/consent.go @@ -8,6 +8,7 @@ import ( "time" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" "gorm.io/gorm" ) @@ -48,6 +49,7 @@ type UpdateConsentBody struct { } // GetConsentById godoc +// // @Summary Get details of a specific consent // @Description Get details of a specific consent // @Tags consent @@ -74,13 +76,14 @@ func (dh *DataHandler) GetConsentById(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(consent) log.Printf("| get consent | name : %v | %v", consent.Lastname, r.RemoteAddr) } // PostConsent godoc +// // @Summary Create a new consent // @Description Create a new consent // @Tags consent @@ -114,7 +117,7 @@ func (dh *DataHandler) PostConsent(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(consent) @@ -122,6 +125,7 @@ func (dh *DataHandler) PostConsent(w http.ResponseWriter, r *http.Request) { } // UpdateConsent godoc +// // @Summary Update a consent, giving it a serviceID // @Description Update a consent, giving it a serviceID // @Tags consent @@ -173,13 +177,14 @@ func (dh *DataHandler) UpdateConsent(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(consent) log.Printf("| updated consent | name : %v | serviceID : %v | %v", consent.Lastname, consent.ServiceID, r.RemoteAddr) } // DeleteConsentById godoc +// // @Summary Delete a specific consent // @Description Delete a specific consent // @Tags consent @@ -219,6 +224,7 @@ func (dh *DataHandler) DeleteConsentById(w http.ResponseWriter, r *http.Request) } // SearchConsent godoc +// // @Summary Search for consents // @Description Search for consents based on the pointID // @Tags consent @@ -250,7 +256,7 @@ func (dh *DataHandler) SearchConsent(w http.ResponseWriter, r *http.Request) { pagination.TotalRows = totalRows pagination.Rows = consents - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(pagination) log.Printf("| get all consents | limit : %d | page : %d | %v", limit, page, r.RemoteAddr) diff --git a/internal/models/customPopup.go b/internal/models/customPopup.go index 6e3dd2732ead6106a651fa1d2061967ac7d69b37..79b8f6cd6e5dd4ae3c70c1244384a49bb3d2b095 100644 --- a/internal/models/customPopup.go +++ b/internal/models/customPopup.go @@ -7,6 +7,7 @@ import ( "net/http" "time" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" "gorm.io/gorm" ) @@ -19,6 +20,7 @@ type CustomPopup struct { } // GetCustomPopup godoc +// // @Summary Give status of custom popup // @Description Give status of custom poup // @Tags customPopup @@ -35,12 +37,13 @@ func (dh *DataHandler) GetCustomPopup(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(popupInfo) log.Printf("| get customPopup | %v", r.RemoteAddr) } // SaveCustomPopup godoc +// // @Summary Update custom popup content // @Description Update custom popup content // @Tags customPopup @@ -80,7 +83,7 @@ func (dh *DataHandler) SaveCustomPopup(w http.ResponseWriter, r *http.Request) { dh.sqlClient.Save(&updatedCustomPopup) - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(customPopup) log.Printf("| updated customPopup | %v", r.RemoteAddr) } diff --git a/internal/models/mailSubject.go b/internal/models/mailSubject.go index c3005a2f841a27b0c0166caddbd13e3f9eb4277d..b0c5f6cf7370a7190e861fb7051bff622495fee5 100644 --- a/internal/models/mailSubject.go +++ b/internal/models/mailSubject.go @@ -6,6 +6,7 @@ import ( "net/http" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" ) type MailSubject struct { @@ -15,6 +16,7 @@ type MailSubject struct { } // GetSingleMailSubject godoc +// // @Summary Get details of a specific mailSubject // @Description Get details of a specific mailSubject // @Tags mailSubject @@ -31,7 +33,7 @@ func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Reque return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) var mailSubject MailSubject err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&mailSubject).Error @@ -44,6 +46,7 @@ func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Reque } // SaveMailSubject godoc +// // @Summary Create/update a specific mailSubject' content // @Description Create/update a specific mailSubject' content // @Tags mailSubject @@ -103,6 +106,7 @@ func (dh *DataHandler) SaveMailSubject(w http.ResponseWriter, r *http.Request) { } // DeleteMailSubject godoc +// // @Summary Delete a specific mailSubject // @Description Delete a specific mailSubject // @Tags mailSubject diff --git a/internal/models/monthlyInfo.go b/internal/models/monthlyInfo.go index 971c9c5f1817b2390b20f350f4b93a2d912607b5..3d98125e950a7a6729f1ea819dfe3ec64152ccc7 100644 --- a/internal/models/monthlyInfo.go +++ b/internal/models/monthlyInfo.go @@ -6,6 +6,7 @@ import ( "net/http" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" ) type MonthlyInfo struct { @@ -16,6 +17,7 @@ type MonthlyInfo struct { } // GetAllMonthlyInfo godoc +// // @Summary List all monthlyInfo // @Description Get details of all monthlyInfo // @Tags monthlyInfo @@ -26,12 +28,13 @@ func (dh *DataHandler) GetAllMonthlyInfo(w http.ResponseWriter, r *http.Request) var monthlyInfo []MonthlyInfo dh.sqlClient.Find(&monthlyInfo) - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(monthlyInfo) log.Printf("| get all monthlyInfo | %v", r.RemoteAddr) } // GetSingleMonthlyInfo godoc +// // @Summary Get details of a specific monthlyInfo // @Description Get details of a specific monthlyInfo // @Tags monthlyInfo @@ -48,7 +51,7 @@ func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Reque return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) var monthlyInfo MonthlyInfo err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&monthlyInfo).Error @@ -61,6 +64,7 @@ func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Reque } // SaveMonthlyInfo godoc +// // @Summary Create/update a specific monthlyInfo' content // @Description Create/update a specific monthlyInfo' content // @Tags monthlyInfo @@ -128,6 +132,7 @@ func (dh *DataHandler) SaveMonthlyInfo(w http.ResponseWriter, r *http.Request) { } // DeleteMonthlyInfo godoc +// // @Summary Delete a specific monthlyInfo // @Description Delete a specific monthlyInfo // @Tags monthlyInfo diff --git a/internal/models/monthlyNews.go b/internal/models/monthlyNews.go index 9bdfdb8dccc79d8d987a558dca771e9463af2be6..9b687f144e860877ef966191ae554b32f198d4a2 100644 --- a/internal/models/monthlyNews.go +++ b/internal/models/monthlyNews.go @@ -6,6 +6,7 @@ import ( "net/http" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" ) type MonthlyNews struct { @@ -16,6 +17,7 @@ type MonthlyNews struct { } // GetAllMonthlyNews godoc +// // @Summary List all monthlyNews // @Description Get details of all monthlyNews // @Tags monthlyNews @@ -26,12 +28,13 @@ func (dh *DataHandler) GetAllMonthlyNews(w http.ResponseWriter, r *http.Request) var monthlyNews []MonthlyNews dh.sqlClient.Find(&monthlyNews) - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(monthlyNews) log.Printf("| get all monthlyNews | %v", r.RemoteAddr) } // GetSingleMonthlyNews godoc +// // @Summary Get details of a specific monthlyNews // @Description Get details of a specific monthlyNews // @Tags monthlyNews @@ -48,7 +51,7 @@ func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Reque return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) var monthlyNews MonthlyNews err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&monthlyNews).Error @@ -61,6 +64,7 @@ func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Reque } // SaveMonthlyNews godoc +// // @Summary Create/update a specific monthlyNews' content // @Description Create/update a specific monthlyNews' content // @Tags monthlyNews @@ -128,6 +132,7 @@ func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) { } // DeleteMonthlyNews godoc +// // @Summary Delete a specific monthlyNews // @Description Delete a specific monthlyNews // @Tags monthlyNews diff --git a/internal/models/monthlyReport.go b/internal/models/monthlyReport.go index c5df9c1a349ddee50174f3e04391a3e5db0e5860..136a9b463d25908a708f82a0686e63512bea6716 100644 --- a/internal/models/monthlyReport.go +++ b/internal/models/monthlyReport.go @@ -5,6 +5,8 @@ import ( "fmt" "net/http" "strconv" + + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" ) type MonthlyReport struct { @@ -20,6 +22,7 @@ type MonthlyReport struct { } // GetMonthlyReport godoc +// // @Summary Get details of a specific monthlyReport // @Description Get details of a specific monthlyReport // @Tags monthlyReport @@ -48,7 +51,7 @@ func (dh *DataHandler) GetMonthlyReport(w http.ResponseWriter, r *http.Request) return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(monthlyReport) } diff --git a/internal/models/partnersInfo.go b/internal/models/partnersInfo.go index cdea10aec1770bbba1051ccb1bfd934d8560a007..7d0b58c4515e85ab588f354170fc2d396fcc4739 100644 --- a/internal/models/partnersInfo.go +++ b/internal/models/partnersInfo.go @@ -6,6 +6,7 @@ import ( "log" "net/http" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" "gorm.io/gorm" ) @@ -18,6 +19,7 @@ type PartnersInfo struct { } // GetPartnersInfo godoc +// // @Summary Give status of partners' services // @Description Give status of partners' services // @Tags partnersInfo @@ -34,12 +36,13 @@ func (dh *DataHandler) GetPartnersInfo(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.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 @@ -79,7 +82,7 @@ func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request) dh.sqlClient.Save(&updatedPartnersInfo) - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(partnersInfo) log.Printf("| updated partnersInfo | %v", r.RemoteAddr) diff --git a/internal/models/poll.go b/internal/models/poll.go index 76683a20660ebd17f3b2ae1259062c5aefd636b4..e046ee5839e031633ad46c941ec801e51b4c952b 100644 --- a/internal/models/poll.go +++ b/internal/models/poll.go @@ -6,6 +6,7 @@ import ( "net/http" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" ) type Poll struct { @@ -16,6 +17,7 @@ type Poll struct { } // GetAllPolls godoc +// // @Summary List all polls // @Description Get details of all polls // @Tags poll @@ -30,12 +32,13 @@ func (dh *DataHandler) GetAllPolls(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(polls) log.Printf("| get all polls | %v", r.RemoteAddr) } // GetSinglePoll godoc +// // @Summary Get details of a specific poll // @Description Get details of a specific poll // @Tags poll @@ -52,7 +55,7 @@ func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) var poll Poll err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&poll).Error @@ -65,6 +68,7 @@ func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) { } // SavePoll godoc +// // @Summary Update a specific poll' content // @Description Update a specific poll' content // @Tags poll @@ -125,6 +129,7 @@ func (dh *DataHandler) SavePoll(w http.ResponseWriter, r *http.Request) { } // DeletePoll godoc +// // @Summary Delete a specific poll // @Description Delete a specific poll // @Tags poll diff --git a/internal/models/price.go b/internal/models/price.go index 5503bf185fe55ec3d83bfad7709ba529fb7b9a3c..c0c59d127d9263587d2eb20bf7170f027c99f143 100644 --- a/internal/models/price.go +++ b/internal/models/price.go @@ -7,6 +7,7 @@ import ( "time" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common" + "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants" "gorm.io/gorm" ) @@ -19,6 +20,7 @@ type Price struct { } // GetPrices godoc +// // @Summary Get all prices // @Description Get all prices // @Tags prices @@ -30,12 +32,13 @@ func (dh *DataHandler) GetAllPrices(w http.ResponseWriter, r *http.Request) { var prices []Price dh.sqlClient.Find(&prices) - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(prices) log.Printf("| Get all prices | %v", r.RemoteAddr) } // GetPricesByFluid godoc +// // @Summary Get all prices for a given fluid // @Description Get all prices for a given fluid // @Tags prices @@ -51,7 +54,7 @@ func (dh *DataHandler) GetPricesByFluid(w http.ResponseWriter, r *http.Request) return } var price []Price - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) err = dh.sqlClient.Where("fluid_type = ? ", fluidtype).Order("start_date desc").Find(&price).Error if err != nil { @@ -63,6 +66,7 @@ func (dh *DataHandler) GetPricesByFluid(w http.ResponseWriter, r *http.Request) } // SavePrice godoc +// // @Summary Add a new price entry // @Description Add a new price entry // @Tags prices @@ -143,9 +147,9 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) { } } - if isEditable == false { + if !isEditable { w.WriteHeader(http.StatusForbidden) - log.Printf("Unallowed to edit price because is not included in the the last 3 editable prices") + log.Printf("Unauthorized to edit price because is not included in the the last 3 editable prices") return } // Update existing price @@ -155,7 +159,7 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") + w.Header().Set(constants.ContentType, constants.Json) json.NewEncoder(w).Encode(priceToUpdate) log.Printf("| Updated price | fluidType : %d price : %v | startDate : %v | %v", priceToUpdate.FluidType, priceToUpdate.Price, priceToUpdate.StartDate, r.RemoteAddr) } diff --git a/internal/rootmux/rootmux.go b/internal/rootmux/rootmux.go index 04e185c7d855b939f47234e24a144650da8a3d59..1d572e9fcab8fbaf61a1b4959c7632aee3848436 100644 --- a/internal/rootmux/rootmux.go +++ b/internal/rootmux/rootmux.go @@ -91,7 +91,7 @@ func CreateRootMux() RootMux { r.Delete("/consent/{id}", dh.DeleteConsentById) }) - r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {}) + r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { /** handles Oauth2 redirection */ }) swaggerFs := http.FileServer(http.Dir("./docs/")) r.Handle("/doc/*", http.StripPrefix("/doc/", swaggerFs)) diff --git a/internal/rootmux/rootmux_test.go b/internal/rootmux/rootmux_test.go index 9d86529c154af8225060079782a35c89b82b3433..5370dbaf074e88240ccfc543911ea28e0962a083 100644 --- a/internal/rootmux/rootmux_test.go +++ b/internal/rootmux/rootmux_test.go @@ -16,6 +16,14 @@ import ( "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/tokens" ) +const ( + SuccessfullDelete = "successful delete" + ErrorExtractingToken = "error extracting token" + ErrorInvalidToken = "invalid token" + ErrorEmptyBody = "request body is empty" + ErrorXSRF = "XSRF protection triggered" +) + var ( oAuth2Server *httptest.Server mailSubject = models.MailSubject{Year: 2021, Month: 1, Subject: "[Ecolyo] Newsletter"} @@ -90,7 +98,7 @@ func TestAll(t *testing.T) { os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth-wrong-state") // Set the server to access failing OAuth2 endpoints oauth2Tests(t) os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth") // Set the server to access the correct OAuth2Endpoint - unloggedTests(t) + noAuthTests(t) os.Setenv("USERINFO_URL", oAuth2Server.URL+"/animatorinfo") animatorTests(t) os.Setenv("USERINFO_URL", oAuth2Server.URL+"/admininfo") @@ -112,16 +120,16 @@ func oauth2Tests(t *testing.T) { /* * -UNLOGGED USER TESTS (this tests are to check that the security protections works) +NO AUTH USER TESTS (this tests are to check that the security protections works) * */ -func unloggedTests(t *testing.T) { +func noAuthTests(t *testing.T) { // Create the tester ts, do, _ := createTester(t) defer ts.Close() // Close the tester // Try to create a monthlyNews (must fail) - do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "error extracting token") + do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, ErrorExtractingToken) // 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 pass empty) @@ -146,9 +154,9 @@ func animatorTests(t *testing.T) { json.Unmarshal([]byte(response), &token) xsrfHeader := map[string]string{"XSRF-TOKEN": token.XSRFToken} // Try to create a monthlyNews without the XSRF-TOKEN (must fail) - do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "XSRF protection triggered") + do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, ErrorXSRF) // Try to create a monthlyNews without body (must fail) - do("PUT", "/api/animator/monthlyNews", xsrfHeader, "", http.StatusBadRequest, "request body is empty") + do("PUT", "/api/animator/monthlyNews", xsrfHeader, "", http.StatusBadRequest, ErrorEmptyBody) // Try to get a monthlyNews before it is created (must fail because not found) do("GET", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusNotFound, "") // Try to create a monthlyNews (must pass) @@ -161,9 +169,9 @@ func animatorTests(t *testing.T) { do("GET", "/api/common/monthlyReport?year=2021&month=1", noH, "", http.StatusOK, `{"year":2021,"month":1,"subject":"[Ecolyo] Votre bilan de décembre 2020","info":"","image":"","newsTitle":"Les nouveautés du service","newsContent":"Nouvelles fonctionnalités","question":"","link":""}`) // Try to create a poll without the XSRF-TOKEN (must fail) - do("PUT", "/api/animator/poll", noH, newPollStr, http.StatusUnauthorized, "XSRF protection triggered") + do("PUT", "/api/animator/poll", noH, newPollStr, http.StatusUnauthorized, ErrorXSRF) // Try to create a poll without body (must fail) - do("PUT", "/api/animator/poll", xsrfHeader, "", http.StatusBadRequest, "request body is empty") + do("PUT", "/api/animator/poll", xsrfHeader, "", http.StatusBadRequest, ErrorEmptyBody) // Try to get a poll before it is created (must fail because not found') do("GET", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusNotFound, "") // Try to create a poll (must pass) @@ -176,9 +184,9 @@ func animatorTests(t *testing.T) { do("GET", "/api/common/monthlyReport?year=2021&month=1", noH, "", http.StatusOK, `{"year":2021,"month":1,"subject":"[Ecolyo] Votre bilan de décembre 2020","info":"","image":"","newsTitle":"Les nouveautés du service","newsContent":"Nouvelles fonctionnalités","question":"pollQuestion","link":"pollLink"}`) // Try to create a monthlyInfo without the XSRF-TOKEN (must fail) - do("PUT", "/api/animator/monthlyInfo", noH, monthlyInfoStr, http.StatusUnauthorized, "XSRF protection triggered") + do("PUT", "/api/animator/monthlyInfo", noH, monthlyInfoStr, http.StatusUnauthorized, ErrorXSRF) // Try to create a monthlyInfo without body (must fail) - do("PUT", "/api/animator/monthlyInfo", xsrfHeader, "", http.StatusBadRequest, "request body is empty") + do("PUT", "/api/animator/monthlyInfo", xsrfHeader, "", http.StatusBadRequest, ErrorEmptyBody) // Try to get a monthlyInfo before it is created (must fail because not found) do("GET", "/api/animator/monthlyInfo/2021/1", xsrfHeader, "", http.StatusNotFound, "") // Try to create a monthlyInfo (must pass) @@ -201,7 +209,7 @@ func animatorTests(t *testing.T) { do("GET", "/api/common/customPopup", xsrfHeader, "", http.StatusOK, customPopupStr) // Try to delete the monthlyNews created (must pass) - do("DELETE", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusOK, "successful delete") + do("DELETE", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusOK, SuccessfullDelete) // Try to get a monthlyNews after it is deleted (must fail because not found) do("GET", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusNotFound, "") @@ -210,14 +218,14 @@ func animatorTests(t *testing.T) { // Try to get the monthlyReport (must pass) do("GET", "/api/common/monthlyReport?year=2021&month=1", noH, "", http.StatusOK, `{"year":2021,"month":1,"subject":"[Ecolyo] Newsletter","info":"Informations du mois","image":"imagebase64","newsTitle":"","newsContent":"","question":"pollQuestion","link":"pollLink"`) // Try to delete the poll created (must pass) - do("DELETE", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusOK, "successful delete") + do("DELETE", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusOK, SuccessfullDelete) // Try to get a poll after it is deleted (must fail because not found) do("GET", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusNotFound, "") // Try to get the monthlyReport (must pass) do("GET", "/api/common/monthlyReport?year=2021&month=1", noH, "", http.StatusOK, `{"year":2021,"month":1,"subject":"[Ecolyo] Newsletter","info":"Informations du mois","image":"imagebase64","newsTitle":"","newsContent":"","question":"","link":""`) // Try to delete the mail subject created (must pass) - do("DELETE", "/api/animator/mailSubject/2021/1", xsrfHeader, "", http.StatusOK, "successful delete") + do("DELETE", "/api/animator/mailSubject/2021/1", xsrfHeader, "", http.StatusOK, SuccessfullDelete) // Try to get a mail subject after it is deleted (must fail because not found) do("GET", "/api/animator/mailSubject/2021/1", xsrfHeader, "", http.StatusNotFound, "") // Try to get the monthlyReport (must pass) @@ -233,9 +241,9 @@ func animatorTests(t *testing.T) { // Try to logout (must pass) do("GET", "/Logout", noH, "", http.StatusOK, "") // Try to get a monthlyNews again (must fail) - do("GET", "/api/animator/monthlyNews", noH, "", http.StatusUnauthorized, "error extracting token") + do("GET", "/api/animator/monthlyNews", noH, "", http.StatusUnauthorized, ErrorExtractingToken) // Try to get a poll again (must fail) - do("GET", "/api/animator/poll", noH, "", http.StatusUnauthorized, "error extracting token") + do("GET", "/api/animator/poll", noH, "", http.StatusUnauthorized, ErrorExtractingToken) } @@ -257,7 +265,7 @@ func adminTests(t *testing.T) { // Try to logout (must pass) do("GET", "/Logout", noH, "", http.StatusOK, "") // Try to get SGE consents again (must fail) - do("GET", "/api/admin/consent?limit=50&page=0", xsrfHeader, "", http.StatusUnauthorized, "error extracting token") + do("GET", "/api/admin/consent?limit=50&page=0", xsrfHeader, "", http.StatusUnauthorized, ErrorExtractingToken) } func sgeTests(t *testing.T) { @@ -265,13 +273,13 @@ func sgeTests(t *testing.T) { ts, do, _ := createTester(t) defer ts.Close() // Close the tester // Try to create a consent (must fail) - do("POST", "/api/sge/consent", noH, consentStr, http.StatusUnauthorized, "invalid token") + do("POST", "/api/sge/consent", noH, consentStr, http.StatusUnauthorized, ErrorInvalidToken) // Try to get a consent (must fail) - do("GET", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token") + do("GET", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, ErrorInvalidToken) // Try to update a consent (must fail) - do("PUT", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token") + do("PUT", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, ErrorInvalidToken) // Try to delete a consent (must fail) - do("DELETE", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token") + do("DELETE", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, ErrorInvalidToken) // Create correct authorization header sgeApiHeader := map[string]string{"Authorization": "Bearer " + auth.SGEApiToken} diff --git a/internal/tester/tester.go b/internal/tester/tester.go index d7c6a6739062d632843205b3a7de13ef13795618..51a9e80cc59c76c733728d6df4c14a648142a266 100644 --- a/internal/tester/tester.go +++ b/internal/tester/tester.go @@ -6,7 +6,6 @@ import ( "net" "net/http" "net/http/cookiejar" - "net/http/httptest" "net/url" "strings" "testing" @@ -15,26 +14,6 @@ import ( type DoFn func(method string, url string, headers map[string]string, payload string, expectedStatus int, expectedBody string) string -// DoRequestOnHandler does a request on a router (or handler) and check the response -func DoRequestOnHandler(t *testing.T, router http.Handler, method string, route string, headers map[string]string, payload string, expectedStatus int, expectedBody string) string { - req, err := http.NewRequest(method, route, strings.NewReader(payload)) - if err != nil { - t.Fatal(err) - } - for i, v := range headers { - req.Header.Set(i, v) - } - rr := httptest.NewRecorder() - router.ServeHTTP(rr, req) - if status := rr.Code; status != expectedStatus { - t.Errorf("Tested %v %v %v ; handler returned wrong status code: got %v want %v", method, route, payload, status, expectedStatus) - } - if !strings.HasPrefix(rr.Body.String(), expectedBody) { - t.Errorf("Tested %v %v %v ; handler returned unexpected body: got %v want %v", method, route, payload, rr.Body.String(), expectedBody) - } - return string(rr.Body.String()) -} - // DoRequestOnServer does a request on listening server func DoRequestOnServer(t *testing.T, hostname string, port string, jar *cookiejar.Jar, method string, testURL string, headers map[string]string, payload string, expectedStatus int, expectedBody string) string { dialer := &net.Dialer{