From f1b7589b2936335957a6a1da1eea3d66233ad0ce Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Sat, 26 Aug 2023 08:53:24 +0300 Subject: refactor: reorganizing packages Former-commit-id: 99410223654c2a5ffc15fdab6ec3e921b5410cba --- backend/handlers/login.go | 166 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 backend/handlers/login.go (limited to 'backend/handlers/login.go') diff --git a/backend/handlers/login.go b/backend/handlers/login.go new file mode 100644 index 0000000..4b151c2 --- /dev/null +++ b/backend/handlers/login.go @@ -0,0 +1,166 @@ +package handlers + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "time" + + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v4" + "github.com/pektezol/leastportalshub/backend/database" + "github.com/pektezol/leastportalshub/backend/models" + "github.com/solovev/steam_go" +) + +type LoginResponse struct { + Token string `json:"token"` +} + +// Login +// +// @Description Get (redirect) login page for Steam auth. +// @Tags login +// @Accept json +// @Produce json +// @Success 200 {object} models.Response{data=LoginResponse} +// @Failure 400 {object} models.Response +// @Router /login [get] +func Login(c *gin.Context) { + openID := steam_go.NewOpenId(c.Request) + switch openID.Mode() { + case "": + c.Redirect(http.StatusMovedPermanently, openID.AuthUrl()) + case "cancel": + c.Redirect(http.StatusMovedPermanently, "/") + default: + steamID, err := openID.ValidateAndGetId() + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) + return + } + // Create user if new + var checkSteamID int64 + database.DB.QueryRow("SELECT steam_id FROM users WHERE steam_id = $1", steamID).Scan(&checkSteamID) + // User does not exist + if checkSteamID == 0 { + user, err := GetPlayerSummaries(steamID, os.Getenv("API_KEY")) + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) + return + } + // Empty country code check + if user.LocCountryCode == "" { + user.LocCountryCode = "XX" + } + // Insert new user to database + database.DB.Exec(`INSERT INTO users (steam_id, user_name, avatar_link, country_code) + VALUES ($1, $2, $3, $4)`, steamID, user.PersonaName, user.AvatarFull, user.LocCountryCode) + } + moderator := false + rows, _ := database.DB.Query("SELECT title_name FROM titles t INNER JOIN user_titles ut ON t.id=ut.title_id WHERE ut.user_id = $1", steamID) + for rows.Next() { + var title string + rows.Scan(&title) + if title == "Moderator" { + moderator = true + } + } + // Generate JWT token + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "sub": steamID, + "exp": time.Now().Add(time.Hour * 24 * 30).Unix(), + "mod": moderator, + }) + // Sign and get the complete encoded token as a string using the secret + tokenString, err := token.SignedString([]byte(os.Getenv("SECRET_KEY"))) + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrorResponse("Failed to generate token.")) + return + } + c.SetCookie("token", tokenString, 3600*24*30, "/", "", true, true) + c.Redirect(http.StatusTemporaryRedirect, "/") + // c.JSON(http.StatusOK, models.Response{ + // Success: true, + // Message: "Successfully generated token.", + // Data: LoginResponse{ + // Token: tokenString, + // }, + // }) + return + } +} + +// GET Token +// +// @Description Gets the token cookie value from the user. +// @Tags auth +// @Produce json +// +// @Success 200 {object} models.Response{data=LoginResponse} +// @Failure 404 {object} models.Response +// @Router /token [get] +func GetCookie(c *gin.Context) { + cookie, err := c.Cookie("token") + if err != nil { + c.JSON(http.StatusNotFound, models.ErrorResponse("No token cookie found.")) + return + } + c.JSON(http.StatusOK, models.Response{ + Success: true, + Message: "Token cookie successfully retrieved.", + Data: LoginResponse{ + Token: cookie, + }, + }) +} + +// DELETE Token +// +// @Description Deletes the token cookie from the user. +// @Tags auth +// @Produce json +// +// @Success 200 {object} models.Response{data=LoginResponse} +// @Failure 404 {object} models.Response +// @Router /token [delete] +func DeleteCookie(c *gin.Context) { + cookie, err := c.Cookie("token") + if err != nil { + c.JSON(http.StatusNotFound, models.ErrorResponse("No token cookie found.")) + return + } + c.SetCookie("token", "", -1, "/", "", true, true) + c.JSON(http.StatusOK, models.Response{ + Success: true, + Message: "Token cookie successfully deleted.", + Data: LoginResponse{ + Token: cookie, + }, + }) +} + +func GetPlayerSummaries(steamId, apiKey string) (*models.PlayerSummaries, error) { + url := fmt.Sprintf("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=%s&steamids=%s", apiKey, steamId) + resp, err := http.Get(url) + if err != nil { + return nil, err + } + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + type Result struct { + Response struct { + Players []models.PlayerSummaries `json:"players"` + } `json:"response"` + } + var data Result + if err := json.Unmarshal(body, &data); err != nil { + return nil, err + } + return &data.Response.Players[0], err +} -- cgit v1.2.3