diff options
| author | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2023-01-18 22:12:38 +0300 |
|---|---|---|
| committer | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2023-01-18 22:12:38 +0300 |
| commit | dd39d8c86667c5446020458f8fe5171149d9ed5c (patch) | |
| tree | f8e8d6a80d60e6da672cdd4cde4e43f72ec4e9bb /backend | |
| parent | added delete demo from drive, also delete if an error is encountered while su... (diff) | |
| download | lphub-dd39d8c86667c5446020458f8fe5171149d9ed5c.tar.gz lphub-dd39d8c86667c5446020458f8fe5171149d9ed5c.tar.bz2 lphub-dd39d8c86667c5446020458f8fe5171149d9ed5c.zip | |
feat: refresh/update user via steam (#30)
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/controllers/homeController.go | 57 | ||||
| -rw-r--r-- | backend/controllers/loginController.go | 92 | ||||
| -rw-r--r-- | backend/controllers/userController.go | 35 | ||||
| -rw-r--r-- | backend/models/models.go | 24 |
4 files changed, 151 insertions, 57 deletions
diff --git a/backend/controllers/homeController.go b/backend/controllers/homeController.go index 42dfaa7..8b52ff3 100644 --- a/backend/controllers/homeController.go +++ b/backend/controllers/homeController.go | |||
| @@ -2,14 +2,10 @@ package controllers | |||
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "net/http" | 4 | "net/http" |
| 5 | "os" | ||
| 6 | "time" | ||
| 7 | 5 | ||
| 8 | "github.com/gin-gonic/gin" | 6 | "github.com/gin-gonic/gin" |
| 9 | "github.com/golang-jwt/jwt/v4" | ||
| 10 | "github.com/pektezol/leastportals/backend/database" | 7 | "github.com/pektezol/leastportals/backend/database" |
| 11 | "github.com/pektezol/leastportals/backend/models" | 8 | "github.com/pektezol/leastportals/backend/models" |
| 12 | "github.com/solovev/steam_go" | ||
| 13 | ) | 9 | ) |
| 14 | 10 | ||
| 15 | func Home(c *gin.Context) { | 11 | func Home(c *gin.Context) { |
| @@ -23,59 +19,6 @@ func Home(c *gin.Context) { | |||
| 23 | } | 19 | } |
| 24 | } | 20 | } |
| 25 | 21 | ||
| 26 | func Login(c *gin.Context) { | ||
| 27 | openID := steam_go.NewOpenId(c.Request) | ||
| 28 | switch openID.Mode() { | ||
| 29 | case "": | ||
| 30 | c.Redirect(http.StatusMovedPermanently, openID.AuthUrl()) | ||
| 31 | case "cancel": | ||
| 32 | c.Redirect(http.StatusMovedPermanently, "/") | ||
| 33 | default: | ||
| 34 | steamID, err := openID.ValidateAndGetId() | ||
| 35 | if err != nil { | ||
| 36 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 37 | return | ||
| 38 | } | ||
| 39 | // Create user if new | ||
| 40 | var checkSteamID int64 | ||
| 41 | err = database.DB.QueryRow("SELECT steam_id FROM users WHERE steam_id = $1", steamID).Scan(&checkSteamID) | ||
| 42 | if err != nil { | ||
| 43 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 44 | return | ||
| 45 | } | ||
| 46 | // User does not exist | ||
| 47 | if checkSteamID == 0 { | ||
| 48 | user, err := steam_go.GetPlayerSummaries(steamID, os.Getenv("API_KEY")) | ||
| 49 | if err != nil { | ||
| 50 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 51 | return | ||
| 52 | } | ||
| 53 | // Insert new user to database | ||
| 54 | database.DB.Exec(`INSERT INTO users (steam_id, username, avatar_link, country_code) | ||
| 55 | VALUES ($1, $2, $3, $4)`, steamID, user.PersonaName, user.AvatarFull, user.LocCountryCode) | ||
| 56 | } | ||
| 57 | // Generate JWT token | ||
| 58 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ | ||
| 59 | "sub": steamID, | ||
| 60 | "exp": time.Now().Add(time.Hour * 24 * 365).Unix(), | ||
| 61 | }) | ||
| 62 | // Sign and get the complete encoded token as a string using the secret | ||
| 63 | tokenString, err := token.SignedString([]byte(os.Getenv("SECRET_KEY"))) | ||
| 64 | if err != nil { | ||
| 65 | c.JSON(http.StatusBadRequest, models.ErrorResponse("Failed to generate token.")) | ||
| 66 | return | ||
| 67 | } | ||
| 68 | c.JSON(http.StatusOK, models.Response{ | ||
| 69 | Success: true, | ||
| 70 | Message: "Successfully generated token.", | ||
| 71 | Data: models.LoginResponse{ | ||
| 72 | Token: tokenString, | ||
| 73 | }, | ||
| 74 | }) | ||
| 75 | return | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | func Rankings(c *gin.Context) { | 22 | func Rankings(c *gin.Context) { |
| 80 | rows, err := database.DB.Query(`SELECT steam_id, username FROM users;`) | 23 | rows, err := database.DB.Query(`SELECT steam_id, username FROM users;`) |
| 81 | if err != nil { | 24 | if err != nil { |
diff --git a/backend/controllers/loginController.go b/backend/controllers/loginController.go new file mode 100644 index 0000000..50189e8 --- /dev/null +++ b/backend/controllers/loginController.go | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | package controllers | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "encoding/json" | ||
| 5 | "fmt" | ||
| 6 | "io/ioutil" | ||
| 7 | "net/http" | ||
| 8 | "os" | ||
| 9 | "time" | ||
| 10 | |||
| 11 | "github.com/gin-gonic/gin" | ||
| 12 | "github.com/golang-jwt/jwt/v4" | ||
| 13 | "github.com/pektezol/leastportals/backend/database" | ||
| 14 | "github.com/pektezol/leastportals/backend/models" | ||
| 15 | "github.com/solovev/steam_go" | ||
| 16 | ) | ||
| 17 | |||
| 18 | func Login(c *gin.Context) { | ||
| 19 | openID := steam_go.NewOpenId(c.Request) | ||
| 20 | switch openID.Mode() { | ||
| 21 | case "": | ||
| 22 | c.Redirect(http.StatusMovedPermanently, openID.AuthUrl()) | ||
| 23 | case "cancel": | ||
| 24 | c.Redirect(http.StatusMovedPermanently, "/") | ||
| 25 | default: | ||
| 26 | steamID, err := openID.ValidateAndGetId() | ||
| 27 | if err != nil { | ||
| 28 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 29 | return | ||
| 30 | } | ||
| 31 | // Create user if new | ||
| 32 | var checkSteamID int64 | ||
| 33 | err = database.DB.QueryRow("SELECT steam_id FROM users WHERE steam_id = $1", steamID).Scan(&checkSteamID) | ||
| 34 | if err != nil { | ||
| 35 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 36 | return | ||
| 37 | } | ||
| 38 | // User does not exist | ||
| 39 | if checkSteamID == 0 { | ||
| 40 | user, err := GetPlayerSummaries(steamID, os.Getenv("API_KEY")) | ||
| 41 | if err != nil { | ||
| 42 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 43 | return | ||
| 44 | } | ||
| 45 | // Insert new user to database | ||
| 46 | database.DB.Exec(`INSERT INTO users (steam_id, username, avatar_link, country_code) | ||
| 47 | VALUES ($1, $2, $3, $4)`, steamID, user.PersonaName, user.AvatarFull, user.LocCountryCode) | ||
| 48 | } | ||
| 49 | // Generate JWT token | ||
| 50 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ | ||
| 51 | "sub": steamID, | ||
| 52 | "exp": time.Now().Add(time.Hour * 24 * 365).Unix(), | ||
| 53 | }) | ||
| 54 | // Sign and get the complete encoded token as a string using the secret | ||
| 55 | tokenString, err := token.SignedString([]byte(os.Getenv("SECRET_KEY"))) | ||
| 56 | if err != nil { | ||
| 57 | c.JSON(http.StatusBadRequest, models.ErrorResponse("Failed to generate token.")) | ||
| 58 | return | ||
| 59 | } | ||
| 60 | c.JSON(http.StatusOK, models.Response{ | ||
| 61 | Success: true, | ||
| 62 | Message: "Successfully generated token.", | ||
| 63 | Data: models.LoginResponse{ | ||
| 64 | Token: tokenString, | ||
| 65 | }, | ||
| 66 | }) | ||
| 67 | return | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | func GetPlayerSummaries(steamId, apiKey string) (*models.PlayerSummaries, error) { | ||
| 72 | url := fmt.Sprintf("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=%s&steamids=%s", apiKey, steamId) | ||
| 73 | resp, err := http.Get(url) | ||
| 74 | if err != nil { | ||
| 75 | return nil, err | ||
| 76 | } | ||
| 77 | body, err := ioutil.ReadAll(resp.Body) | ||
| 78 | if err != nil { | ||
| 79 | return nil, err | ||
| 80 | } | ||
| 81 | |||
| 82 | type Result struct { | ||
| 83 | Response struct { | ||
| 84 | Players []models.PlayerSummaries `json:"players"` | ||
| 85 | } `json:"response"` | ||
| 86 | } | ||
| 87 | var data Result | ||
| 88 | if err := json.Unmarshal(body, &data); err != nil { | ||
| 89 | return nil, err | ||
| 90 | } | ||
| 91 | return &data.Response.Players[0], err | ||
| 92 | } | ||
diff --git a/backend/controllers/userController.go b/backend/controllers/userController.go index 6bca5b9..95b2b52 100644 --- a/backend/controllers/userController.go +++ b/backend/controllers/userController.go | |||
| @@ -2,7 +2,9 @@ package controllers | |||
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "net/http" | 4 | "net/http" |
| 5 | "os" | ||
| 5 | "regexp" | 6 | "regexp" |
| 7 | "time" | ||
| 6 | 8 | ||
| 7 | "github.com/gin-gonic/gin" | 9 | "github.com/gin-gonic/gin" |
| 8 | "github.com/pektezol/leastportals/backend/database" | 10 | "github.com/pektezol/leastportals/backend/database" |
| @@ -176,6 +178,39 @@ func FetchUser(c *gin.Context) { | |||
| 176 | return | 178 | return |
| 177 | } | 179 | } |
| 178 | 180 | ||
| 181 | func UpdateUser(c *gin.Context) { | ||
| 182 | // Check if user exists | ||
| 183 | user, exists := c.Get("user") | ||
| 184 | if !exists { | ||
| 185 | c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in.")) | ||
| 186 | return | ||
| 187 | } | ||
| 188 | profile, err := GetPlayerSummaries(user.(models.User).SteamID, os.Getenv("API_KEY")) | ||
| 189 | if err != nil { | ||
| 190 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 191 | return | ||
| 192 | } | ||
| 193 | // Update profile | ||
| 194 | _, err = database.DB.Exec(`UPDATE users SET username = $1, avatar_link = $2, country_code = $3, updated_at = $4 | ||
| 195 | WHERE steam_id = $5;`, profile.PersonaName, profile.AvatarFull, profile.LocCountryCode, time.Now().UTC(), user.(models.User).SteamID) | ||
| 196 | if err != nil { | ||
| 197 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 198 | return | ||
| 199 | } | ||
| 200 | c.JSON(http.StatusOK, models.Response{ | ||
| 201 | Success: true, | ||
| 202 | Message: "Successfully updated user.", | ||
| 203 | Data: models.ProfileResponse{ | ||
| 204 | Profile: true, | ||
| 205 | SteamID: user.(models.User).SteamID, | ||
| 206 | Username: profile.PersonaName, | ||
| 207 | AvatarLink: profile.AvatarFull, | ||
| 208 | CountryCode: profile.LocCountryCode, | ||
| 209 | }, | ||
| 210 | }) | ||
| 211 | return | ||
| 212 | } | ||
| 213 | |||
| 179 | func UpdateCountryCode(c *gin.Context) { | 214 | func UpdateCountryCode(c *gin.Context) { |
| 180 | // Check if user exists | 215 | // Check if user exists |
| 181 | user, exists := c.Get("user") | 216 | user, exists := c.Get("user") |
diff --git a/backend/models/models.go b/backend/models/models.go index 5ce3ebf..2d14a06 100644 --- a/backend/models/models.go +++ b/backend/models/models.go | |||
| @@ -87,6 +87,30 @@ type ScoreResponse struct { | |||
| 87 | Records any `json:"records"` | 87 | Records any `json:"records"` |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | type PlayerSummaries struct { | ||
| 91 | SteamId string `json:"steamid"` | ||
| 92 | CommunityVisibilityState int `json:"communityvisibilitystate"` | ||
| 93 | ProfileState int `json:"profilestate"` | ||
| 94 | PersonaName string `json:"personaname"` | ||
| 95 | LastLogOff int `json:"lastlogoff"` | ||
| 96 | ProfileUrl string `json:"profileurl"` | ||
| 97 | Avatar string `json:"avatar"` | ||
| 98 | AvatarMedium string `json:"avatarmedium"` | ||
| 99 | AvatarFull string `json:"avatarfull"` | ||
| 100 | PersonaState int `json:"personastate"` | ||
| 101 | |||
| 102 | CommentPermission int `json:"commentpermission"` | ||
| 103 | RealName string `json:"realname"` | ||
| 104 | PrimaryClanId string `json:"primaryclanid"` | ||
| 105 | TimeCreated int `json:"timecreated"` | ||
| 106 | LocCountryCode string `json:"loccountrycode"` | ||
| 107 | LocStateCode string `json:"locstatecode"` | ||
| 108 | LocCityId int `json:"loccityid"` | ||
| 109 | GameId int `json:"gameid"` | ||
| 110 | GameExtraInfo string `json:"gameextrainfo"` | ||
| 111 | GameServerIp string `json:"gameserverip"` | ||
| 112 | } | ||
| 113 | |||
| 90 | func ErrorResponse(message string) Response { | 114 | func ErrorResponse(message string) Response { |
| 91 | return Response{ | 115 | return Response{ |
| 92 | Success: false, | 116 | Success: false, |