Skip to content
Snippets Groups Projects
Commit 999780b7 authored by Bastien DUMONT's avatar Bastien DUMONT :angel:
Browse files

feat(grdf): fetch access token every two hours

parent aa9eb32c
Branches
No related tags found
2 merge requests!108chore(release): Ecolyo 3.1.0,!104feat(grdf): fetch access token every two hours
...@@ -20,4 +20,8 @@ DATABASE_USER ...@@ -20,4 +20,8 @@ DATABASE_USER
DATABASE_PASSWORD DATABASE_PASSWORD
DATABASE_NAME DATABASE_NAME
# rename this to backoffice token ?
SGE_API_TOKEN SGE_API_TOKEN
GRDF_CLIENT_ID
GRDF_CLIENT_SECRET
...@@ -14,7 +14,7 @@ services: ...@@ -14,7 +14,7 @@ services:
variables: variables:
DOCKER_DRIVER: overlay2 DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: "" DOCKER_TLS_CERTDIR: ''
GIT_STRATEGY: clone GIT_STRATEGY: clone
GIT_DEPTH: 0 GIT_DEPTH: 0
...@@ -89,10 +89,10 @@ sonarqube: ...@@ -89,10 +89,10 @@ sonarqube:
- dev - dev
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/sonarsource/sonar-scanner-cli:4 image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/sonarsource/sonar-scanner-cli:4
variables: variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache SONAR_USER_HOME: '${CI_PROJECT_DIR}/.sonar' # Defines the location of the analysis task cache
GIT_DEPTH: "0" # T GIT_DEPTH: '0' # T
cache: cache:
key: "${CI_JOB_NAME}" key: '${CI_JOB_NAME}'
paths: paths:
- .sonar/cache - .sonar/cache
script: script:
...@@ -114,10 +114,10 @@ sonarqube-mr: ...@@ -114,10 +114,10 @@ sonarqube-mr:
- merge_requests - merge_requests
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/sonarsource/sonar-scanner-cli:4 image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/sonarsource/sonar-scanner-cli:4
variables: variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache SONAR_USER_HOME: '${CI_PROJECT_DIR}/.sonar' # Defines the location of the analysis task cache
GIT_DEPTH: "0" # T GIT_DEPTH: '0' # T
cache: cache:
key: "${CI_JOB_NAME}" key: '${CI_JOB_NAME}'
paths: paths:
- .sonar/cache - .sonar/cache
script: script:
...@@ -142,6 +142,8 @@ deploy_rec: ...@@ -142,6 +142,8 @@ deploy_rec:
- sed -i "s/{{CLIENT_ID}}/$REC_CLIENT_ID/" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s/{{CLIENT_ID}}/$REC_CLIENT_ID/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{CLIENT_SECRET}}/$REC_CLIENT_SECRET/" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s/{{CLIENT_SECRET}}/$REC_CLIENT_SECRET/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{SGE_API_TOKEN}}/$REC_SGE_API_TOKEN/" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s/{{SGE_API_TOKEN}}/$REC_SGE_API_TOKEN/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{GRDF_CLIENT_ID}}/$GRDF_CLIENT_ID/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{GRDF_CLIENT_SECRET}}/$GRDF_CLIENT_SECRET/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{HOSTNAME}}/ecolyo-agent-rec.apps.grandlyon.com/g" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s/{{HOSTNAME}}/ecolyo-agent-rec.apps.grandlyon.com/g" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s+{{AUTH_URL}}+https://connexion-rec.grandlyon.fr/IdPOAuth2/authorize/oidc-rec-2+" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s+{{AUTH_URL}}+https://connexion-rec.grandlyon.fr/IdPOAuth2/authorize/oidc-rec-2+" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s+{{USERINFO_URL}}+https://connexion-rec.grandlyon.fr/IdPOAuth2/userinfo/oidc-rec-2+" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s+{{USERINFO_URL}}+https://connexion-rec.grandlyon.fr/IdPOAuth2/userinfo/oidc-rec-2+" ./k8s/secrets/ecolyo-agent-server-config.yml
...@@ -172,6 +174,8 @@ deploy_prod: ...@@ -172,6 +174,8 @@ deploy_prod:
- sed -i "s/{{CLIENT_ID}}/$PROD_CLIENT_ID/" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s/{{CLIENT_ID}}/$PROD_CLIENT_ID/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{CLIENT_SECRET}}/$PROD_CLIENT_SECRET/" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s/{{CLIENT_SECRET}}/$PROD_CLIENT_SECRET/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{SGE_API_TOKEN}}/$PROD_SGE_API_TOKEN/" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s/{{SGE_API_TOKEN}}/$PROD_SGE_API_TOKEN/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{GRDF_CLIENT_ID}}/$GRDF_CLIENT_ID/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{GRDF_CLIENT_SECRET}}/$GRDF_CLIENT_SECRET/" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s/{{HOSTNAME}}/ecolyo-agent.apps.grandlyon.com/g" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s/{{HOSTNAME}}/ecolyo-agent.apps.grandlyon.com/g" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s+{{AUTH_URL}}+https://connexion.grandlyon.fr/IdPOAuth2/authorize/oidc-2+" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s+{{AUTH_URL}}+https://connexion.grandlyon.fr/IdPOAuth2/authorize/oidc-2+" ./k8s/secrets/ecolyo-agent-server-config.yml
- sed -i "s+{{USERINFO_URL}}+https://connexion.grandlyon.fr/IdPOAuth2/userinfo/oidc-2+" ./k8s/secrets/ecolyo-agent-server-config.yml - sed -i "s+{{USERINFO_URL}}+https://connexion.grandlyon.fr/IdPOAuth2/userinfo/oidc-2+" ./k8s/secrets/ecolyo-agent-server-config.yml
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
}, },
"peacock.color": "#32f0ff", "peacock.color": "#32f0ff",
"cSpell.words": [ "cSpell.words": [
"adict",
"admininfo", "admininfo",
"animatorinfo", "animatorinfo",
"backoffice", "backoffice",
......
package models
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"strings"
"time"
"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
"gorm.io/gorm"
)
type GrdfAccessToken struct {
AccessToken string `json:"access_token"`
FetchedAt time.Time `json:"fetched_at"`
}
// Fetches GRDF auth API for an access token and save it in DB
func FetchGRDFAuthAPI() {
log.Println("| Calling GRDF auth API")
dh := NewDataHandler()
reqBody := url.Values{
"scope": {"/adict/v2"},
"grant_type": {"client_credentials"},
"client_id": {os.Getenv("GRDF_CLIENT_ID")},
"client_secret": {os.Getenv("GRDF_CLIENT_SECRET")},
}
client := &http.Client{}
req, err := http.NewRequest(http.MethodPost, "https://adict-connexion.grdf.fr/oauth2/aus5y2ta2uEHjCWIR417/v1/token", strings.NewReader(reqBody.Encode()))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
return
}
var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
fmt.Println("Error unmarshaling JSON:", err)
return
}
accessToken, ok := result["access_token"].(string)
if !ok {
fmt.Println("Access token not found in response")
return
}
dh.WriteAccessToken(accessToken)
}
// Writes a new access token to the database
func (dh *DataHandler) WriteAccessToken(token string) {
result := dh.sqlClient.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&GrdfAccessToken{}).Updates(&GrdfAccessToken{
AccessToken: token,
FetchedAt: time.Now(),
})
if result.Error != nil {
log.Println("| Error updating GRDF access token")
log.Println(result.Error)
} else {
log.Println("| New GRDF access token written")
}
}
func (dh *DataHandler) GetGrdfAccessToken(w http.ResponseWriter, r *http.Request) {
var token GrdfAccessToken
err := dh.sqlClient.First(&token).Error
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set(constants.ContentType, constants.Json)
json.NewEncoder(w).Encode(token)
log.Printf("| get partnersInfo | %v", r.RemoteAddr)
}
...@@ -50,6 +50,7 @@ func NewDataHandler() *DataHandler { ...@@ -50,6 +50,7 @@ func NewDataHandler() *DataHandler {
sqlClient.AutoMigrate(&Price{}) sqlClient.AutoMigrate(&Price{})
sqlClient.AutoMigrate(&SgeConsent{}) sqlClient.AutoMigrate(&SgeConsent{})
sqlClient.AutoMigrate(&GrdfConsent{}) sqlClient.AutoMigrate(&GrdfConsent{})
sqlClient.AutoMigrate(&GrdfAccessToken{})
// Check if partners info already exists // Check if partners info already exists
var partnersInfo PartnersInfo var partnersInfo PartnersInfo
...@@ -78,5 +79,16 @@ func NewDataHandler() *DataHandler { ...@@ -78,5 +79,16 @@ func NewDataHandler() *DataHandler {
}) })
} }
// check if access token already exists
var accessToken GrdfAccessToken
err = sqlClient.First(&accessToken).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
// Create default access token
sqlClient.Create(&GrdfAccessToken{
AccessToken: "",
FetchedAt: time.Now(),
})
}
return &DataHandler{sqlClient: sqlClient} return &DataHandler{sqlClient: sqlClient}
} }
...@@ -64,5 +64,4 @@ func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request) ...@@ -64,5 +64,4 @@ func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request)
w.Header().Set(constants.ContentType, constants.Json) w.Header().Set(constants.ContentType, constants.Json)
json.NewEncoder(w).Encode(partnersInfo) json.NewEncoder(w).Encode(partnersInfo)
log.Printf("| updated partnersInfo | %v", r.RemoteAddr) log.Printf("| updated partnersInfo | %v", r.RemoteAddr)
} }
...@@ -90,6 +90,7 @@ func CreateRootMux() RootMux { ...@@ -90,6 +90,7 @@ func CreateRootMux() RootMux {
r.Post("/consent", dh.PostGrdfConsent) r.Post("/consent", dh.PostGrdfConsent)
r.Get("/consent/{id}", dh.GetGrdfConsentById) r.Get("/consent/{id}", dh.GetGrdfConsentById)
r.Delete("/consent/{id}", dh.DeleteGrdfConsentById) r.Delete("/consent/{id}", dh.DeleteGrdfConsentById)
r.Get("/access-token", dh.GetGrdfAccessToken)
}) })
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { /** handles Oauth2 redirection */ }) r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { /** handles Oauth2 redirection */ })
......
...@@ -60,7 +60,7 @@ func newManager(keyfile string, debug bool) manager { ...@@ -60,7 +60,7 @@ func newManager(keyfile string, debug bool) manager {
} }
} }
// Token represents a token containting data // Token represents a token containing data
type Token struct { type Token struct {
ExpiresAt int64 ExpiresAt int64
IssuedAt int64 `json:"iat,omitempty"` IssuedAt int64 `json:"iat,omitempty"`
......
...@@ -20,4 +20,6 @@ stringData: ...@@ -20,4 +20,6 @@ stringData:
SGE_API_TOKEN: {{SGE_API_TOKEN}} SGE_API_TOKEN: {{SGE_API_TOKEN}}
TOKEN_URL: {{TOKEN_URL}} TOKEN_URL: {{TOKEN_URL}}
USERINFO_URL: {{USERINFO_URL}} USERINFO_URL: {{USERINFO_URL}}
GRDF_CLIENT_ID: {{GRDF_CLIENT_ID}}
GRDF_CLIENT_SECRET: {{GRDF_CLIENT_SECRET}}
type: Opaque type: Opaque
...@@ -4,11 +4,13 @@ import ( ...@@ -4,11 +4,13 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
"time"
"log" "log"
"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/mocks" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/mocks"
"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/models"
"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/rootmux" "forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/rootmux"
"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"
) )
...@@ -37,6 +39,24 @@ func main() { ...@@ -37,6 +39,24 @@ func main() {
mockOAuth2Port := ":8090" mockOAuth2Port := ":8090"
go http.ListenAndServe(mockOAuth2Port, mocks.CreateMockOAuth2()) go http.ListenAndServe(mockOAuth2Port, mocks.CreateMockOAuth2())
fmt.Println("Mock OAuth2 server Listening on: http://localhost" + mockOAuth2Port) fmt.Println("Mock OAuth2 server Listening on: http://localhost" + mockOAuth2Port)
// Call the function immediately when the server starts
models.FetchGRDFAuthAPI()
// then call GRDF auth api every two hours
ticker := time.NewTicker(time.Hour * 2)
quit := make(chan struct{})
go func() {
for {
select {
case <-ticker.C:
models.FetchGRDFAuthAPI()
case <-quit:
ticker.Stop()
return
}
}
}()
} }
// Serve locally with https // Serve locally with https
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment