diff --git a/.gitignore b/.gitignore index 8c09811d196e402bd273d828868eacd5ae8e855d..ccce815bf6e02ba5ab615afdcdee9c2fa44b42e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env -backoffice.db \ No newline at end of file +backoffice.db +meili_data/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 8add34982dc6870e6fe686dd0f8de91bb29a3468..da3a8c41db6a7509af70ad003d3b52eefbaa7f25 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,11 +25,14 @@ "TOKEN_URL": "http://localhost:8090/token", "USERINFO_URL": "http://localhost:8090/admininfo", - "DATABASE_USER": "", + "DATABASE_USER": "root", "DATABASE_PASSWORD": "password", "DATABASE_NAME": "backoffice", "DATABASE_HOST": "127.0.0.1", "LOGOUT_URL": "/", + "SGE_API_TOKEN": "sgeapitoken", + "MEILI_HOST": "http://localhost:7700", + "MEILI_MASTER_KEY": "masterkey" }, "showLog": true }, @@ -55,4 +58,4 @@ "showLog": true } ] -} +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 8aa22632efe030ac4a7aec18404210a10b1c2b38..87bf2455f69ae98ac71702ff7ca3d35a0b2a70ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,13 +4,16 @@ # STEP 1 build executable binary # ################################## -FROM golang:alpine as builder +FROM golang as builder # Install git + SSL ca certificates. # Git is required for fetching the dependencies. # Ca-certificates is required to call HTTPS endpoints. -RUN apk update && apk add --no-cache git ca-certificates tzdata libcap mailcap && update-ca-certificates -RUN apk add build-base +RUN apt-get update && apt-get install -y git ca-certificates tzdata libcap2-bin mailcap curl && update-ca-certificates + +# Get meilisearch binary +RUN curl -L https://install.meilisearch.com | sh +RUN mv ./meilisearch /usr/bin/ # Create appuser ENV USER=appuser @@ -29,17 +32,9 @@ WORKDIR /app ADD . . -RUN chown -Rf "${UID}" ./* - -# Get dependencies and run tests -RUN go version -RUN go get -d -v -RUN CGO_ENABLED=1 go test ./... +RUN ./start-meilisearch-test-and-build.sh -# Build the binary -RUN CGO_ENABLED=1 go build \ - -ldflags='-w -s -extldflags "-static"' -a \ - -o /app/backoffice-server . +RUN chown -Rf "${UID}" ./* # Allow running on ports < 1000 RUN setcap cap_net_bind_service=+ep /app/backoffice-server @@ -47,7 +42,7 @@ RUN setcap cap_net_bind_service=+ep /app/backoffice-server ############################## # STEP 2 build a small image # ############################## -FROM alpine:3.14.0 +FROM scratch WORKDIR /app diff --git a/docker-compose.yml b/docker-compose.yml index ca2476473ed949939736274e10c63ae3f1224c1b..1f0cb5cf3e993c793c6711ed58d6b86e784bcd7a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,23 +3,44 @@ version: '3.1' services: database: image: mysql:5 + healthcheck: + test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD + interval: 5s + timeout: 10s + retries: 60 + volumes: + - ./dbinit:/dbinit + networks: + - ecolyo-agent-network ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} + + meilisearch: + image: getmeili/meilisearch:v0.27.2 healthcheck: - test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD - interval: 5s + test: ["CMD", "curl", "-f", "http://0.0.0.0:7700"] + interval: 10s timeout: 10s - retries: 60 + retries: 3 volumes: - - ./dbinit:/dbinit + - ./meili_data:/meili_data + networks: + - ecolyo-agent-network + ports: + - 7700:7700 + environment: + - MEILI_MASTER_KEY=${MEILI_MASTER_KEY} + phpmyadmin: image: phpmyadmin/phpmyadmin:latest depends_on: - database + networks: + - ecolyo-agent-network ports: - 8008:80 environment: @@ -30,6 +51,8 @@ services: depends_on: database: condition: service_healthy + meilisearch: + condition: service_healthy build: . restart: unless-stopped volumes: @@ -38,6 +61,8 @@ services: - ./letsencrypt_cache:/app/letsencrypt_cache - ./data:/app/data - ./../${IMAGE_FOLDER}:/app/${IMAGE_FOLDER} + networks: + - ecolyo-agent-network ports: - ${HTTPS_PORT}:${HTTPS_PORT} - 8090:8090 @@ -60,4 +85,7 @@ services: - DATABASE_HOST=database volumes: - db_data: \ No newline at end of file + db_data: + +networks: + ecolyo-agent-network: \ No newline at end of file diff --git a/go.mod b/go.mod index 6f731e4c0e51da8154808194ce57f0bc3ed82b47..0f8ad00874dc5106a17c233084d163e67fe537e7 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.15 require ( github.com/gorilla/mux v1.8.0 + github.com/meilisearch/meilisearch-go v0.20.1 github.com/swaggo/http-swagger v1.3.0 github.com/swaggo/swag v1.8.3 golang.org/x/oauth2 v0.0.0-20220630143837-2104d58473e0 diff --git a/go.sum b/go.sum index 97b6e2d25eda8a8ca66e0b56364c078f59857f9f..22f6658a70d06f336ff686829051601b8ee3f005 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,9 @@ github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6Xge github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs= github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -113,6 +114,8 @@ github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyr github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -138,7 +141,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -154,7 +156,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -212,6 +213,9 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= +github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -219,20 +223,22 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/meilisearch/meilisearch-go v0.20.1 h1:Lddkf3C/f/Uv0+eD2f9qtpykmK5E7IZStJpIV0UVxu4= +github.com/meilisearch/meilisearch-go v0.20.1/go.mod h1:jUGQlQNFYcni/mSG/d71utwqPuKG0bRT+63Xenw2B+0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI= github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -244,25 +250,28 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM= -github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe h1:K8pHPVoTgxFJt1lXuIzzOX7zZhZFldJQK/CgKx9BFIc= github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= -github.com/swaggo/http-swagger v1.2.7 h1:q0jLKqJRtmQzwmI2eHX8V6Hgr0TGg3IqBMDN78G6eQI= -github.com/swaggo/http-swagger v1.2.7/go.mod h1:FrQwV7rx+A5t11PIX8d+tFJa2GKx11RdAXQptllPQHg= github.com/swaggo/http-swagger v1.3.0 h1:1+6M4qRorIbdyTWTsGrwnb0r9jGK5dcWN82O6oY/yHQ= github.com/swaggo/http-swagger v1.3.0/go.mod h1:9glekdg40lwclrrKNRGgj/IMDxpNPZ3kzab4oPcF8EM= -github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI= github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= github.com/swaggo/swag v1.8.3 h1:3pZSSCQ//gAH88lfmxM3Cd1+JCsxV8Md6f36b9hrZ5s= github.com/swaggo/swag v1.8.3/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d h1:xS9QTPgKl9ewGsAOPc+xW7DeStJDqYPfisDmeSCcbco= +github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -284,6 +293,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -359,11 +369,11 @@ golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1 golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= @@ -386,7 +396,6 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= golang.org/x/oauth2 v0.0.0-20220630143837-2104d58473e0 h1:VnGaRqoLmqZH/3TMLJwYCEWkR4j1nuIU1U9TvbqsDUw= @@ -454,7 +463,6 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -538,7 +546,6 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= @@ -588,7 +595,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -711,7 +717,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -728,20 +733,14 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.3.3 h1:jXG9ANrwBc4+bMvBcSl8zCfPBaVoPyBEBshA8dA93X8= -gorm.io/driver/mysql v1.3.3/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.3.4 h1:/KoBMgsUHC3bExsekDcmNYaBnfH2WNeFuXqqrqMc98Q= gorm.io/driver/mysql v1.3.4/go.mod h1:s4Tq0KmD0yhPGHbZEwg1VPlH0vT/GBHJZorPzhcxBUE= -gorm.io/driver/sqlite v1.3.2 h1:nWTy4cE52K6nnMhv23wLmur9Y3qWbZvOBz+V4PrGAxg= -gorm.io/driver/sqlite v1.3.2/go.mod h1:B+8GyC9K7VgzJAcrcXMRPdnMcck+8FgJynEehEPM16U= gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ= gorm.io/driver/sqlite v1.3.6/go.mod h1:Sg1/pvnKtbQ7jLXxfZa+jSHvoX8hoZA8cn4xllOMTgE= -gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.5 h1:TnlF26wScKSvknUC/Rn8t0NLLM22fypYBlvj1+aH6dM= -gorm.io/gorm v1.23.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/auth/auth.go b/internal/auth/auth.go index fd469bd976ef40a065a9513654c1fe904fecbf08..23cfb6862d6c976a30c30aa1ffcad1718190a9ef 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -25,8 +25,9 @@ const ( var ( // AdminRole represents the role reserved for admins - AdminRole = common.StringValueFromEnv("ADMIN_ROLE", "ADMINS") - hostname = common.StringValueFromEnv("HOSTNAME", "ecolyobackoffice.127.0.0.1.nip.io") + AdminRole = common.StringValueFromEnv("ADMIN_ROLE", "ADMINS") + hostname = common.StringValueFromEnv("HOSTNAME", "ecolyobackoffice.127.0.0.1.nip.io") + SGEApiToken = common.StringValueFromEnv("SGE_API_TOKEN", "sgetoken") ) // User represents a logged in user @@ -116,6 +117,18 @@ func ValidateAuthMiddleware(next http.Handler, allowedRoles []string, checkXSRF return http.HandlerFunc(roleChecker) } +func SGEAuthMiddleware(next http.Handler) http.Handler { + tokenChecker := func(w http.ResponseWriter, r *http.Request) { + // Check API Token + if r.Header.Get("Authorization") != "Bearer "+SGEApiToken { + http.Error(w, "invalid token", http.StatusUnauthorized) + return + } + next.ServeHTTP(w, r) + } + return http.HandlerFunc(tokenChecker) +} + // HandleLogout remove the user from the cookie store func (m Manager) HandleLogout(w http.ResponseWriter, r *http.Request) { // Delete the auth cookie diff --git a/internal/common/common.go b/internal/common/common.go index 3ee2d9635c1200ec11750e2fcbc8a2820c83e302..9497fe81a905602d405657dff4701c224dc4dad1 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -172,6 +172,51 @@ func YearMonthFromRequest(r *http.Request) (year int, month int, err error) { return year, month, nil } +func IdFromRequest(r *http.Request) (id int, err error) { + vars := mux.Vars(r) + idStr := vars["id"] + + if idStr == "" { + return 0, errors.New("missing id") + } + + id, err = strconv.Atoi(idStr) + if err != nil { + return 0, errors.New("id is not an integer") + } + + return id, nil +} + +func PageLimitFromRequest(r *http.Request) (page int, limit int, err error) { + pageStr := r.URL.Query().Get("page") + limitStr := r.URL.Query().Get("limit") + + if pageStr == "" || limitStr == "" { + return 0, 0, errors.New("missing query element") + } + + page, err = strconv.Atoi(pageStr) + if err != nil { + return 0, 0, errors.New("page is not an integer") + } + limit, err = strconv.Atoi(limitStr) + if err != nil { + return 0, 0, errors.New("limite is not an integer") + } + + if page < 0 { + page = 0 + } + switch { + case limit > 100: + limit = 100 + case limit < 10: + limit = 10 + } + return page, limit, nil +} + //Get fluidType from Request func FluidTypeFromRequest(r *http.Request) (fluidtype int, err error) { vars := mux.Vars(r) @@ -188,6 +233,3 @@ func FluidTypeFromRequest(r *http.Request) (fluidtype int, err error) { return fluidtype, nil } - - - diff --git a/internal/models/consent.go b/internal/models/consent.go new file mode 100644 index 0000000000000000000000000000000000000000..e7ed2da030cfc55a18b42d4851d6019759c2ac21 --- /dev/null +++ b/internal/models/consent.go @@ -0,0 +1,212 @@ +package models + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "time" + + "forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/common" + "github.com/meilisearch/meilisearch-go" + "gorm.io/gorm" +) + +type Consent struct { + gorm.Model + Firstname string `json:"firstname"` + Lastname string `json:"lastname"` + Address string `json:"address"` + PointID int `json:"pointID"` + PostalCode string `json:"postalCode"` + InseeCode string `json:"inseeCode"` + EndDate time.Time `json:"endDate"` + ServiceID int `json:"serviceID,omitempty"` +} + +func (dh *DataHandler) GetConsentById(w http.ResponseWriter, r *http.Request) { + id, err := common.IdFromRequest(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + var consent Consent + err = dh.sqlClient.First(&consent, id).Error + if err != nil { + http.Error(w, "couldn't find consent", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(consent) + + log.Printf("| get consent | name : %v | %v", consent.Lastname, r.RemoteAddr) +} + +func (dh *DataHandler) PostConsent(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 consent Consent + err := decoder.Decode(&consent) + if err != nil { + http.Error(w, "couldn't parse body", http.StatusInternalServerError) + log.Println(err.Error()) + return + } + consent.EndDate = time.Now().AddDate(1, 0, 0) + + // Create a consent in SQL + err = dh.sqlClient.Create(&consent).Error + if err != nil { + http.Error(w, "couldn't create consent", http.StatusInternalServerError) + log.Println(err.Error()) + return + } + // Adding consent in Meilisearch + _, err = dh.meiliClient.Index("consents").AddDocuments(consent) + if err != nil { + log.Println(err) + http.Error(w, "error when saving new consent", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(consent) + + log.Printf("| new consent | name : %v | %v", consent.Lastname, r.RemoteAddr) +} + +func (dh *DataHandler) UpdateConsent(w http.ResponseWriter, r *http.Request) { + if r.Body == http.NoBody { + http.Error(w, "request body is empty", http.StatusBadRequest) + return + } + id, err := common.IdFromRequest(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // Find consent + var consent Consent + err = dh.sqlClient.First(&consent, id).Error + if err != nil { + http.Error(w, "couldn't find consent", http.StatusInternalServerError) + log.Println(err.Error()) + return + } + // Get service ID + decoder := json.NewDecoder(r.Body) + var body struct { + ServiceID int `json:"serviceID"` + } + err = decoder.Decode(&body) + if err != nil { + http.Error(w, "couldn't parse body", http.StatusInternalServerError) + return + } + if body.ServiceID <= 0 { + http.Error(w, "invalid service id", http.StatusBadRequest) + return + } + + // Update and save consent + consent.ServiceID = body.ServiceID + err = dh.sqlClient.Save(&consent).Error + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + log.Println(err.Error()) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(consent) + + log.Printf("| updated consent | name : %v | serviceID : %v | %v", consent.Lastname, consent.ServiceID, r.RemoteAddr) +} + +func (dh *DataHandler) DeleteConsentById(w http.ResponseWriter, r *http.Request) { + id, err := common.IdFromRequest(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + var consent = Consent{} + err = dh.sqlClient.First(&consent, id).Error + if err != nil { + http.Error(w, "couldn't find consent", http.StatusInternalServerError) + log.Println(err.Error()) + return + } + + // Update and save consent + consent.EndDate = time.Now() + err = dh.sqlClient.Save(&consent).Error + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + log.Println(err.Error()) + return + } + + dh.sqlClient.Delete(&consent) + + log.Printf("| deleted consent | id : %d | %v", id, r.RemoteAddr) +} + +func (dh *DataHandler) SearchConsent(w http.ResponseWriter, r *http.Request) { + search := r.URL.Query().Get("search") + if search != "" { + resp, err := dh.meiliClient.Index("consents").Search(search, &meilisearch.SearchRequest{ + Limit: 50, + }) + if err != nil { + http.Error(w, "error when searching consents", http.StatusInternalServerError) + log.Println(err.Error()) + return + } + + hits, err := json.Marshal(resp.Hits) + if err != nil { + fmt.Println("error:", err) + } + var consents []Consent + err = json.Unmarshal(hits, &consents) + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(consents) + + log.Printf("| searched consents | search : %v | %v", search, r.RemoteAddr) + } else { + page, limit, err := common.PageLimitFromRequest(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + var totalRows int64 + dh.sqlClient.Model(Consent{}).Count(&totalRows) + offset := page * limit + + var consents []Consent + dh.sqlClient.Offset(offset).Limit(limit).Find(&consents) + + var pagination struct { + TotalRows int64 `json:"totalRows"` + Rows []Consent `json:"rows"` + } + pagination.TotalRows = totalRows + pagination.Rows = consents + + w.Header().Set("Content-Type", "application/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/mailSubject.go b/internal/models/mailSubject.go index ba37ac11aff523e7c33368f71795eaa0d34670a7..556568b12ed959d4ad18a6faec7cbe21f40bb3de 100644 --- a/internal/models/mailSubject.go +++ b/internal/models/mailSubject.go @@ -34,7 +34,7 @@ func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Reque w.Header().Set("Content-Type", "application/json") var mailSubject MailSubject - err = dh.db.Where("year = ? AND month = ?", year, month).First(&mailSubject).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&mailSubject).Error if err != nil { // If not found, answer "not found" w.WriteHeader(http.StatusNotFound) @@ -70,11 +70,11 @@ func (dh *DataHandler) SaveMailSubject(w http.ResponseWriter, r *http.Request) { } // Check if this mailSubject exists - err = dh.db.Where("year = ? AND month = ?", mailSubject.Year, mailSubject.Month).First(&MailSubject{}).Error + err = dh.sqlClient.Where("year = ? AND month = ?", mailSubject.Year, mailSubject.Month).First(&MailSubject{}).Error if err != nil { // Create a mailSubject - err = dh.db.Create(&MailSubject{ + err = dh.sqlClient.Create(&MailSubject{ Year: mailSubject.Year, Month: mailSubject.Month, Subject: mailSubject.Subject, @@ -91,7 +91,7 @@ func (dh *DataHandler) SaveMailSubject(w http.ResponseWriter, r *http.Request) { } else { // Update object - err = dh.db.Model(&MailSubject{}).Where("year = ? AND month = ?", mailSubject.Year, mailSubject.Month).Update("subject", mailSubject.Subject).Error + err = dh.sqlClient.Model(&MailSubject{}).Where("year = ? AND month = ?", mailSubject.Year, mailSubject.Month).Update("subject", mailSubject.Subject).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -119,7 +119,7 @@ func (dh *DataHandler) DeleteMailSubject(w http.ResponseWriter, r *http.Request) return } - err = dh.db.Where("year = ? AND month = ?", year, month).Delete(&MailSubject{}).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).Delete(&MailSubject{}).Error if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return diff --git a/internal/models/models.go b/internal/models/models.go index 50f40e5dab13dae7dca6c52d5a256aeee8203259..607f8f8ed828a2124876716dc17645f771a86292 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -4,13 +4,15 @@ import ( "fmt" "forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/common" + "github.com/meilisearch/meilisearch-go" "gorm.io/driver/mysql" "gorm.io/driver/sqlite" "gorm.io/gorm" ) type DataHandler struct { - db *gorm.DB + sqlClient *gorm.DB + meiliClient *meilisearch.Client } var ( @@ -22,35 +24,75 @@ var ( // NewDataHandler init a DataHandler and returns a pointer to it func NewDataHandler() *DataHandler { - var db *gorm.DB + // SQL setup + var sqlClient *gorm.DB var err error if dbUser == "" || dbPassword == "" || dbName == "" { - db, err = gorm.Open(sqlite.Open("backoffice.db"), &gorm.Config{}) + sqlClient, err = gorm.Open(sqlite.Open("backoffice.db"), &gorm.Config{}) if err != nil { panic("failed to connect database") } } else { dsn := fmt.Sprintf("%v:%v@tcp(%v:3306)/%v?charset=utf8mb4&parseTime=True&loc=Local", dbUser, dbPassword, dbHost, dbName) - db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) + sqlClient, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") } } // Migrate the schema - db.AutoMigrate(&MailSubject{}) - db.AutoMigrate(&MonthlyInfo{}) - db.AutoMigrate(&MonthlyNews{}) - db.AutoMigrate(&Poll{}) - db.AutoMigrate(&PartnersInfo{}) - db.AutoMigrate(&Price{}) + sqlClient.AutoMigrate(&MailSubject{}) + sqlClient.AutoMigrate(&MonthlyInfo{}) + sqlClient.AutoMigrate(&MonthlyNews{}) + sqlClient.AutoMigrate(&Poll{}) + sqlClient.AutoMigrate(&PartnersInfo{}) + sqlClient.AutoMigrate(&Price{}) + sqlClient.AutoMigrate(&Consent{}) // Create default partner status - db.Create(&PartnersInfo{ + sqlClient.Create(&PartnersInfo{ GRDFFailure: false, EnedisFailure: false, EGLFailure: false, NotificationActivated: false, }) - return &DataHandler{db: db} + + // Meilisearch setup + meiliClient := meilisearch.NewClient(meilisearch.ClientConfig{ + Host: common.StringValueFromEnv("MEILI_HOST", ""), + APIKey: common.StringValueFromEnv("MEILI_MASTER_KEY", ""), + }) + + settings := meilisearch.Settings{ + DisplayedAttributes: []string{ + "ID", + "CreatedAt", + "firstname", + "lastname", + "pointID", + }, + SearchableAttributes: []string{ + "pointID", + "lastname", + "firstname", + }, + RankingRules: []string{ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + }, + TypoTolerance: &meilisearch.TypoTolerance{ + MinWordSizeForTypos: meilisearch.MinWordSizeForTypos{ + OneTypo: 4, + TwoTypos: 8, + }, + }, + } + + meiliClient.Index("consents").UpdateSettings(&settings) + + return &DataHandler{sqlClient: sqlClient, meiliClient: meiliClient} } diff --git a/internal/models/monthlyInfo.go b/internal/models/monthlyInfo.go index 5425f8b5e41b57a6c004aa76205d116f0fefa532..2f6b1da76838f5f2d3407fd5a54f3fe7379e857d 100644 --- a/internal/models/monthlyInfo.go +++ b/internal/models/monthlyInfo.go @@ -24,7 +24,7 @@ type MonthlyInfo struct { // @Router /api/admin/monthlyInfo [get] func (dh *DataHandler) GetAllMonthlyInfo(w http.ResponseWriter, r *http.Request) { var monthlyInfo []MonthlyInfo - dh.db.Find(&monthlyInfo) + dh.sqlClient.Find(&monthlyInfo) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(monthlyInfo) @@ -51,7 +51,7 @@ func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Reque w.Header().Set("Content-Type", "application/json") var monthlyInfo MonthlyInfo - err = dh.db.Where("year = ? AND month = ?", year, month).First(&monthlyInfo).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&monthlyInfo).Error if err != nil { // If not found, answer "not found" w.WriteHeader(http.StatusNotFound) @@ -87,11 +87,11 @@ func (dh *DataHandler) SaveMonthlyInfo(w http.ResponseWriter, r *http.Request) { } // Check if this monthlyInfo exists - err = dh.db.Where("year = ? AND month = ?", monthlyInfo.Year, monthlyInfo.Month).First(&MonthlyInfo{}).Error + err = dh.sqlClient.Where("year = ? AND month = ?", monthlyInfo.Year, monthlyInfo.Month).First(&MonthlyInfo{}).Error if err != nil { // Create a monthlyInfo - err = dh.db.Create(&MonthlyInfo{ + err = dh.sqlClient.Create(&MonthlyInfo{ Year: monthlyInfo.Year, Month: monthlyInfo.Month, Info: monthlyInfo.Info, @@ -109,14 +109,14 @@ func (dh *DataHandler) SaveMonthlyInfo(w http.ResponseWriter, r *http.Request) { } else { // Update info - err = dh.db.Model(&MonthlyInfo{}).Where("year = ? AND month = ?", monthlyInfo.Year, monthlyInfo.Month).Update("info", monthlyInfo.Info).Error + err = dh.sqlClient.Model(&MonthlyInfo{}).Where("year = ? AND month = ?", monthlyInfo.Year, monthlyInfo.Month).Update("info", monthlyInfo.Info).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return } // Update info - err = dh.db.Model(&MonthlyInfo{}).Where("year = ? AND month = ?", monthlyInfo.Year, monthlyInfo.Month).Update("image", monthlyInfo.Image).Error + err = dh.sqlClient.Model(&MonthlyInfo{}).Where("year = ? AND month = ?", monthlyInfo.Year, monthlyInfo.Month).Update("image", monthlyInfo.Image).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -144,7 +144,7 @@ func (dh *DataHandler) DeleteMonthlyInfo(w http.ResponseWriter, r *http.Request) return } - err = dh.db.Where("year = ? AND month = ?", year, month).Delete(&MonthlyInfo{}).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).Delete(&MonthlyInfo{}).Error if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return diff --git a/internal/models/monthlyNews.go b/internal/models/monthlyNews.go index 638df1c08975cb7cd271339776c1ba0365b9f2d2..eab06f0f1f029342267c49feff5fe88fae6a6e66 100644 --- a/internal/models/monthlyNews.go +++ b/internal/models/monthlyNews.go @@ -24,7 +24,7 @@ type MonthlyNews struct { // @Router /api/admin/monthlyNews [get] func (dh *DataHandler) GetAllMonthlyNews(w http.ResponseWriter, r *http.Request) { var monthlyNews []MonthlyNews - dh.db.Find(&monthlyNews) + dh.sqlClient.Find(&monthlyNews) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(monthlyNews) @@ -51,7 +51,7 @@ func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Reque w.Header().Set("Content-Type", "application/json") var monthlyNews MonthlyNews - err = dh.db.Where("year = ? AND month = ?", year, month).First(&monthlyNews).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&monthlyNews).Error if err != nil { // If not found, answer "not found" w.WriteHeader(http.StatusNotFound) @@ -87,7 +87,7 @@ func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) { } // Check if this monthlyNews exists - err = dh.db.Where("year = ? AND month = ?", monthlyNews.Year, monthlyNews.Month).First(&MonthlyNews{}).Error + err = dh.sqlClient.Where("year = ? AND month = ?", monthlyNews.Year, monthlyNews.Month).First(&MonthlyNews{}).Error // Default title if monthlyNews.Title == "" && monthlyNews.Content != "" { @@ -97,7 +97,7 @@ func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) { if err != nil { // Create a monthlyNews - err = dh.db.Create(&MonthlyNews{Year: monthlyNews.Year, Month: monthlyNews.Month, Title: monthlyNews.Title, Content: monthlyNews.Content}).Error + err = dh.sqlClient.Create(&MonthlyNews{Year: monthlyNews.Year, Month: monthlyNews.Month, Title: monthlyNews.Title, Content: monthlyNews.Content}).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -110,13 +110,13 @@ func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) { } else { // Update title - err = dh.db.Model(&MonthlyNews{}).Where("year = ? AND month = ?", monthlyNews.Year, monthlyNews.Month).Update("title", monthlyNews.Title).Error + err = dh.sqlClient.Model(&MonthlyNews{}).Where("year = ? AND month = ?", monthlyNews.Year, monthlyNews.Month).Update("title", monthlyNews.Title).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return } // Update content - err = dh.db.Model(&MonthlyNews{}).Where("year = ? AND month = ?", monthlyNews.Year, monthlyNews.Month).Update("content", monthlyNews.Content).Error + err = dh.sqlClient.Model(&MonthlyNews{}).Where("year = ? AND month = ?", monthlyNews.Year, monthlyNews.Month).Update("content", monthlyNews.Content).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -144,7 +144,7 @@ func (dh *DataHandler) DeleteMonthlyNews(w http.ResponseWriter, r *http.Request) return } - err = dh.db.Where("year = ? AND month = ?", year, month).Delete(&MonthlyNews{}).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).Delete(&MonthlyNews{}).Error if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return diff --git a/internal/models/monthlyReport.go b/internal/models/monthlyReport.go index a11c50f747ce908952e29b1374749b5b95af17bb..7ba6549e6555223363fdb6bab576e6187235b10e 100644 --- a/internal/models/monthlyReport.go +++ b/internal/models/monthlyReport.go @@ -81,20 +81,20 @@ func (dh *DataHandler) GetCurrentMonthlyReport(w http.ResponseWriter, r *http.Re func (dh *DataHandler) getMonthlyReport(year int, month int) (monthlyReport MonthlyReport, err error) { var monthlyInfo MonthlyInfo - dh.db.Where("year = ? AND month = ?", year, month).First(&monthlyInfo) + dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&monthlyInfo) var mailSubject MailSubject - err = dh.db.Where("year = ? AND month = ?", year, month).First(&mailSubject).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&mailSubject).Error if err != nil { // Build default object mailSubject.Subject = fmt.Sprintf("[Ecolyo] Votre bilan %s %v", getMonthNameWithPrep(month-1), year) } var monthlyNews MonthlyNews - dh.db.Where("year = ? AND month = ?", year, month).First(&monthlyNews) + dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&monthlyNews) var poll Poll - dh.db.Where("year = ? AND month = ?", year, month).First(&poll) + dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&poll) monthlyReport = MonthlyReport{ Year: year, diff --git a/internal/models/partnersInfo.go b/internal/models/partnersInfo.go index 35652e7cdf9ed941b72140b7f383a82b4598608a..c21596a839935683c952c24c07dec5ca5f22c102 100644 --- a/internal/models/partnersInfo.go +++ b/internal/models/partnersInfo.go @@ -10,11 +10,11 @@ import ( ) 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"` + 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 @@ -27,7 +27,7 @@ type PartnersInfo struct { // @Router /api/common/partnersInfo [get] func (dh *DataHandler) GetPartnersInfo(w http.ResponseWriter, r *http.Request) { var partnersInfo PartnersInfo - err := dh.db.First(&partnersInfo).Error + err := dh.sqlClient.First(&partnersInfo).Error if errors.Is(err, gorm.ErrRecordNotFound) { http.Error(w, "partners status not found", http.StatusNotFound) @@ -66,7 +66,7 @@ func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request) var updatedPartnersInfo PartnersInfo - err = dh.db.First(&updatedPartnersInfo).Error + err = dh.sqlClient.First(&updatedPartnersInfo).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -77,7 +77,7 @@ func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request) updatedPartnersInfo.EGLFailure = partnersInfo.EGLFailure updatedPartnersInfo.NotificationActivated = partnersInfo.NotificationActivated - dh.db.Save(&updatedPartnersInfo) + dh.sqlClient.Save(&updatedPartnersInfo) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(partnersInfo) diff --git a/internal/models/poll.go b/internal/models/poll.go index 76acbc8dac5585019cc47f8c6f28945fcb5a235e..02bb2abb4df55c844efa6d6f53f6533896eb1d55 100644 --- a/internal/models/poll.go +++ b/internal/models/poll.go @@ -24,7 +24,7 @@ type Poll struct { // @Router /api/admin/poll [get] func (dh *DataHandler) GetAllPolls(w http.ResponseWriter, r *http.Request) { var polls []Poll - err := dh.db.Find(&polls).Error + err := dh.sqlClient.Find(&polls).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -55,7 +55,7 @@ func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var poll Poll - err = dh.db.Where("year = ? AND month = ?", year, month).First(&poll).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&poll).Error if err != nil { // If not found, answer "not found" w.WriteHeader(http.StatusNotFound) @@ -91,11 +91,11 @@ func (dh *DataHandler) SavePoll(w http.ResponseWriter, r *http.Request) { } // Check if this poll exists - err = dh.db.Where("year = ? AND month = ?", poll.Year, poll.Month).First(&Poll{}).Error + err = dh.sqlClient.Where("year = ? AND month = ?", poll.Year, poll.Month).First(&Poll{}).Error if err != nil { // Create a poll - err = dh.db.Create(&Poll{Year: poll.Year, Month: poll.Month, Question: poll.Question, Link: poll.Link}).Error + err = dh.sqlClient.Create(&Poll{Year: poll.Year, Month: poll.Month, Question: poll.Question, Link: poll.Link}).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -107,13 +107,13 @@ func (dh *DataHandler) SavePoll(w http.ResponseWriter, r *http.Request) { } else { // Update question - err = dh.db.Model(&Poll{}).Where("year = ? AND month = ?", poll.Year, poll.Month).Update("question", poll.Question).Error + err = dh.sqlClient.Model(&Poll{}).Where("year = ? AND month = ?", poll.Year, poll.Month).Update("question", poll.Question).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return } // Update link - err = dh.db.Model(&Poll{}).Where("year = ? AND month = ?", poll.Year, poll.Month).Update("link", poll.Link).Error + err = dh.sqlClient.Model(&Poll{}).Where("year = ? AND month = ?", poll.Year, poll.Month).Update("link", poll.Link).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -141,7 +141,7 @@ func (dh *DataHandler) DeletePoll(w http.ResponseWriter, r *http.Request) { return } - err = dh.db.Where("year = ? AND month = ?", year, month).Delete(&Poll{}).Error + err = dh.sqlClient.Where("year = ? AND month = ?", year, month).Delete(&Poll{}).Error if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return diff --git a/internal/models/price.go b/internal/models/price.go index 013c5d5b41f85cabe738c95949c9425ad05a2a94..b5130d93a9f02ea2fbb416d1edbfa27287ca354a 100644 --- a/internal/models/price.go +++ b/internal/models/price.go @@ -11,10 +11,10 @@ import ( ) type Price struct { - FluidType int `json:"fluidType"` - Price float32 `json:"price"` - StartDate string `json:"startDate"` - EndDate string `json:"endDate"` + FluidType int `json:"fluidType"` + Price float32 `json:"price"` + StartDate string `json:"startDate"` + EndDate string `json:"endDate"` gorm.Model } @@ -28,7 +28,7 @@ type Price struct { // @Router /api/common/prices [get] func (dh *DataHandler) GetAllPrices(w http.ResponseWriter, r *http.Request) { var prices []Price - dh.db.Find(&prices) + dh.sqlClient.Find(&prices) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(prices) @@ -52,17 +52,16 @@ func (dh *DataHandler) GetPricesByFluid(w http.ResponseWriter, r *http.Request) } var price []Price w.Header().Set("Content-Type", "application/json") - err = dh.db.Where("fluid_type = ? ", fluidtype).Order("start_date desc").Find(&price).Error + err = dh.sqlClient.Where("fluid_type = ? ", fluidtype).Order("start_date desc").Find(&price).Error if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } json.NewEncoder(w).Encode(price) - log.Printf("| Get prices by fluid : %v | %v",fluidtype, r.RemoteAddr) + log.Printf("| Get prices by fluid : %v | %v", fluidtype, r.RemoteAddr) } - // SavePrice godoc // @Summary Add a new price entry // @Description Add a new price entry @@ -90,13 +89,13 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) { } // Check if this price exists - err = dh.db.Where("fluid_type = ? AND start_date = ?", price.FluidType, price.StartDate).First(&Price{}).Error + err = dh.sqlClient.Where("fluid_type = ? AND start_date = ?", price.FluidType, price.StartDate).First(&Price{}).Error if err != nil { println("Price does not exist in database") //Gets the last price for this fluid var lastPrice Price - err = dh.db.Where("fluid_type = ?", price.FluidType).Order("start_date desc").Limit(1).Find(&lastPrice).Error + err = dh.sqlClient.Where("fluid_type = ?", price.FluidType).Order("start_date desc").Limit(1).Find(&lastPrice).Error if err != nil { println("Failed to get last price for this fluid") w.WriteHeader(http.StatusInternalServerError) @@ -107,15 +106,15 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) { updatedEndDate := t.Add(-1 * time.Minute).Format(time.RFC3339) lastPrice.EndDate = updatedEndDate - dh.db.Save(&lastPrice) + dh.sqlClient.Save(&lastPrice) log.Printf("updated last price") - + // Create a new price - err = dh.db.Create(&Price{ - FluidType: price.FluidType, - Price: price.Price, - StartDate: price.StartDate, - EndDate: "", + err = dh.sqlClient.Create(&Price{ + FluidType: price.FluidType, + Price: price.Price, + StartDate: price.StartDate, + EndDate: "", }).Error if err != nil { println("Failed to create price") @@ -132,7 +131,7 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) { priceToUpdate := price isEditable := false // If price is not included in the last 3 editable prices, throw error - err = dh.db.Where("fluid_type = ? ", price.FluidType).Order("start_date desc").Limit(3).Find(&editablePrices).Error + err = dh.sqlClient.Where("fluid_type = ? ", price.FluidType).Order("start_date desc").Limit(3).Find(&editablePrices).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -143,14 +142,14 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) { isEditable = true } } - + if isEditable == false { w.WriteHeader(http.StatusForbidden) log.Printf("Unallowed to edit price because is not included in the the last 3 editable prices") return } // Update existing price - err = dh.db.Model(&Price{}).Where("start_date = ? AND fluid_type = ?", priceToUpdate.StartDate, priceToUpdate.FluidType).Update("price", priceToUpdate.Price).Error + err = dh.sqlClient.Model(&Price{}).Where("start_date = ? AND fluid_type = ?", priceToUpdate.StartDate, priceToUpdate.FluidType).Update("price", priceToUpdate.Price).Error if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -161,4 +160,3 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) { 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 8dcc835e4bb0ec67f51b4c604d2a641979e7c182..a3d236f786a52a1fc53aa85907a6c89f3cd20239 100644 --- a/internal/rootmux/rootmux.go +++ b/internal/rootmux/rootmux.go @@ -74,6 +74,15 @@ func CreateRootMux() RootMux { apiAdmin.HandleFunc("/prices", dh.SavePrice).Methods(http.MethodPut) + apiAdmin.HandleFunc("/consent", dh.SearchConsent).Methods(http.MethodGet) + + apiSGE := r.PathPrefix("/api/sge").Subrouter() + apiSGE.Use(auth.SGEAuthMiddleware) + apiSGE.HandleFunc("/consent", dh.PostConsent).Methods(http.MethodPost) + apiSGE.HandleFunc("/consent/{id}", dh.GetConsentById).Methods(http.MethodGet) + apiSGE.HandleFunc("/consent/{id}", dh.UpdateConsent).Methods(http.MethodPut) + apiSGE.HandleFunc("/consent/{id}", dh.DeleteConsentById).Methods(http.MethodDelete) + // Swagger r.PathPrefix("/swagger").Handler(httpSwagger.WrapHandler) diff --git a/internal/rootmux/rootmux_test.go b/internal/rootmux/rootmux_test.go index 63ba50e8a032eb54758efca018aa5edc71a0a51c..d6ee76e3c989b05859f3af0af360527cdacbbc1f 100644 --- a/internal/rootmux/rootmux_test.go +++ b/internal/rootmux/rootmux_test.go @@ -8,6 +8,7 @@ import ( "net/url" "os" "testing" + "time" "forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/auth" "forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/mocks" @@ -28,6 +29,8 @@ var ( newPollStr string partnersInfo = models.PartnersInfo{ID: 1, GRDFFailure: false, EnedisFailure: false, EGLFailure: true, NotificationActivated: true} partnersInfoStr string + consent = models.Consent{Firstname: "Foo", Lastname: "Bar", PointID: 123456} + consentStr string noH map[string]string ) @@ -45,6 +48,9 @@ func TestMain(m *testing.M) { os.Setenv("TOKEN_URL", oAuth2Server.URL+"/token") os.Setenv("USERINFO_URL", oAuth2Server.URL+"/userinfo") os.Setenv("LOGOUT_URL", oAuth2Server.URL+"/logout") + os.Setenv("MEILI_MASTER_KEY", "masterkey") + os.Setenv("MEILI_HOST", "http://localhost:7700") + os.Setenv("SGE_API_TOKEN", "sgeApiToken") // Setup the token manager to use debug mode os.Setenv("DEBUG_MODE", "true") @@ -61,6 +67,8 @@ func TestMain(m *testing.M) { partnersInfoStr = string(partnersInfoBytes) newPollBytes, _ := json.Marshal(newPoll) newPollStr = string(newPollBytes) + consentBytes, _ := json.Marshal(consent) + consentStr = string(consentBytes) code := m.Run() // Remove the database @@ -75,10 +83,11 @@ func TestAll(t *testing.T) { oauth2Tests(t) os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth") // Set the server to access the correct OAuth2Endpoint unloggedTests(t) - os.Setenv("USERINFO_URL", oAuth2Server.URL+"/admininfo") adminTests(t) + // SGE API tests + sgeTests(t) } /** @@ -212,6 +221,48 @@ func adminTests(t *testing.T) { do("GET", "/api/admin/monthlyNews", noH, "", http.StatusUnauthorized, "error extracting token") // Try to get a poll again (must fail) do("GET", "/api/admin/poll", noH, "", http.StatusUnauthorized, "error extracting token") + +} + +func sgeTests(t *testing.T) { + // Create the tester + 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") + // Try to get a consent (must fail) + do("GET", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token") + // Try to update a consent (must fail) + do("PUT", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token") + // Try to delete a consent (must fail) + do("DELETE", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token") + + // Create correct authorization header + sgeApiHeader := map[string]string{"Authorization": "Bearer " + auth.SGEApiToken} + // Try to create a consent (must pass) + do("POST", "/api/sge/consent", sgeApiHeader, consentStr, http.StatusCreated, `{"ID":1`) + // Wait for new documents to be indexed + time.Sleep(1 * time.Second) + // Try to update a consent (must pass) + do("PUT", "/api/sge/consent/1", sgeApiHeader, `{"serviceId":123456}`, http.StatusOK, `{"ID":1`) + // Try to get a consent (must pass) + do("GET", "/api/sge/consent/1", sgeApiHeader, `{"serviceId":123456}`, http.StatusOK, `{"ID":1`) + + // 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":1,"rows":[{"ID":1`) + // Try to search for a consent (must pass) + do("GET", "/api/admin/consent?search=123456", xsrfHeader, "", http.StatusOK, `[{"ID":1`) + // Try to delete a consent (must pass) + do("DELETE", "/api/sge/consent/1", sgeApiHeader, "", http.StatusOK, "") + } func createTester(t *testing.T) (*httptest.Server, tester.DoFn, tester.DoFn) { diff --git a/start-meilisearch-test-and-build.sh b/start-meilisearch-test-and-build.sh new file mode 100755 index 0000000000000000000000000000000000000000..cfe1951e27df78052bb1554c28cf097c123085a8 --- /dev/null +++ b/start-meilisearch-test-and-build.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -e + +# Start the process +meilisearch & + +# Get dependencies and run tests +go version +go get -d -v +CGO_ENABLED=1 go test ./... + +# Build the binary +CGO_ENABLED=0 go build \ + -ldflags='-w -s -extldflags "-static"' -a \ + -o /app/backoffice-server .