User registration

This commit is contained in:
Max 2024-11-08 20:43:57 +03:00
parent 2398d3ebc0
commit 27d7df3d59
9 changed files with 161 additions and 10 deletions

View File

@ -0,0 +1,35 @@
package rest_api_stuff
import (
"net/http"
"github.com/gin-gonic/gin"
)
func OkAnswer(c *gin.Context, message string) {
c.IndentedJSON(
http.StatusOK,
gin.H{"message": message},
)
}
func BadRequestAnswer(c *gin.Context, err error) {
c.IndentedJSON(
http.StatusBadRequest,
gin.H{"error": err.Error()},
)
}
func InternalErrorAnswer(c *gin.Context, err error) {
c.IndentedJSON(
http.StatusInternalServerError,
gin.H{"error": err.Error()},
)
}
func ConflictAnswer(c *gin.Context, err error) {
c.IndentedJSON(
http.StatusConflict,
gin.H{"error": err.Error()},
)
}

View File

@ -85,9 +85,9 @@ type Tag struct {
type User struct {
UserID int64 `json:"user_id"`
Username string `json:"username"`
Email string `json:"email"`
Password string `json:"password"`
Username string `json:"username" validate:"required"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
CreatedAt pgtype.Timestamp `json:"created_at"`
IsAdmin bool `json:"is_admin"`
}

View File

@ -18,9 +18,9 @@ RETURNING user_id, username, email, password, created_at, is_admin
type CreateUserParams struct {
UserID int64 `json:"user_id"`
Username string `json:"username"`
Email string `json:"email"`
Password string `json:"password"`
Username string `json:"username" validate:"required"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
}
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {
@ -93,6 +93,29 @@ func (q *Queries) GetAllUsers(ctx context.Context) ([]User, error) {
return items, nil
}
const getUserByEmailOrNickname = `-- name: GetUserByEmailOrNickname :one
SELECT user_id, username, email, password, created_at, is_admin FROM users WHERE username = $1 OR email = $2 LIMIT 1
`
type GetUserByEmailOrNicknameParams struct {
Username string `json:"username" validate:"required"`
Email string `json:"email" validate:"required,email"`
}
func (q *Queries) GetUserByEmailOrNickname(ctx context.Context, arg GetUserByEmailOrNicknameParams) (User, error) {
row := q.db.QueryRow(ctx, getUserByEmailOrNickname, arg.Username, arg.Email)
var i User
err := row.Scan(
&i.UserID,
&i.Username,
&i.Email,
&i.Password,
&i.CreatedAt,
&i.IsAdmin,
)
return i, err
}
const getUserById = `-- name: GetUserById :one
SELECT user_id, username, email, password, created_at, is_admin FROM users WHERE user_id = $1
`
@ -137,7 +160,7 @@ RETURNING user_id, username, email, password, created_at, is_admin
`
type UpdateUserPasswordHashParams struct {
Password string `json:"password"`
Password string `json:"password" validate:"required"`
UserID int64 `json:"user_id"`
}

View File

@ -26,3 +26,6 @@ WHERE user_id=$1;
-- name: DeleteUserByUsername :exec
DELETE FROM public.users
WHERE username=$1;
-- name: GetUserByEmailOrNickname :one
SELECT * FROM users WHERE username = $1 OR email = $2 LIMIT 1;

View File

@ -10,6 +10,12 @@ sql:
out: "./go_queries"
sql_package: "pgx/v5"
overrides:
- column: users.password
go_struct_tag: validate:"required"
- column: users.username
go_struct_tag: validate:"required"
- column: users.email
go_struct_tag: validate:"required,email"
- db_type: "uuid"
go_type:
import: 'github.com/google/uuid'

View File

@ -17,7 +17,7 @@ require (
github.com/gin-gonic/gin v1.10.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-playground/validator/v10 v10.22.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/google/uuid v1.6.0 // indirect

View File

@ -21,6 +21,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=

View File

@ -2,6 +2,7 @@ package utils
import (
"context"
db_repo "enshi/db/go_queries"
"fmt"
"github.com/jackc/pgx/v5"
@ -11,6 +12,7 @@ import (
// Pgx connection to database
var Dbx *pgxpool.Pool
var Dbx_connection *pgx.Conn
var Sqlc_db = db_repo.New(Dbx)
func SetupDatabase() error {
@ -27,7 +29,7 @@ func SetupDatabase() error {
}
// Url to connect
url := fmt.Sprintf("postgres://%v:%v@nekiiinkognito.ru:5432/enshi_db", bd_user, bd_pass)
url := fmt.Sprintf("postgres://%v:%v@nekiiinkognito.ru:5432/postgres", bd_user, bd_pass)
// Connecting to database
Dbx, err = pgxpool.New(context.Background(), url)

View File

@ -2,13 +2,18 @@ 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) {
@ -16,6 +21,80 @@ func testCookie(c *gin.Context) {
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())
@ -25,6 +104,7 @@ func SetupRotes(g *gin.Engine) error {
freeGroup.POST("login", login)
freeGroup.GET("getCookie", testCookie)
freeGroup.POST("registerUser", RegisterUser)
authGroup := g.Group("/")
authGroup.Use(AuthMiddleware())