Enshi/enshi_back/utils/routesSetup.go
2024-11-08 20:43:57 +03:00

213 lines
5.3 KiB
Go

package utils
import (
"context"
"encoding/binary"
rest_api_stuff "enshi/REST_API_stuff"
db_repo "enshi/db/go_queries"
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"
)
func testCookie(c *gin.Context) {
cock, _ := c.Cookie("auth_cookie")
c.IndentedJSON(http.StatusOK, gin.H{"token": "SLESAR' U STASA " + strings.Split(cock, "_")[0]})
}
func RegisterUser(c *gin.Context) {
var userParams db_repo.CreateUserParams
transaction, err := Dbx.Begin(context.Background())
defer transaction.Rollback(context.Background())
if err != nil {
rest_api_stuff.InternalErrorAnswer(c, err)
return
}
if err := c.BindJSON(&userParams); err != nil {
rest_api_stuff.BadRequestAnswer(c, err)
return
}
validate := validator.New(validator.WithRequiredStructEnabled())
err = validate.Struct(userParams)
if err != nil {
rest_api_stuff.BadRequestAnswer(c, err)
return
}
query := db_repo.New(Dbx)
sameNicknameOrEmailUser, _ := query.GetUserByEmailOrNickname(
context.Background(),
db_repo.GetUserByEmailOrNicknameParams{
Username: userParams.Username,
Email: userParams.Email,
},
)
if sameNicknameOrEmailUser.Username == userParams.Username {
rest_api_stuff.ConflictAnswer(
c,
fmt.Errorf("username"),
)
return
} else if sameNicknameOrEmailUser.Email == userParams.Email {
rest_api_stuff.ConflictAnswer(
c,
fmt.Errorf("email"),
)
return
}
sqlc_transaction := Sqlc_db.WithTx(transaction)
passwordHashSalt, err := Argon2Hasher.HashGen([]byte(userParams.Password), []byte{})
if err != nil {
rest_api_stuff.InternalErrorAnswer(c, err)
return
}
userParams.Password = passwordHashSalt.StringToStore
uuid, err := uuid.NewV7()
if err != nil {
rest_api_stuff.InternalErrorAnswer(c, err)
return
}
userParams.UserID = int64(
binary.BigEndian.Uint64(append(uuid[0:4], uuid[12:16]...)),
)
if _, err := sqlc_transaction.CreateUser(context.Background(), userParams); err != nil {
rest_api_stuff.InternalErrorAnswer(c, err)
return
}
transaction.Commit(context.Background())
rest_api_stuff.OkAnswer(c, "User has been created!")
}
func SetupRotes(g *gin.Engine) error {
g.Use(CORSMiddleware())
freeGroup := g.Group("/")
// Free group routes
freeGroup.POST("login", login)
freeGroup.GET("getCookie", testCookie)
freeGroup.POST("registerUser", RegisterUser)
authGroup := g.Group("/")
authGroup.Use(AuthMiddleware())
// Auth group routes
return nil
}
func login(c *gin.Context) {
type content struct {
Nickname string
Password string
}
var body content
err := c.BindJSON(&body)
if err != nil {
c.IndentedJSON(http.StatusBadRequest, gin.H{"error 1st": err.Error()})
return
}
repo := db_repo.New(Dbx)
user, err := repo.GetUserByUsername(context.Background(), body.Nickname)
if err != nil {
c.IndentedJSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
password_hash, salt, err := DecodeArgon2String(user.Password)
if err != nil {
c.IndentedJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err = Argon2Hasher.Compare(password_hash, salt, []byte(body.Password))
if err != nil {
c.IndentedJSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
return
}
user_info := map[string]interface{}{
"id": user.UserID,
"name": user.Username,
}
token, err := CreateToken(user_info)
if err != nil {
c.IndentedJSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
cookieName := "auth_cookie"
cookieValue := "id=" + strconv.FormatInt(user_info["id"].(int64), 10) +
"_nickname=" + user_info["name"].(string)
maxAge := int(2 * time.Hour.Seconds()) // Cookie expiry time in seconds (1 hour)
path := "/" // Cookie path
domain := "localhost" // Set domain (localhost for testing)
secure := false // Secure cookie (set to true in production with HTTPS)
httpOnly := false // HTTP only, so it can't be accessed by JavaScript
// LookupEnv(&domain, "DOMAIN")
c.Header("Authorization", token)
c.SetCookie(cookieName, cookieValue, maxAge, path, domain, secure, httpOnly)
c.IndentedJSON(http.StatusOK, gin.H{"token": token})
}
func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, authorization, Authorization, accept, origin, Cache-Control, X-Requested-With, Cookie")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
c.Writer.Header().Set("Access-Control-Expose-Headers", "Access-Token, Uid, Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
claims, err := ValidateToken(token)
if err != nil {
c.IndentedJSON(http.StatusUnauthorized, gin.H{"error auth": err.Error()})
c.Abort()
return
}
// Claims -> data stored in token
c.Set("id", claims["id"])
c.Set("claims", claims)
c.Next()
}
}