package oauth2 import ( "clapclap/internal/ginctx" "clapclap/internal/models" "encoding/json" "errors" "io" "net/http" "time" "clapclap/internal/uuid" "github.com/gin-gonic/gin" "golang.org/x/oauth2" ) func (a *Authenticator) Ft() { a.states = map[string]stateValue{} a.oauth2Config = oauth2ConfigFor("FT") a.duration = 5 * time.Minute a.authenticate = ftAuthenticate a.register = ftRegister } func ftRegister(c *gin.Context, token *oauth2.Token) { // fetch 42 data data, err := get42UserData(token) if err != nil { OAuth2Error(c, err, "Failed to communicate with 42 API") return } id := uuid.New() user := models.User{ Base: models.Base{ID: id}, Username: data["login"].(string) + "@ft", Email: data["email"].(string), Avatar: data["image"].(map[string]any)["link"].(string), IsFt: true, IsVerified: true, } // check if user is registered in clap clap repo, err := ginctx.GetRepo(c, "repo") if err != nil { OAuth2Error(c, err, "Internal error") return } err = repo.CreateUser(&user, "") if err != nil { OAuth2Error(c, err, "Failed to create 42 user profile") return } c.Set("userID", user.ID) c.Next() } func ftAuthenticate(c *gin.Context, token *oauth2.Token) { // fetch 42 data data, err := get42UserData(token) if err != nil { OAuth2Error(c, err, "Failed to communicate with 42 API") return } username, ok := data["login"].(string) if !ok { // TODO log that there is a missing login field for backend OAuth2Error(c, errors.New("no login field"), "Invalid data received from 42") return } username = username + "@ft" // check if user is registered in clap clap repo, err := ginctx.GetRepo(c, "repo") if err != nil { OAuth2Error(c, err, "Internal error") return } user, err := repo.Find42UserByUsername(username, nil) if err != nil { OAuth2Error(c, err, "User not found in system") return } c.Set("userID", user.ID) c.Next() } func get42UserData(token *oauth2.Token) (map[string]any, error) { // dispatch http request method := "GET" // TODO (pipo) : no magic strings req, err := http.NewRequest(method, "https://api.intra.42.fr/v2/me", nil) if err != nil { return nil, err } req.Header.Set("Authorization", "Bearer "+token.AccessToken) res, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer res.Body.Close() bytes, err := io.ReadAll(res.Body) if err != nil { return nil, err } // parse response body var data map[string]any if err := json.Unmarshal(bytes, &data); err != nil { return nil, err } return data, nil }