aboutsummaryrefslogtreecommitdiff
path: root/backend/controllers/controllers.go
blob: 712b33cfbb27c68bb1746fd2278b3ceb1ee28a60 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package controllers

import (
	"log"
	"net/http"
	"os"
	"regexp"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v4"
	"github.com/pektezol/leastportals/backend/database"
	"github.com/pektezol/leastportals/backend/models"
	"github.com/solovev/steam_go"
)

func Home(c *gin.Context) {
	user, exists := c.Get("user")
	if !exists {
		c.JSON(200, "no id, not auth")
	} else {
		c.JSON(200, gin.H{
			"output": user,
		})
	}
}

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 {
			http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
		}
		// Create user if new
		var checkSteamID int64
		database.DB.QueryRow("SELECT steam_id FROM users WHERE steamid = $1", steamID).Scan(&checkSteamID)
		// User does not exist
		if checkSteamID == 0 {
			user, err := steam_go.GetPlayerSummaries(steamID, os.Getenv("API_KEY"))
			if err != nil {
				log.Panic(err)
			}
			// Insert new user to database
			database.DB.Exec(`INSERT INTO users (steam_id, username, avatar_link, country_code, created_at, updated_at, user_type)
			VALUES ($1, $2, $3, $4, $5, $6, $7)`, steamID, user.PersonaName, user.AvatarFull, user.LocCountryCode, time.Now().UTC(), time.Now().UTC(), 0)
		}
		// Update updated_at
		database.DB.Exec(`UPDATE users SET updated_at = $1 WHERE steam_id = $2`, time.Now().UTC(), steamID)
		// Generate JWT token
		token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
			"sub": steamID,
			"exp": time.Now().Add(time.Hour * 24 * 30).Unix(),
		})
		// 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, gin.H{
				"error": "failed to create token",
			})
			return
		}
		// Create auth cookie
		c.SetSameSite(http.SameSiteLaxMode)
		c.SetCookie("auth", tokenString, 3600*24*30, "/", "", true, true)
		c.Redirect(http.StatusMovedPermanently, "/")
	}
}

func Logout(c *gin.Context) {
	// Check if user exists
	_, exists := c.Get("user")
	if !exists {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "not logged in",
		})
	} else {
		// Set auth cookie to die
		tokenString, _ := c.Cookie("auth")
		c.SetCookie("auth", tokenString, -1, "/", "", true, true)
		c.JSON(http.StatusOK, gin.H{
			"output": "logout success",
		})
	}
}

func Profile(c *gin.Context) {
	// Check if user exists
	user, exists := c.Get("user")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code": http.StatusUnauthorized,
			"output": gin.H{
				"error": "User not logged in. Could be invalid token.",
			},
		})
	} else {
		user := user.(models.User)
		c.JSON(http.StatusOK, gin.H{
			"code": http.StatusOK,
			"output": gin.H{
				"username": user.Username,
				"avatar":   user.AvatarLink,
				"types":    user.TypeToString(),
			},
			"profile": true,
		})
	}
}

func User(c *gin.Context) {
	id := c.Param("id")
	// Check if id is all numbers and 17 length
	match, _ := regexp.MatchString("^[0-9]{17}$", id)
	if !match {
		c.JSON(http.StatusNotFound, gin.H{
			"code": http.StatusNotFound,
			"output": gin.H{
				"error": "User not found.",
			},
		})
		return
	}
	// Check if user exists
	var targetUser models.User
	database.DB.QueryRow(`SELECT * FROM users WHERE steam_id = $1;`, id).Scan(
		&targetUser.SteamID, &targetUser.Username, &targetUser.AvatarLink, &targetUser.CountryCode,
		&targetUser.CreatedAt, &targetUser.UpdatedAt, &targetUser.UserType)
	if targetUser.SteamID == "" {
		// User does not exist
		c.JSON(http.StatusNotFound, gin.H{
			"code": http.StatusNotFound,
			"output": gin.H{
				"error": "User not found.",
			},
		})
		return
	}
	// Target user exists
	_, exists := c.Get("user")
	if exists {
		c.Redirect(http.StatusFound, "/api/v1/profile")
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"output": gin.H{
			"username": targetUser.Username,
			"avatar":   targetUser.AvatarLink,
			"types":    targetUser.TypeToString(),
		},
		"profile": false,
	})
}