Skip to content
Snippets Groups Projects
Commit f0fb5066 authored by Rémi PAILHAREY's avatar Rémi PAILHAREY :fork_knife_plate:
Browse files

Merge branch 'dev' into 'master'

MEP animator role

See merge request !85
parents 1d026538 71de4789
Branches
No related tags found
1 merge request!85MEP animator role
Pipeline #72278 passed
Showing
with 121 additions and 261 deletions
# Common settings # Common settings
HOSTNAME=localhost HOSTNAME=localhost
ADMIN_ROLE ANIMATOR_ROLE=ANIMATORS
ADMIN_ROLE=ADMINS
DEBUG_MODE DEBUG_MODE
MOCK_OAUTH2 MOCK_OAUTH2
HTTPS_PORT HTTPS_PORT
......
| :triangular_flag_on_post: Give your MR the same name that the desired squash commit. In doubt, check the conventional commit [doc](https://www.conventionalcommits.org/en/v1.0.0/).| # Related to #000
| :triangular_flag_on_post: Give your MR title the same name that the desired squash commit. In doubt, check the conventional commit [doc][conventional-commits]. examples |
| --- | | --- |
| **feat(profile)**: add... |
| **fix(annuaire)**: remove... |
## What does this MR do and why? ## What does this MR do and why?
_Describe in detail what your merge request does and why._ _Describe in detail what your merge request does and why._
| :warning: Keep an up to date checklist based on your icescrum tasks during all the draft phase of the MR to help any other developer who would take the job after you to finish it.|
| --- |
## Screenshots or screen recordings ## Screenshots or screen recordings
_These are strongly recommended to assist reviewers and reduce the time to merge your change._ _These are strongly recommended to assist reviewers and reduce the time to merge your change._
## How to set up and validate locally (or on alpha) ## How to set up and validate locally (or on alpha)
_List all steps to set up and validate the changes on local environment._ _List all steps to set up and validate the changes on local environment._
## MR acceptance checklist ## MR acceptance checklist
_To be completed by the chosen reviewer._ _To be completed by the chosen reviewer._
<!--- <!---
...@@ -27,39 +28,30 @@ More reading on checklists can be found in the "Checklist Manifesto": http://atu ...@@ -27,39 +28,30 @@ More reading on checklists can be found in the "Checklist Manifesto": http://atu
"It is common to misconceive how checklists function in complex lines of work. They are not comprehensive how-to guides, whether for building a skyscraper or getting a plane out of trouble. They are quick and simple tools aimed to buttress the skills of expert professionals." - Gawande, Atul. The Checklist Manifesto "It is common to misconceive how checklists function in complex lines of work. They are not comprehensive how-to guides, whether for building a skyscraper or getting a plane out of trouble. They are quick and simple tools aimed to buttress the skills of expert professionals." - Gawande, Atul. The Checklist Manifesto
---> --->
### Quality [![Bugs](https://sonarqube.forge.grandlyon.com/api/project_badges/measure?project=ecolyo-agent-server-mr&metric=bugs&token=sqb_58fbbe7daac77dc42eed3e144532aaa6176d11ba)](https://sonarqube.forge.grandlyon.com/dashboard?id=ecolyo-agent-server-mr) [![Code Smells](https://sonarqube.forge.grandlyon.com/api/project_badges/measure?project=ecolyo-agent-server-mr&metric=code_smells&token=sqb_58fbbe7daac77dc42eed3e144532aaa6176d11ba)](https://sonarqube.forge.grandlyon.com/dashboard?id=ecolyo-agent-server-mr)
### Quality - For the code that this change impacts, I believe that the **automated tests validate functionality** that is **highly important to users**. If the existing automated tests do not cover this functionality, I have **added the necessary additional tests** or I have added an issue to describe the automation testing gap and linked it to this MR.
- I have made sure that the **sonar quality coverage is up to standards**.
* [ ] Confirmed - I have **considered the impact** of this change on the **front-end**, **back-end**, and **database** portions of the system where appropriate and applied.
- I have tested this MR in **all supported browsers** or determined that this testing is not needed.
1. For the code that this change impacts, I believe that the automated tests validate functionality that is highly important to users. If the existing automated tests do not cover this functionality, I have added the necessary additional tests or I have added an issue to describe the automation testing gap and linked it to this MR. - I have confirmed that this change is **backwards compatible** across updates (migrate up needs a migrate down), or I have decided that this does not apply.
1. I have made sure that the sonar quality coverage is up to standards.
1. I have considered the impact of this change on the front-end, back-end, and database portions of the system where appropriate and applied.
1. I have tested this MR in all supported browsers or determined that this testing is not needed.
1. I have confirmed that this change is backwards compatible across updates (migrate up needs a migrate down), or I have decided that this does not apply.
### Performance, reliability and availability ### Performance, reliability and availability
* [ ] Confirmed - I am confident that this MR **does not harm performance**, or I have asked a reviewer to help assess the performance impact.
- I have considered the **scalability risk** based on future predicted growth.
1. I am confident that this MR does not harm performance, or I have asked a reviewer to help assess the performance impact.
1. I have considered the scalability risk based on future predicted growth.
### Documentation ### Documentation
* [ ] Confirmed - The MR is named after the **desired squash commit** to feed the changelog linked to the current milestone.
- I have **added/updated documentation** (also updated if the changes feature a deprecation) or I have decided that documentation changes are not needed for this MR.
1. The MR is named after the desired squash commit to feed the changelog linked to the current milestone.
1. I have added/updated documentation (also updated if the changes feature a deprecation) or I have decided that documentation changes are not needed for this MR.
### Security
* [ ] Confirmed ### Security [![Security Rating](https://sonarqube.forge.grandlyon.com/api/project_badges/measure?project=ecolyo-agent-server-mr&metric=security_rating&token=sqb_58fbbe7daac77dc42eed3e144532aaa6176d11ba)](https://sonarqube.forge.grandlyon.com/dashboard?id=ecolyo-agent-server-mr)
1. I have confirmed that if this MR does not contains any sensitive informations hidden in the changes. - I have confirmed that if this MR **does not contains any sensitive informations** hidden in the changes.
### Deployment ### Deployment
* [ ] Confirmed - When featured on a self-data project release, I have made sure my **app version** in the manifest and package.json is **incremented** and any relative **changes to the permissions are clearly written and transmitted to Cozy**.
1. When featured on a self-data project release, i have made sure my app version in the manifest and package.json is incremented and any relative changes to the permissions are clearly written and transmitted to Cozy. [conventional-commits]: https://www.conventionalcommits.org/en/v1.0.0/
{
// Utilisez IntelliSense pour en savoir plus sur les attributs possibles.
// Pointez pour afficher la description des attributs existants.
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug Back-office with Mock OAuth2",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/main.go",
"envFile": "${workspaceFolder}/.env",
"showLog": true
},
{
"name": "Debug Back-office with Sign&Go",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/main.go",
"env": {
"REDIRECT_URL": "https://localhost:1443/OAuth2Callback",
"CLIENT_ID": "<GET ONE FROM YOUR IDP>",
"CLIENT_SECRET": "<GET ONE FROM YOUR IDP>",
"AUTH_URL": "https://connexion-rec.grandlyon.fr/IdPOAuth2/authorize/oidc-rec",
"TOKEN_URL": "https://connexion-rec.grandlyon.fr/IdPOAuth2/token/oidc-rec",
"USERINFO_URL": "https://connexion-rec.grandlyon.fr/IdPOAuth2/userinfo/oidc-rec",
"LOGOUT_URL": "https://connexion-rec.grandlyon.fr/auth/logout.jsp",
"ADMIN_ROLE": "GGD_ORG_DG-DEES-DINSI-DAAG_TOUS",
"HOSTNAME": "ecolyobackoffice.127.0.0.1.nip.io",
"DEBUG_MODE": "true",
"HTTPS_PORT": "1443"
},
"showLog": true
}
]
}
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
}, },
"peacock.color": "#32f0ff", "peacock.color": "#32f0ff",
"cSpell.words": [ "cSpell.words": [
"admininfo",
"animatorinfo",
"backoffice", "backoffice",
"ecogesture", "ecogesture",
"ecolyo", "ecolyo",
......
version: '3.7'
services:
database-agent:
image: mysql:8
networks:
backoffice:
restart: always
volumes:
- /mnt/local/data/ecolyo_agent_mysql_data:/var/lib/mysql
- ./dbinit:/dbinit
environment:
MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
MYSQL_DATABASE: ${DATABASE_NAME}
healthcheck:
test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD
interval: 5s
timeout: 10s
retries: 60
backend:
image: registry.forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server:dev
networks:
backoffice:
nginx-network:
depends_on:
database-agent:
condition: service_healthy
restart: unless-stopped
volumes:
- /etc/localtime:/etc/localtime:ro
- ./configs:/app/configs
- ./letsencrypt_cache:/app/letsencrypt_cache
- ./data:/app/data
- ./${IMAGE_FOLDER}:/app/${IMAGE_FOLDER}
expose:
- ${HTTPS_PORT}
environment:
- HOSTNAME=${HOSTNAME}
- HTTPS_PORT=${HTTPS_PORT}
- ADMIN_ROLE=${ADMIN_ROLE}
- REDIRECT_URL=${REDIRECT_URL}
- CLIENT_ID=${CLIENT_ID}
- CLIENT_SECRET=${CLIENT_SECRET}
- AUTH_URL=${AUTH_URL}
- IMAGE_FOLDER=${IMAGE_FOLDER}
- MOCK_OAUTH2=${MOCK_OAUTH2}
- TOKEN_URL=${TOKEN_URL}
- USERINFO_URL=${USERINFO_URL}
- DEBUG_MODE=${DEBUG_MODE}
- DATABASE_USER=${DATABASE_USER}
- DATABASE_NAME=${DATABASE_NAME}
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
- DATABASE_HOST=database-agent
networks:
backoffice:
nginx-network:
external: true
\ No newline at end of file
...@@ -7,9 +7,7 @@ import ( ...@@ -7,9 +7,7 @@ import (
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"os"
"strings" "strings"
"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/common"
"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/tokens" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/tokens"
...@@ -24,6 +22,7 @@ const ( ...@@ -24,6 +22,7 @@ const (
) )
var ( var (
AnimatorRole = common.StringValueFromEnv("ANIMATOR_ROLE", "ANIMATORS")
// AdminRole represents the role reserved for admins // AdminRole represents the role reserved for admins
AdminRole = common.StringValueFromEnv("ADMIN_ROLE", "ADMINS") AdminRole = common.StringValueFromEnv("ADMIN_ROLE", "ADMINS")
hostname = common.StringValueFromEnv("HOSTNAME", "ecolyobackoffice.127.0.0.1.nip.io") hostname = common.StringValueFromEnv("HOSTNAME", "ecolyobackoffice.127.0.0.1.nip.io")
...@@ -53,12 +52,12 @@ type TokenData struct { ...@@ -53,12 +52,12 @@ type TokenData struct {
XSRFToken string `json:"xsrftoken,omitempty"` XSRFToken string `json:"xsrftoken,omitempty"`
} }
func AdminAuthMiddleware(next http.Handler) http.Handler { func AnimatorAuthMiddleware(next http.Handler) http.Handler {
return ValidateAuthMiddleware(next, []string{os.Getenv("ADMIN_ROLE")}, true) return ValidateAuthMiddleware(next, []string{AdminRole, AnimatorRole}, true)
} }
func CommonAuthMiddleware(next http.Handler) http.Handler { func AdminAuthMiddleware(next http.Handler) http.Handler {
return ValidateAuthMiddleware(next, []string{"*"}, false) return ValidateAuthMiddleware(next, []string{AdminRole}, true)
} }
// ValidateAuthMiddleware validates that the token is valid and that the user has the correct roles // ValidateAuthMiddleware validates that the token is valid and that the user has the correct roles
...@@ -169,45 +168,6 @@ func checkUserHasRole(user TokenData, allowedRoles []string) error { ...@@ -169,45 +168,6 @@ func checkUserHasRole(user TokenData, allowedRoles []string) error {
return fmt.Errorf("no user role among %v is in allowed roles (%v)", user.Roles, allowedRoles) return fmt.Errorf("no user role among %v is in allowed roles (%v)", user.Roles, allowedRoles)
} }
//GetShareToken gets a share token for a given ressource
func GetShareToken(w http.ResponseWriter, r *http.Request) {
user, err := GetTokenData(r)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
var wantedToken struct {
Sharedfor string `json:"sharedfor"`
URL string `json:"url"`
Lifespan int `json:"lifespan"`
ReadOnly bool `json:"readonly,omitempty"`
}
err = json.NewDecoder(r.Body).Decode(&wantedToken)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if wantedToken.URL == "" {
http.Error(w, "url cannot be empty", http.StatusBadRequest)
return
}
user.Login = user.Login + "_share_for_" + wantedToken.Sharedfor
user.URL = wantedToken.URL
user.ReadOnly = wantedToken.ReadOnly
user.SharingUserLogin = wantedToken.Sharedfor
token, err := tokens.CreateToken(user, time.Now().Add(time.Hour*time.Duration(24*wantedToken.Lifespan)))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
fmt.Fprint(w, token)
}
// GetTokenData gets an user from a request // GetTokenData gets an user from a request
func GetTokenData(r *http.Request) (TokenData, error) { func GetTokenData(r *http.Request) (TokenData, error) {
user, ok := r.Context().Value(ContextData).(TokenData) user, ok := r.Context().Value(ContextData).(TokenData)
...@@ -216,13 +176,3 @@ func GetTokenData(r *http.Request) (TokenData, error) { ...@@ -216,13 +176,3 @@ func GetTokenData(r *http.Request) (TokenData, error) {
} }
return user, nil return user, nil
} }
// isWebdav works out if an user agent is a webdav user agent
func isWebdav(ua string) bool {
for _, a := range []string{"vfs", "Microsoft-WebDAV", "Konqueror", "LibreOffice", "Rei.Fs.WebDAV"} {
if strings.Contains(ua, a) {
return true
}
}
return false
}
...@@ -127,7 +127,7 @@ func (m Manager) HandleOAuth2Callback() http.Handler { ...@@ -127,7 +127,7 @@ func (m Manager) HandleOAuth2Callback() http.Handler {
} }
// Check if user has the correct role // Check if user has the correct role
err = checkUserHasRole(TokenData{User: user}, []string{AdminRole}) err = checkUserHasRole(TokenData{User: user}, []string{AdminRole, AnimatorRole})
if err != nil { if err != nil {
// Log the connexion attempt // Log the connexion attempt
......
...@@ -36,17 +36,17 @@ func CreateMockOAuth2() *http.ServeMux { ...@@ -36,17 +36,17 @@ func CreateMockOAuth2() *http.ServeMux {
w.Header().Set("Content-Type", "application/x-www-form-urlencoded") w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
w.Write([]byte("access_token=mocktoken&scope=user&token_type=bearer")) w.Write([]byte("access_token=mocktoken&scope=user&token_type=bearer"))
}) })
// Returns userinfo back to the user // Returns userinfo back to the user (with an animator user)
mux.HandleFunc("/userinfo", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/animatorinfo", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{ w.Write([]byte(`{
"displayName": "Us ER", "displayName": "Anim Ator",
"memberOf": [ "memberOf": [
"CN=USERS", "CN=ANIMATORS",
"CN=OTHER_GROUP" "CN=OTHER_GROUP"
], ],
"id": "1000", "id": "1000",
"login": "USER" "login": "ANIMATOR"
}`)) }`))
}) })
// Returns userinfo back to the user (with an admin user) // Returns userinfo back to the user (with an admin user)
......
...@@ -50,7 +50,7 @@ func (dh *DataHandler) GetCustomPopup(w http.ResponseWriter, r *http.Request) { ...@@ -50,7 +50,7 @@ func (dh *DataHandler) GetCustomPopup(w http.ResponseWriter, r *http.Request) {
// @Failure 400 {string} string "Bad Request" // @Failure 400 {string} string "Bad Request"
// @Failure 500 {string} string "Internal server error" // @Failure 500 {string} string "Internal server error"
// @Param customPopup body CustomPopup true "CustomPopup to create/update with new content" // @Param customPopup body CustomPopup true "CustomPopup to create/update with new content"
// @Router /api/admin/customPopup [put] // @Router /api/animator/customPopup [put]
func (dh *DataHandler) SaveCustomPopup(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) SaveCustomPopup(w http.ResponseWriter, r *http.Request) {
if r.Body == http.NoBody { if r.Body == http.NoBody {
http.Error(w, "request body is empty", http.StatusBadRequest) http.Error(w, "request body is empty", http.StatusBadRequest)
......
...@@ -23,7 +23,7 @@ type MailSubject struct { ...@@ -23,7 +23,7 @@ type MailSubject struct {
// @Failure 404 {string} string "Not found" // @Failure 404 {string} string "Not found"
// @Param year path int true "Year of the mailSubject" // @Param year path int true "Year of the mailSubject"
// @Param month path int true "Month of the mailSubject" // @Param month path int true "Month of the mailSubject"
// @Router /api/admin/mailSubject/{year}/{month} [get] // @Router /api/animator/mailSubject/{year}/{month} [get]
func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Request) {
year, month, err := common.YearMonthFromRequest(r) year, month, err := common.YearMonthFromRequest(r)
if err != nil { if err != nil {
...@@ -54,7 +54,7 @@ func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Reque ...@@ -54,7 +54,7 @@ func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Reque
// @Failure 400 {string} string "Bad Request" // @Failure 400 {string} string "Bad Request"
// @Failure 500 {string} string "Internal server error" // @Failure 500 {string} string "Internal server error"
// @Param mailSubject body MailSubject true "MailSubject to create/update with new content" // @Param mailSubject body MailSubject true "MailSubject to create/update with new content"
// @Router /api/admin/mailSubject [put] // @Router /api/animator/mailSubject [put]
func (dh *DataHandler) SaveMailSubject(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) SaveMailSubject(w http.ResponseWriter, r *http.Request) {
if r.Body == http.NoBody { if r.Body == http.NoBody {
http.Error(w, "request body is empty", http.StatusBadRequest) http.Error(w, "request body is empty", http.StatusBadRequest)
...@@ -111,7 +111,7 @@ func (dh *DataHandler) SaveMailSubject(w http.ResponseWriter, r *http.Request) { ...@@ -111,7 +111,7 @@ func (dh *DataHandler) SaveMailSubject(w http.ResponseWriter, r *http.Request) {
// @Failure 404 {string} string "Not found" // @Failure 404 {string} string "Not found"
// @Param year path int true "Year of the mailSubject" // @Param year path int true "Year of the mailSubject"
// @Param month path int true "Month of the mailSubject" // @Param month path int true "Month of the mailSubject"
// @Router /api/admin/mailSubject/{year}/{month} [delete] // @Router /api/animator/mailSubject/{year}/{month} [delete]
func (dh *DataHandler) DeleteMailSubject(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) DeleteMailSubject(w http.ResponseWriter, r *http.Request) {
year, month, err := common.YearMonthFromRequest(r) year, month, err := common.YearMonthFromRequest(r)
if err != nil { if err != nil {
......
...@@ -21,7 +21,7 @@ type MonthlyInfo struct { ...@@ -21,7 +21,7 @@ type MonthlyInfo struct {
// @Tags monthlyInfo // @Tags monthlyInfo
// @Produce json // @Produce json
// @Success 200 {array} MonthlyInfo // @Success 200 {array} MonthlyInfo
// @Router /api/admin/monthlyInfo [get] // @Router /api/animator/monthlyInfo [get]
func (dh *DataHandler) GetAllMonthlyInfo(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) GetAllMonthlyInfo(w http.ResponseWriter, r *http.Request) {
var monthlyInfo []MonthlyInfo var monthlyInfo []MonthlyInfo
dh.sqlClient.Find(&monthlyInfo) dh.sqlClient.Find(&monthlyInfo)
...@@ -40,7 +40,7 @@ func (dh *DataHandler) GetAllMonthlyInfo(w http.ResponseWriter, r *http.Request) ...@@ -40,7 +40,7 @@ func (dh *DataHandler) GetAllMonthlyInfo(w http.ResponseWriter, r *http.Request)
// @Failure 404 {string} string "Not found" // @Failure 404 {string} string "Not found"
// @Param year path int true "Year of the monthlyInfo" // @Param year path int true "Year of the monthlyInfo"
// @Param month path int true "Month of the monthlyInfo" // @Param month path int true "Month of the monthlyInfo"
// @Router /api/admin/monthlyInfo/{year}/{month} [get] // @Router /api/animator/monthlyInfo/{year}/{month} [get]
func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Request) {
year, month, err := common.YearMonthFromRequest(r) year, month, err := common.YearMonthFromRequest(r)
if err != nil { if err != nil {
...@@ -71,7 +71,7 @@ func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Reque ...@@ -71,7 +71,7 @@ func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Reque
// @Failure 400 {string} string "Bad Request" // @Failure 400 {string} string "Bad Request"
// @Failure 500 {string} string "Internal server error" // @Failure 500 {string} string "Internal server error"
// @Param monthlyInfo body MonthlyInfo true "MonthlyInfo to create/update with new content" // @Param monthlyInfo body MonthlyInfo true "MonthlyInfo to create/update with new content"
// @Router /api/admin/monthlyInfo [put] // @Router /api/animator/monthlyInfo [put]
func (dh *DataHandler) SaveMonthlyInfo(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) SaveMonthlyInfo(w http.ResponseWriter, r *http.Request) {
if r.Body == http.NoBody { if r.Body == http.NoBody {
http.Error(w, "request body is empty", http.StatusBadRequest) http.Error(w, "request body is empty", http.StatusBadRequest)
...@@ -136,7 +136,7 @@ func (dh *DataHandler) SaveMonthlyInfo(w http.ResponseWriter, r *http.Request) { ...@@ -136,7 +136,7 @@ func (dh *DataHandler) SaveMonthlyInfo(w http.ResponseWriter, r *http.Request) {
// @Failure 404 {string} string "Not found" // @Failure 404 {string} string "Not found"
// @Param year path int true "Year of the monthlyInfo" // @Param year path int true "Year of the monthlyInfo"
// @Param month path int true "Month of the monthlyInfo" // @Param month path int true "Month of the monthlyInfo"
// @Router /api/admin/monthlyInfo/{year}/{month} [delete] // @Router /api/animator/monthlyInfo/{year}/{month} [delete]
func (dh *DataHandler) DeleteMonthlyInfo(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) DeleteMonthlyInfo(w http.ResponseWriter, r *http.Request) {
year, month, err := common.YearMonthFromRequest(r) year, month, err := common.YearMonthFromRequest(r)
if err != nil { if err != nil {
......
...@@ -21,7 +21,7 @@ type MonthlyNews struct { ...@@ -21,7 +21,7 @@ type MonthlyNews struct {
// @Tags monthlyNews // @Tags monthlyNews
// @Produce json // @Produce json
// @Success 200 {array} MonthlyNews // @Success 200 {array} MonthlyNews
// @Router /api/admin/monthlyNews [get] // @Router /api/animator/monthlyNews [get]
func (dh *DataHandler) GetAllMonthlyNews(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) GetAllMonthlyNews(w http.ResponseWriter, r *http.Request) {
var monthlyNews []MonthlyNews var monthlyNews []MonthlyNews
dh.sqlClient.Find(&monthlyNews) dh.sqlClient.Find(&monthlyNews)
...@@ -40,7 +40,7 @@ func (dh *DataHandler) GetAllMonthlyNews(w http.ResponseWriter, r *http.Request) ...@@ -40,7 +40,7 @@ func (dh *DataHandler) GetAllMonthlyNews(w http.ResponseWriter, r *http.Request)
// @Failure 404 {string} string "Not found" // @Failure 404 {string} string "Not found"
// @Param year path int true "Year of the monthlyNews" // @Param year path int true "Year of the monthlyNews"
// @Param month path int true "Month of the monthlyNews" // @Param month path int true "Month of the monthlyNews"
// @Router /api/admin/monthlyNews/{year}/{month} [get] // @Router /api/animator/monthlyNews/{year}/{month} [get]
func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Request) {
year, month, err := common.YearMonthFromRequest(r) year, month, err := common.YearMonthFromRequest(r)
if err != nil { if err != nil {
...@@ -71,7 +71,7 @@ func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Reque ...@@ -71,7 +71,7 @@ func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Reque
// @Failure 400 {string} string "Bad Request" // @Failure 400 {string} string "Bad Request"
// @Failure 500 {string} string "Internal server error" // @Failure 500 {string} string "Internal server error"
// @Param monthlyNews body MonthlyNews true "MonthlyNews to create/update with new content" // @Param monthlyNews body MonthlyNews true "MonthlyNews to create/update with new content"
// @Router /api/admin/monthlyNews [put] // @Router /api/animator/monthlyNews [put]
func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) {
if r.Body == http.NoBody { if r.Body == http.NoBody {
http.Error(w, "request body is empty", http.StatusBadRequest) http.Error(w, "request body is empty", http.StatusBadRequest)
...@@ -136,7 +136,7 @@ func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) { ...@@ -136,7 +136,7 @@ func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) {
// @Failure 404 {string} string "Not found" // @Failure 404 {string} string "Not found"
// @Param year path int true "Year of the monthlyNews" // @Param year path int true "Year of the monthlyNews"
// @Param month path int true "Month of the monthlyNews" // @Param month path int true "Month of the monthlyNews"
// @Router /api/admin/monthlyNews/{year}/{month} [delete] // @Router /api/animator/monthlyNews/{year}/{month} [delete]
func (dh *DataHandler) DeleteMonthlyNews(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) DeleteMonthlyNews(w http.ResponseWriter, r *http.Request) {
year, month, err := common.YearMonthFromRequest(r) year, month, err := common.YearMonthFromRequest(r)
if err != nil { if err != nil {
......
...@@ -49,7 +49,7 @@ func (dh *DataHandler) GetPartnersInfo(w http.ResponseWriter, r *http.Request) { ...@@ -49,7 +49,7 @@ func (dh *DataHandler) GetPartnersInfo(w http.ResponseWriter, r *http.Request) {
// @Failure 400 {string} string "Bad Request" // @Failure 400 {string} string "Bad Request"
// @Failure 500 {string} string "Internal server error" // @Failure 500 {string} string "Internal server error"
// @Param partnersInfo body PartnersInfo true "PartnersInfo to create/update with new content" // @Param partnersInfo body PartnersInfo true "PartnersInfo to create/update with new content"
// @Router /api/admin/partnersInfo [put] // @Router /api/animator/partnersInfo [put]
func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request) {
if r.Body == http.NoBody { if r.Body == http.NoBody {
http.Error(w, "request body is empty", http.StatusBadRequest) http.Error(w, "request body is empty", http.StatusBadRequest)
......
...@@ -21,7 +21,7 @@ type Poll struct { ...@@ -21,7 +21,7 @@ type Poll struct {
// @Tags poll // @Tags poll
// @Produce json // @Produce json
// @Success 200 {array} Poll // @Success 200 {array} Poll
// @Router /api/admin/poll [get] // @Router /api/animator/poll [get]
func (dh *DataHandler) GetAllPolls(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) GetAllPolls(w http.ResponseWriter, r *http.Request) {
var polls []Poll var polls []Poll
err := dh.sqlClient.Find(&polls).Error err := dh.sqlClient.Find(&polls).Error
...@@ -44,7 +44,7 @@ func (dh *DataHandler) GetAllPolls(w http.ResponseWriter, r *http.Request) { ...@@ -44,7 +44,7 @@ func (dh *DataHandler) GetAllPolls(w http.ResponseWriter, r *http.Request) {
// @Failure 404 {string} string "Not found" // @Failure 404 {string} string "Not found"
// @Param year path int true "Year of the poll" // @Param year path int true "Year of the poll"
// @Param month path int true "Month of the poll" // @Param month path int true "Month of the poll"
// @Router /api/admin/poll/{year}/{month} [get] // @Router /api/animator/poll/{year}/{month} [get]
func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) {
year, month, err := common.YearMonthFromRequest(r) year, month, err := common.YearMonthFromRequest(r)
if err != nil { if err != nil {
...@@ -75,7 +75,7 @@ func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) { ...@@ -75,7 +75,7 @@ func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) {
// @Failure 400 {string} string "Bad Request" // @Failure 400 {string} string "Bad Request"
// @Failure 500 {string} string "Internal server error" // @Failure 500 {string} string "Internal server error"
// @Param poll body Poll true "Poll to update with new content" // @Param poll body Poll true "Poll to update with new content"
// @Router /api/admin/poll [put] // @Router /api/animator/poll [put]
func (dh *DataHandler) SavePoll(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) SavePoll(w http.ResponseWriter, r *http.Request) {
if r.Body == http.NoBody { if r.Body == http.NoBody {
http.Error(w, "request body is empty", http.StatusBadRequest) http.Error(w, "request body is empty", http.StatusBadRequest)
...@@ -133,7 +133,7 @@ func (dh *DataHandler) SavePoll(w http.ResponseWriter, r *http.Request) { ...@@ -133,7 +133,7 @@ func (dh *DataHandler) SavePoll(w http.ResponseWriter, r *http.Request) {
// @Failure 404 {string} string "Not found" // @Failure 404 {string} string "Not found"
// @Param year path int true "Year of the poll" // @Param year path int true "Year of the poll"
// @Param month path int true "Month of the poll" // @Param month path int true "Month of the poll"
// @Router /api/admin/poll/{year}/{month} [delete] // @Router /api/animator/poll/{year}/{month} [delete]
func (dh *DataHandler) DeletePoll(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) DeletePoll(w http.ResponseWriter, r *http.Request) {
year, month, err := common.YearMonthFromRequest(r) year, month, err := common.YearMonthFromRequest(r)
if err != nil { if err != nil {
......
...@@ -72,7 +72,7 @@ func (dh *DataHandler) GetPricesByFluid(w http.ResponseWriter, r *http.Request) ...@@ -72,7 +72,7 @@ func (dh *DataHandler) GetPricesByFluid(w http.ResponseWriter, r *http.Request)
// @Failure 400 {string} string "Bad Request" // @Failure 400 {string} string "Bad Request"
// @Failure 500 {string} string "Internal server error" // @Failure 500 {string} string "Internal server error"
// @Param price body object true "Price to create/update with new content" // @Param price body object true "Price to create/update with new content"
// @Router /api/admin/price [put] // @Router /api/animator/price [put]
func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) { func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) {
if r.Body == http.NoBody { if r.Body == http.NoBody {
http.Error(w, "request body price is empty", http.StatusBadRequest) http.Error(w, "request body price is empty", http.StatusBadRequest)
......
...@@ -51,8 +51,8 @@ func CreateRootMux() RootMux { ...@@ -51,8 +51,8 @@ func CreateRootMux() RootMux {
r.Get("/prices/{fluidtype}", dh.GetPricesByFluid) r.Get("/prices/{fluidtype}", dh.GetPricesByFluid)
}) })
r.Route("/api/admin", func(r chi.Router) { r.Route("/api/animator", func(r chi.Router) {
r.Use(auth.AdminAuthMiddleware) r.Use(auth.AnimatorAuthMiddleware)
r.Get("/mailSubject/{year}/{month}", dh.GetSingleMailSubject) r.Get("/mailSubject/{year}/{month}", dh.GetSingleMailSubject)
r.Put("/mailSubject", dh.SaveMailSubject) r.Put("/mailSubject", dh.SaveMailSubject)
r.Delete("/mailSubject/{year}/{month}", dh.DeleteMailSubject) r.Delete("/mailSubject/{year}/{month}", dh.DeleteMailSubject)
...@@ -76,6 +76,10 @@ func CreateRootMux() RootMux { ...@@ -76,6 +76,10 @@ func CreateRootMux() RootMux {
r.Put("/customPopup", dh.SaveCustomPopup) r.Put("/customPopup", dh.SaveCustomPopup)
r.Get("/imageNames", file.GetEcogestureImages) r.Get("/imageNames", file.GetEcogestureImages)
r.Put("/prices", dh.SavePrice) r.Put("/prices", dh.SavePrice)
})
r.Route("/api/admin", func(r chi.Router) {
r.Use(auth.AdminAuthMiddleware)
r.Get("/consent", dh.SearchConsent) r.Get("/consent", dh.SearchConsent)
}) })
......
...@@ -45,11 +45,12 @@ func TestMain(m *testing.M) { ...@@ -45,11 +45,12 @@ func TestMain(m *testing.M) {
// Set the constants with environment variables // Set the constants with environment variables
os.Setenv("HOSTNAME", "localhost") os.Setenv("HOSTNAME", "localhost")
os.Setenv("ANIMATOR_ROLE", "ANIMATORS")
os.Setenv("ADMIN_ROLE", "ADMINS") os.Setenv("ADMIN_ROLE", "ADMINS")
os.Setenv("CLIENT_ID", "foo") os.Setenv("CLIENT_ID", "foo")
os.Setenv("CLIENT_SECRET", "bar") os.Setenv("CLIENT_SECRET", "bar")
os.Setenv("TOKEN_URL", oAuth2Server.URL+"/token") os.Setenv("TOKEN_URL", oAuth2Server.URL+"/token")
os.Setenv("USERINFO_URL", oAuth2Server.URL+"/userinfo") os.Setenv("USERINFO_URL", oAuth2Server.URL+"/animatorinfo")
os.Setenv("LOGOUT_URL", oAuth2Server.URL+"/logout") os.Setenv("LOGOUT_URL", oAuth2Server.URL+"/logout")
os.Setenv("SGE_API_TOKEN", "sgeApiToken") os.Setenv("SGE_API_TOKEN", "sgeApiToken")
...@@ -82,17 +83,18 @@ func TestMain(m *testing.M) { ...@@ -82,17 +83,18 @@ func TestMain(m *testing.M) {
} }
func TestAll(t *testing.T) { func TestAll(t *testing.T) {
// SGE API tests
sgeTests(t)
// Set up testers // Set up testers
os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth-wrong-state") // Set the server to access failing OAuth2 endpoints os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth-wrong-state") // Set the server to access failing OAuth2 endpoints
oauth2Tests(t) oauth2Tests(t)
os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth") // Set the server to access the correct OAuth2Endpoint os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth") // Set the server to access the correct OAuth2Endpoint
unloggedTests(t) unloggedTests(t)
os.Setenv("USERINFO_URL", oAuth2Server.URL+"/animatorinfo")
animatorTests(t)
os.Setenv("USERINFO_URL", oAuth2Server.URL+"/admininfo") os.Setenv("USERINFO_URL", oAuth2Server.URL+"/admininfo")
adminTests(t) adminTests(t)
// SGE API tests
sgeTests(t)
} }
/* /*
...@@ -119,7 +121,7 @@ func unloggedTests(t *testing.T) { ...@@ -119,7 +121,7 @@ func unloggedTests(t *testing.T) {
defer ts.Close() // Close the tester defer ts.Close() // Close the tester
// Try to create a monthlyNews (must fail) // Try to create a monthlyNews (must fail)
do("PUT", "/api/admin/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "error extracting token") do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "error extracting token")
// Try to get a monthlyReport (must fail because no parameters are given) // Try to get a monthlyReport (must fail because no parameters are given)
do("GET", "/api/common/monthlyReport", noH, "", http.StatusBadRequest, "") do("GET", "/api/common/monthlyReport", noH, "", http.StatusBadRequest, "")
// Try to get a monthlyReport (must pass empty) // Try to get a monthlyReport (must pass empty)
...@@ -130,10 +132,10 @@ func unloggedTests(t *testing.T) { ...@@ -130,10 +132,10 @@ func unloggedTests(t *testing.T) {
/* /*
* *
ADMIN TESTS (this tests are to check that an administrator can edit a newsletter's content) ANIMATOR TESTS (these tests are to check that an animator user can edit a newsletter's content but can't access SGE consents)
* *
*/ */
func adminTests(t *testing.T) { func animatorTests(t *testing.T) {
// Create the tester // Create the tester
ts, do, _ := createTester(t) ts, do, _ := createTester(t)
defer ts.Close() // Close the tester defer ts.Close() // Close the tester
...@@ -144,83 +146,85 @@ func adminTests(t *testing.T) { ...@@ -144,83 +146,85 @@ func adminTests(t *testing.T) {
json.Unmarshal([]byte(response), &token) json.Unmarshal([]byte(response), &token)
xsrfHeader := map[string]string{"XSRF-TOKEN": token.XSRFToken} xsrfHeader := map[string]string{"XSRF-TOKEN": token.XSRFToken}
// Try to create a monthlyNews without the XSRF-TOKEN (must fail) // Try to create a monthlyNews without the XSRF-TOKEN (must fail)
do("PUT", "/api/admin/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "XSRF protection triggered") do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "XSRF protection triggered")
// Try to create a monthlyNews without body (must fail) // Try to create a monthlyNews without body (must fail)
do("PUT", "/api/admin/monthlyNews", xsrfHeader, "", http.StatusBadRequest, "request body is empty") do("PUT", "/api/animator/monthlyNews", xsrfHeader, "", http.StatusBadRequest, "request body is empty")
// Try to get a monthlyNews before it is created (must fail because not found) // Try to get a monthlyNews before it is created (must fail because not found)
do("GET", "/api/admin/monthlyNews/2021/1", xsrfHeader, "", http.StatusNotFound, "") do("GET", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusNotFound, "")
// Try to create a monthlyNews (must pass) // Try to create a monthlyNews (must pass)
do("PUT", "/api/admin/monthlyNews", xsrfHeader, monthlyNewsStr, http.StatusCreated, `{"year":2021,"month":1,"title":"Les nouveautés du service","content":"Nouvelles fonctionnalités"`) do("PUT", "/api/animator/monthlyNews", xsrfHeader, monthlyNewsStr, http.StatusCreated, `{"year":2021,"month":1,"title":"Les nouveautés du service","content":"Nouvelles fonctionnalités"`)
// Try to update a monthlyNews (must pass) // Try to update a monthlyNews (must pass)
do("PUT", "/api/admin/monthlyNews", xsrfHeader, monthlyNewsStr, http.StatusOK, `{"year":2021,"month":1,"title":"Les nouveautés du service","content":"Nouvelles fonctionnalités"`) do("PUT", "/api/animator/monthlyNews", xsrfHeader, monthlyNewsStr, http.StatusOK, `{"year":2021,"month":1,"title":"Les nouveautés du service","content":"Nouvelles fonctionnalités"`)
// Try to get the monthlyNews created (must pass) // Try to get the monthlyNews created (must pass)
do("GET", "/api/admin/monthlyNews/2021/1", xsrfHeader, "", http.StatusOK, `{"year":2021,"month":1,"title":"Les nouveautés du service","content":"Nouvelles fonctionnalités"`) do("GET", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusOK, `{"year":2021,"month":1,"title":"Les nouveautés du service","content":"Nouvelles fonctionnalités"`)
// Try to get the monthlyReport (must pass) // 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] Votre bilan de décembre 2020","info":"","image":"","newsTitle":"Les nouveautés du service","newsContent":"Nouvelles fonctionnalités","question":"","link":""}`) 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) // Try to create a poll without the XSRF-TOKEN (must fail)
do("PUT", "/api/admin/poll", noH, newPollStr, http.StatusUnauthorized, "XSRF protection triggered") do("PUT", "/api/animator/poll", noH, newPollStr, http.StatusUnauthorized, "XSRF protection triggered")
// Try to create a poll without body (must fail) // Try to create a poll without body (must fail)
do("PUT", "/api/admin/poll", xsrfHeader, "", http.StatusBadRequest, "request body is empty") do("PUT", "/api/animator/poll", xsrfHeader, "", http.StatusBadRequest, "request body is empty")
// Try to get a poll before it is created (must fail because not found') // Try to get a poll before it is created (must fail because not found')
do("GET", "/api/admin/poll/2021/1", xsrfHeader, "", http.StatusNotFound, "") do("GET", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusNotFound, "")
// Try to create a poll (must pass) // Try to create a poll (must pass)
do("PUT", "/api/admin/poll", xsrfHeader, newPollStr, http.StatusCreated, newPollStr) do("PUT", "/api/animator/poll", xsrfHeader, newPollStr, http.StatusCreated, newPollStr)
// Try to update a poll (must pass) // Try to update a poll (must pass)
do("PUT", "/api/admin/poll", xsrfHeader, newPollStr, http.StatusOK, newPollStr) do("PUT", "/api/animator/poll", xsrfHeader, newPollStr, http.StatusOK, newPollStr)
// Try to get the poll created (must pass) // Try to get the poll created (must pass)
do("GET", "/api/admin/poll/2021/1", xsrfHeader, "", http.StatusOK, newPollStr) do("GET", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusOK, newPollStr)
// Try to get the monthlyReport (must pass) // 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] Votre bilan de décembre 2020","info":"","image":"","newsTitle":"Les nouveautés du service","newsContent":"Nouvelles fonctionnalités","question":"pollQuestion","link":"pollLink"}`) 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) // Try to create a monthlyInfo without the XSRF-TOKEN (must fail)
do("PUT", "/api/admin/monthlyInfo", noH, monthlyInfoStr, http.StatusUnauthorized, "XSRF protection triggered") do("PUT", "/api/animator/monthlyInfo", noH, monthlyInfoStr, http.StatusUnauthorized, "XSRF protection triggered")
// Try to create a monthlyInfo without body (must fail) // Try to create a monthlyInfo without body (must fail)
do("PUT", "/api/admin/monthlyInfo", xsrfHeader, "", http.StatusBadRequest, "request body is empty") do("PUT", "/api/animator/monthlyInfo", xsrfHeader, "", http.StatusBadRequest, "request body is empty")
// Try to get a monthlyInfo before it is created (must fail because not found) // Try to get a monthlyInfo before it is created (must fail because not found)
do("GET", "/api/admin/monthlyInfo/2021/1", xsrfHeader, "", http.StatusNotFound, "") do("GET", "/api/animator/monthlyInfo/2021/1", xsrfHeader, "", http.StatusNotFound, "")
// Try to create a monthlyInfo (must pass) // Try to create a monthlyInfo (must pass)
do("PUT", "/api/admin/monthlyInfo", xsrfHeader, monthlyInfoStr, http.StatusCreated, monthlyInfoStr) do("PUT", "/api/animator/monthlyInfo", xsrfHeader, monthlyInfoStr, http.StatusCreated, monthlyInfoStr)
// Try to update a monthlyInfo (must pass) // Try to update a monthlyInfo (must pass)
do("PUT", "/api/admin/monthlyInfo", xsrfHeader, monthlyInfoStr, http.StatusOK, monthlyInfoStr) do("PUT", "/api/animator/monthlyInfo", xsrfHeader, monthlyInfoStr, http.StatusOK, monthlyInfoStr)
// Try to get the monthlyInfo created (must pass) // Try to get the monthlyInfo created (must pass)
do("GET", "/api/admin/monthlyInfo/2021/1", xsrfHeader, "", http.StatusOK, monthlyInfoStr) do("GET", "/api/animator/monthlyInfo/2021/1", xsrfHeader, "", http.StatusOK, monthlyInfoStr)
// Try to get the monthlyReport (must pass) // 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] Votre bilan de décembre 2020","info":"Informations du mois","image":"imagebase64","newsTitle":"Les nouveautés du service","newsContent":"Nouvelles fonctionnalités","question":"pollQuestion","link":"pollLink"`) 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":"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) // Try to update the partnersInfo (must pass)
do("PUT", "/api/admin/partnersInfo", xsrfHeader, partnersInfoStr, http.StatusOK, partnersInfoStr) do("PUT", "/api/animator/partnersInfo", xsrfHeader, partnersInfoStr, http.StatusOK, partnersInfoStr)
// Try to get the partnersInfo created (must pass) // Try to get the partnersInfo created (must pass)
do("GET", "/api/common/partnersInfo", xsrfHeader, "", http.StatusOK, partnersInfoStr) do("GET", "/api/common/partnersInfo", xsrfHeader, "", http.StatusOK, partnersInfoStr)
// Try to update the customPopup (must pass) // Try to update the customPopup (must pass)
do("PUT", "/api/admin/customPopup", xsrfHeader, customPopupStr, http.StatusOK, customPopupStr) do("PUT", "/api/animator/customPopup", xsrfHeader, customPopupStr, http.StatusOK, customPopupStr)
// Try to get the partnersInfo created (must pass) // Try to get the partnersInfo created (must pass)
do("GET", "/api/common/customPopup", xsrfHeader, "", http.StatusOK, customPopupStr) do("GET", "/api/common/customPopup", xsrfHeader, "", http.StatusOK, customPopupStr)
// Try to delete the monthlyNews created (must pass) // Try to delete the monthlyNews created (must pass)
do("DELETE", "/api/admin/monthlyNews/2021/1", xsrfHeader, "", http.StatusOK, "successful delete") do("DELETE", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusOK, "successful delete")
// Try to get a monthlyNews after it is deleted (must fail because not found) // Try to get a monthlyNews after it is deleted (must fail because not found)
do("GET", "/api/admin/monthlyNews/2021/1", xsrfHeader, "", http.StatusNotFound, "") do("GET", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusNotFound, "")
// Try to create a mail subject (must pass) // Try to create a mail subject (must pass)
do("PUT", "/api/admin/mailSubject", xsrfHeader, mailSubjectStr, http.StatusCreated, mailSubjectStr) do("PUT", "/api/animator/mailSubject", xsrfHeader, mailSubjectStr, http.StatusCreated, mailSubjectStr)
// Try to get the monthlyReport (must pass) // 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"`) 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) // Try to delete the poll created (must pass)
do("DELETE", "/api/admin/poll/2021/1", xsrfHeader, "", http.StatusOK, "successful delete") do("DELETE", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusOK, "successful delete")
// Try to get a poll after it is deleted (must fail because not found) // Try to get a poll after it is deleted (must fail because not found)
do("GET", "/api/admin/poll/2021/1", xsrfHeader, "", http.StatusNotFound, "") do("GET", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusNotFound, "")
// Try to get the monthlyReport (must pass) // 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":""`) 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) // Try to delete the mail subject created (must pass)
do("DELETE", "/api/admin/mailSubject/2021/1", xsrfHeader, "", http.StatusOK, "successful delete") do("DELETE", "/api/animator/mailSubject/2021/1", xsrfHeader, "", http.StatusOK, "successful delete")
// Try to get a mail subject after it is deleted (must fail because not found) // Try to get a mail subject after it is deleted (must fail because not found)
do("GET", "/api/admin/mailSubject/2021/1", xsrfHeader, "", http.StatusNotFound, "") do("GET", "/api/animator/mailSubject/2021/1", xsrfHeader, "", http.StatusNotFound, "")
// Try to get the monthlyReport (must pass) // 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] Votre bilan de décembre 2020","info":"Informations du mois","image":"imagebase64","newsTitle":"","newsContent":"","question":"","link":""`) 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":"Informations du mois","image":"imagebase64","newsTitle":"","newsContent":"","question":"","link":""`)
// Try to get SGE consents (must fail)
do("GET", "/api/admin/consent?limit=50&page=0", xsrfHeader, "", http.StatusForbidden, "no user role among [ANIMATORS OTHER_GROUP] is in allowed roles ([ADMINS])")
} }
// Try to login (must pass) // Try to login (must pass)
do("GET", "/OAuth2Login", noH, "", http.StatusOK, "") do("GET", "/OAuth2Login", noH, "", http.StatusOK, "")
...@@ -229,12 +233,33 @@ func adminTests(t *testing.T) { ...@@ -229,12 +233,33 @@ func adminTests(t *testing.T) {
// Try to logout (must pass) // Try to logout (must pass)
do("GET", "/Logout", noH, "", http.StatusOK, "") do("GET", "/Logout", noH, "", http.StatusOK, "")
// Try to get a monthlyNews again (must fail) // Try to get a monthlyNews again (must fail)
do("GET", "/api/admin/monthlyNews", noH, "", http.StatusUnauthorized, "error extracting token") do("GET", "/api/animator/monthlyNews", noH, "", http.StatusUnauthorized, "error extracting token")
// Try to get a poll again (must fail) // Try to get a poll again (must fail)
do("GET", "/api/admin/poll", noH, "", http.StatusUnauthorized, "error extracting token") do("GET", "/api/animator/poll", noH, "", http.StatusUnauthorized, "error extracting token")
} }
func adminTests(t *testing.T) {
// Create the tester
ts, do, _ := createTester(t)
defer ts.Close() // Close the tester
// Try to login (must pass)
do("GET", "/OAuth2Login", noH, "", http.StatusOK, "")
// Get the XSRF Token
response := do("GET", "/api/common/WhoAmI", noH, "", http.StatusOK, "")
token := auth.TokenData{}
json.Unmarshal([]byte(response), &token)
xsrfHeader := map[string]string{"XSRF-TOKEN": token.XSRFToken}
// Try to get SGE consents (must pass)
do("GET", "/api/admin/consent?limit=50&page=0", xsrfHeader, "", http.StatusOK, `{"totalRows":2,"rows":[{"ID":2`)
// 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")
}
func sgeTests(t *testing.T) { func sgeTests(t *testing.T) {
// Create the tester // Create the tester
ts, do, _ := createTester(t) ts, do, _ := createTester(t)
...@@ -260,25 +285,6 @@ func sgeTests(t *testing.T) { ...@@ -260,25 +285,6 @@ func sgeTests(t *testing.T) {
do("GET", "/api/sge/consent/1", sgeApiHeader, "", http.StatusOK, `{"ID":1`) do("GET", "/api/sge/consent/1", sgeApiHeader, "", http.StatusOK, `{"ID":1`)
// Try to get a consent that doesn't exist (must fail not found) // Try to get a consent that doesn't exist (must fail not found)
do("GET", "/api/sge/consent/3", sgeApiHeader, "", http.StatusNotFound, `consent not found`) do("GET", "/api/sge/consent/3", sgeApiHeader, "", http.StatusNotFound, `consent not found`)
// Try to login (must pass)
do("GET", "/OAuth2Login", noH, "", http.StatusOK, "")
response := do("GET", "/api/common/WhoAmI", noH, "", http.StatusOK, "")
token := auth.TokenData{}
json.Unmarshal([]byte(response), &token)
xsrfHeader := map[string]string{"XSRF-TOKEN": token.XSRFToken}
// Try to get first 50 consents (must pass)
do("GET", "/api/admin/consent?limit=50&page=0", xsrfHeader, "", http.StatusOK, `{"totalRows":2,"rows":[{"ID":2`)
// Try to search for both consent (must pass)
do("GET", "/api/admin/consent?search=123456&limit=50&page=0", xsrfHeader, "", http.StatusOK, `{"totalRows":2,"rows":[{"ID":2`)
// Try to search for first point id (must pass)
do("GET", "/api/admin/consent?search=12345671234567&limit=50&page=0", xsrfHeader, "", http.StatusOK, `{"totalRows":1,"rows":[{"ID":1`)
// Try to search for second point id (must pass)
do("GET", "/api/admin/consent?search=01234560123456&limit=50&page=0", xsrfHeader, "", http.StatusOK, `{"totalRows":1,"rows":[{"ID":2`)
// Try to search for unknown point id (must pass empty)
do("GET", "/api/admin/consent?search=000000&limit=50&page=0", xsrfHeader, "", http.StatusOK, `{"totalRows":0,"rows":[]`)
// Try to delete a consent (must pass) // Try to delete a consent (must pass)
do("DELETE", "/api/sge/consent/1", sgeApiHeader, "", http.StatusOK, "") do("DELETE", "/api/sge/consent/1", sgeApiHeader, "", http.StatusOK, "")
} }
......
...@@ -6,6 +6,7 @@ stringData: ...@@ -6,6 +6,7 @@ stringData:
# Replace all values between <...> # Replace all values between <...>
# All values must be string ex: 1443 => '1443' # All values must be string ex: 1443 => '1443'
ADMIN_ROLE: GG_SNG_ECO ADMIN_ROLE: GG_SNG_ECO
ANIMATOR_ROLE: GG_SNG_ECO_ANIM
AUTH_URL: {{AUTH_URL}} AUTH_URL: {{AUTH_URL}}
CLIENT_ID: {{CLIENT_ID}} CLIENT_ID: {{CLIENT_ID}}
CLIENT_SECRET: {{CLIENT_SECRET}} CLIENT_SECRET: {{CLIENT_SECRET}}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment