reorganized back
This commit is contained in:
parent
27d7df3d59
commit
2b306c687c
27
enshi_back/REST_API_stuff/setCookie.go
Normal file
27
enshi_back/REST_API_stuff/setCookie.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package rest_api_stuff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CookieParams struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
MaxAge int
|
||||||
|
Path string
|
||||||
|
Domain string
|
||||||
|
Secure bool
|
||||||
|
HttpOnly bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetCookie(c *gin.Context, params *CookieParams) {
|
||||||
|
c.SetCookie(
|
||||||
|
params.Name,
|
||||||
|
params.Value,
|
||||||
|
params.MaxAge,
|
||||||
|
params.Path,
|
||||||
|
params.Domain,
|
||||||
|
params.Secure,
|
||||||
|
params.HttpOnly,
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package utils
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -71,7 +71,6 @@ type PostVote struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
ProfileID int64 `json:"profile_id"`
|
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
Bio pgtype.Text `json:"bio"`
|
Bio pgtype.Text `json:"bio"`
|
||||||
AvatarUrl pgtype.Text `json:"avatar_url"`
|
AvatarUrl pgtype.Text `json:"avatar_url"`
|
||||||
|
|||||||
@ -15,14 +15,13 @@ const clearProfileByUserId = `-- name: ClearProfileByUserId :one
|
|||||||
UPDATE public.profiles
|
UPDATE public.profiles
|
||||||
SET bio='', avatar_url='', website_url=''
|
SET bio='', avatar_url='', website_url=''
|
||||||
WHERE user_id=$1
|
WHERE user_id=$1
|
||||||
RETURNING profile_id, user_id, bio, avatar_url, website_url
|
RETURNING user_id, bio, avatar_url, website_url
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) ClearProfileByUserId(ctx context.Context, userID int64) (Profile, error) {
|
func (q *Queries) ClearProfileByUserId(ctx context.Context, userID int64) (Profile, error) {
|
||||||
row := q.db.QueryRow(ctx, clearProfileByUserId, userID)
|
row := q.db.QueryRow(ctx, clearProfileByUserId, userID)
|
||||||
var i Profile
|
var i Profile
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ProfileID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.Bio,
|
&i.Bio,
|
||||||
&i.AvatarUrl,
|
&i.AvatarUrl,
|
||||||
@ -33,21 +32,15 @@ func (q *Queries) ClearProfileByUserId(ctx context.Context, userID int64) (Profi
|
|||||||
|
|
||||||
const createProfileForUser = `-- name: CreateProfileForUser :one
|
const createProfileForUser = `-- name: CreateProfileForUser :one
|
||||||
INSERT INTO public.profiles
|
INSERT INTO public.profiles
|
||||||
(profile_id, user_id, bio, avatar_url, website_url)
|
(user_id, bio, avatar_url, website_url)
|
||||||
VALUES($1, $2, '', '', '')
|
VALUES($1, '', '', '')
|
||||||
RETURNING profile_id, user_id, bio, avatar_url, website_url
|
RETURNING user_id, bio, avatar_url, website_url
|
||||||
`
|
`
|
||||||
|
|
||||||
type CreateProfileForUserParams struct {
|
func (q *Queries) CreateProfileForUser(ctx context.Context, userID int64) (Profile, error) {
|
||||||
ProfileID int64 `json:"profile_id"`
|
row := q.db.QueryRow(ctx, createProfileForUser, userID)
|
||||||
UserID int64 `json:"user_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) CreateProfileForUser(ctx context.Context, arg CreateProfileForUserParams) (Profile, error) {
|
|
||||||
row := q.db.QueryRow(ctx, createProfileForUser, arg.ProfileID, arg.UserID)
|
|
||||||
var i Profile
|
var i Profile
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ProfileID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.Bio,
|
&i.Bio,
|
||||||
&i.AvatarUrl,
|
&i.AvatarUrl,
|
||||||
@ -67,14 +60,13 @@ func (q *Queries) DeleteProfileByUserId(ctx context.Context, userID int64) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getProfileByUserId = `-- name: GetProfileByUserId :one
|
const getProfileByUserId = `-- name: GetProfileByUserId :one
|
||||||
SELECT profile_id, user_id, bio, avatar_url, website_url FROM public.profiles WHERE user_id = $1
|
SELECT user_id, bio, avatar_url, website_url FROM public.profiles WHERE user_id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) GetProfileByUserId(ctx context.Context, userID int64) (Profile, error) {
|
func (q *Queries) GetProfileByUserId(ctx context.Context, userID int64) (Profile, error) {
|
||||||
row := q.db.QueryRow(ctx, getProfileByUserId, userID)
|
row := q.db.QueryRow(ctx, getProfileByUserId, userID)
|
||||||
var i Profile
|
var i Profile
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ProfileID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.Bio,
|
&i.Bio,
|
||||||
&i.AvatarUrl,
|
&i.AvatarUrl,
|
||||||
@ -86,12 +78,12 @@ func (q *Queries) GetProfileByUserId(ctx context.Context, userID int64) (Profile
|
|||||||
const updateProfileByUserId = `-- name: UpdateProfileByUserId :one
|
const updateProfileByUserId = `-- name: UpdateProfileByUserId :one
|
||||||
UPDATE public.profiles
|
UPDATE public.profiles
|
||||||
SET bio=$2, avatar_url=$3, website_url=$4
|
SET bio=$2, avatar_url=$3, website_url=$4
|
||||||
WHERE profile_id=$1
|
WHERE user_id=$1
|
||||||
RETURNING profile_id, user_id, bio, avatar_url, website_url
|
RETURNING user_id, bio, avatar_url, website_url
|
||||||
`
|
`
|
||||||
|
|
||||||
type UpdateProfileByUserIdParams struct {
|
type UpdateProfileByUserIdParams struct {
|
||||||
ProfileID int64 `json:"profile_id"`
|
UserID int64 `json:"user_id"`
|
||||||
Bio pgtype.Text `json:"bio"`
|
Bio pgtype.Text `json:"bio"`
|
||||||
AvatarUrl pgtype.Text `json:"avatar_url"`
|
AvatarUrl pgtype.Text `json:"avatar_url"`
|
||||||
WebsiteUrl pgtype.Text `json:"website_url"`
|
WebsiteUrl pgtype.Text `json:"website_url"`
|
||||||
@ -99,14 +91,13 @@ type UpdateProfileByUserIdParams struct {
|
|||||||
|
|
||||||
func (q *Queries) UpdateProfileByUserId(ctx context.Context, arg UpdateProfileByUserIdParams) (Profile, error) {
|
func (q *Queries) UpdateProfileByUserId(ctx context.Context, arg UpdateProfileByUserIdParams) (Profile, error) {
|
||||||
row := q.db.QueryRow(ctx, updateProfileByUserId,
|
row := q.db.QueryRow(ctx, updateProfileByUserId,
|
||||||
arg.ProfileID,
|
arg.UserID,
|
||||||
arg.Bio,
|
arg.Bio,
|
||||||
arg.AvatarUrl,
|
arg.AvatarUrl,
|
||||||
arg.WebsiteUrl,
|
arg.WebsiteUrl,
|
||||||
)
|
)
|
||||||
var i Profile
|
var i Profile
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ProfileID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.Bio,
|
&i.Bio,
|
||||||
&i.AvatarUrl,
|
&i.AvatarUrl,
|
||||||
|
|||||||
@ -25,6 +25,6 @@ CREATE TABLE "public"."post_tags" ("post_id" bigint NOT NULL, "tag_id" integer N
|
|||||||
-- Create "post_votes" table
|
-- Create "post_votes" table
|
||||||
CREATE TABLE "public"."post_votes" ("post_id" bigint NOT NULL, "user_id" bigint NOT NULL, "vote" boolean NOT NULL, PRIMARY KEY ("post_id", "user_id"), CONSTRAINT "post_votes_post_id_fkey" FOREIGN KEY ("post_id") REFERENCES "public"."posts" ("post_id") ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT "post_votes_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users" ("user_id") ON UPDATE NO ACTION ON DELETE NO ACTION);
|
CREATE TABLE "public"."post_votes" ("post_id" bigint NOT NULL, "user_id" bigint NOT NULL, "vote" boolean NOT NULL, PRIMARY KEY ("post_id", "user_id"), CONSTRAINT "post_votes_post_id_fkey" FOREIGN KEY ("post_id") REFERENCES "public"."posts" ("post_id") ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT "post_votes_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users" ("user_id") ON UPDATE NO ACTION ON DELETE NO ACTION);
|
||||||
-- Create "profiles" table
|
-- Create "profiles" table
|
||||||
CREATE TABLE "public"."profiles" ("profile_id" bigint NOT NULL, "user_id" bigint NOT NULL, "bio" text NULL, "avatar_url" character varying(255) NULL, "website_url" character varying(100) NULL, PRIMARY KEY ("profile_id"), CONSTRAINT "profiles_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users" ("user_id") ON UPDATE NO ACTION ON DELETE CASCADE);
|
CREATE TABLE "public"."profiles" ("user_id" bigint NOT NULL, "bio" text NULL, "avatar_url" character varying(255) NULL, "website_url" character varying(100) NULL, PRIMARY KEY ("user_id"), CONSTRAINT "profiles_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users" ("user_id") ON UPDATE NO ACTION ON DELETE CASCADE);
|
||||||
-- Create index "profiles_user_id_idx" to table: "profiles"
|
-- Create index "profiles_user_id_idx" to table: "profiles"
|
||||||
CREATE UNIQUE INDEX "profiles_user_id_idx" ON "public"."profiles" ("user_id");
|
CREATE UNIQUE INDEX "profiles_user_id_idx" ON "public"."profiles" ("user_id");
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
-- name: CreateProfileForUser :one
|
-- name: CreateProfileForUser :one
|
||||||
INSERT INTO public.profiles
|
INSERT INTO public.profiles
|
||||||
(profile_id, user_id, bio, avatar_url, website_url)
|
(user_id, bio, avatar_url, website_url)
|
||||||
VALUES($1, $2, '', '', '')
|
VALUES($1, '', '', '')
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
|
||||||
-- name: ClearProfileByUserId :one
|
-- name: ClearProfileByUserId :one
|
||||||
@ -20,6 +20,6 @@ SELECT * FROM public.profiles WHERE user_id = $1;
|
|||||||
-- name: UpdateProfileByUserId :one
|
-- name: UpdateProfileByUserId :one
|
||||||
UPDATE public.profiles
|
UPDATE public.profiles
|
||||||
SET bio=$2, avatar_url=$3, website_url=$4
|
SET bio=$2, avatar_url=$3, website_url=$4
|
||||||
WHERE profile_id=$1
|
WHERE user_id=$1
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
package utils
|
package db_connection
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
db_repo "enshi/db/go_queries"
|
db_repo "enshi/db/go_queries"
|
||||||
|
"enshi/env"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
@ -12,18 +13,18 @@ import (
|
|||||||
// Pgx connection to database
|
// Pgx connection to database
|
||||||
var Dbx *pgxpool.Pool
|
var Dbx *pgxpool.Pool
|
||||||
var Dbx_connection *pgx.Conn
|
var Dbx_connection *pgx.Conn
|
||||||
var Sqlc_db = db_repo.New(Dbx)
|
var Sqlc_query = db_repo.New(Dbx)
|
||||||
|
|
||||||
func SetupDatabase() error {
|
func SetupDatabase() error {
|
||||||
|
|
||||||
var bd_pass, bd_user string
|
var bd_pass, bd_user string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if err := LookupEnv(&bd_pass, "BD_PASSWORD"); err != nil {
|
if err := env.LookupEnv(&bd_pass, "BD_PASSWORD"); err != nil {
|
||||||
fmt.Printf("%v", err)
|
fmt.Printf("%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := LookupEnv(&bd_user, "BD_USER"); err != nil {
|
if err := env.LookupEnv(&bd_user, "BD_USER"); err != nil {
|
||||||
fmt.Printf("%v", err)
|
fmt.Printf("%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package utils
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"enshi/auth"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ func LoadEnv(path string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := LookupEnv(&SecretKey, "SECRET_KEY"); err != nil {
|
if err := LookupEnv(&auth.SecretKey, "SECRET_KEY"); err != nil {
|
||||||
fmt.Printf("%v\n", err)
|
fmt.Printf("%v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package utils
|
package global
|
||||||
|
|
||||||
var ResetColor = "\033[0m"
|
var ResetColor = "\033[0m"
|
||||||
var RedColor = "\033[31m"
|
var RedColor = "\033[31m"
|
||||||
6
enshi_back/global/globalVars.go
Normal file
6
enshi_back/global/globalVars.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package global
|
||||||
|
|
||||||
|
var PathForCookies = "/"
|
||||||
|
var DomainForCookies = "localhost"
|
||||||
|
var SecureForCookies = false
|
||||||
|
var HttpOnlyForCookies = false
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package utils
|
package hasher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -3,6 +3,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
db_repo "enshi/db/go_queries"
|
db_repo "enshi/db/go_queries"
|
||||||
|
"enshi/db_connection"
|
||||||
|
"enshi/env"
|
||||||
utils "enshi/utils"
|
utils "enshi/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
@ -11,17 +13,17 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
if err := utils.LoadEnv("utils/secret.env"); err != nil {
|
if err := env.LoadEnv("utils/secret.env"); err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := utils.SetupDatabase(); err != nil {
|
if err := db_connection.SetupDatabase(); err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer utils.Dbx.Close()
|
defer db_connection.Dbx.Close()
|
||||||
defer utils.Dbx_connection.Close(context.Background())
|
defer db_connection.Dbx_connection.Close(context.Background())
|
||||||
|
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
if err := utils.SetupRotes(router); err != nil {
|
if err := utils.SetupRotes(router); err != nil {
|
||||||
@ -30,7 +32,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transaction
|
// Transaction
|
||||||
tx, _ := utils.Dbx.Begin(context.Background())
|
tx, _ := db_connection.Dbx.Begin(context.Background())
|
||||||
defer tx.Rollback(context.Background())
|
defer tx.Rollback(context.Background())
|
||||||
|
|
||||||
repo := db_repo.New(tx)
|
repo := db_repo.New(tx)
|
||||||
|
|||||||
29
enshi_back/middleware/authMiddleware.go
Normal file
29
enshi_back/middleware/authMiddleware.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"enshi/auth"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AuthMiddleware() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
|
||||||
|
token := c.GetHeader("Authorization")
|
||||||
|
// tokenFromCoolies := c.Request.CookiesNamed("auth_cookie")
|
||||||
|
|
||||||
|
claims, err := auth.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()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
20
enshi_back/middleware/corsMiddleware.go
Normal file
20
enshi_back/middleware/corsMiddleware.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import "github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
17
enshi_back/routes/changeUserProfile.go
Normal file
17
enshi_back/routes/changeUserProfile.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
rest_api_stuff "enshi/REST_API_stuff"
|
||||||
|
db_repo "enshi/db/go_queries"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ChangeUserProfile(c *gin.Context) {
|
||||||
|
var userProfileParams db_repo.UpdateProfileByUserIdParams
|
||||||
|
|
||||||
|
if err := c.BindJSON(&userProfileParams); err != nil {
|
||||||
|
rest_api_stuff.BadRequestAnswer(c, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
74
enshi_back/routes/login.go
Normal file
74
enshi_back/routes/login.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"enshi/auth"
|
||||||
|
db_repo "enshi/db/go_queries"
|
||||||
|
"enshi/db_connection"
|
||||||
|
"enshi/global"
|
||||||
|
"enshi/hasher"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
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(db_connection.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 := hasher.DecodeArgon2String(user.Password)
|
||||||
|
if err != nil {
|
||||||
|
c.IndentedJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hasher.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 := auth.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 := global.PathForCookies // Cookie path
|
||||||
|
domain := global.DomainForCookies // Set domain (localhost for testing)
|
||||||
|
secure := global.SecureForCookies // Secure cookie (set to true in production with HTTPS)
|
||||||
|
httpOnly := global.HttpOnlyForCookies // HTTP only, so it can't be accessed by JavaScript
|
||||||
|
|
||||||
|
c.Header("Authorization", token)
|
||||||
|
c.SetCookie(cookieName, cookieValue, maxAge, path, domain, secure, httpOnly)
|
||||||
|
c.IndentedJSON(http.StatusOK, gin.H{"token": token})
|
||||||
|
|
||||||
|
}
|
||||||
121
enshi_back/routes/registerUser.go
Normal file
121
enshi_back/routes/registerUser.go
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
|
rest_api_stuff "enshi/REST_API_stuff"
|
||||||
|
"enshi/auth"
|
||||||
|
db_repo "enshi/db/go_queries"
|
||||||
|
"enshi/db_connection"
|
||||||
|
"enshi/global"
|
||||||
|
"enshi/hasher"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterUser(c *gin.Context) {
|
||||||
|
var userParams db_repo.CreateUserParams
|
||||||
|
|
||||||
|
if err := c.BindJSON(&userParams); err != nil {
|
||||||
|
rest_api_stuff.BadRequestAnswer(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
validate := validator.New(validator.WithRequiredStructEnabled())
|
||||||
|
if err := validate.Struct(userParams); err != nil {
|
||||||
|
rest_api_stuff.BadRequestAnswer(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
query := db_repo.New(db_connection.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
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction, err := db_connection.Dbx.Begin(context.Background())
|
||||||
|
defer transaction.Rollback(context.Background())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
query_transaction := query.WithTx(transaction)
|
||||||
|
|
||||||
|
passwordHashSalt, err := hasher.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(uuid[8:]),
|
||||||
|
)
|
||||||
|
|
||||||
|
if _, err := query_transaction.CreateUser(context.Background(), userParams); err != nil {
|
||||||
|
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := query_transaction.CreateProfileForUser(
|
||||||
|
context.Background(),
|
||||||
|
userParams.UserID,
|
||||||
|
); err != nil {
|
||||||
|
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenParams := map[string]interface{}{
|
||||||
|
"id": userParams.UserID,
|
||||||
|
"username": userParams.Username,
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := auth.CreateToken(tokenParams)
|
||||||
|
if err != nil {
|
||||||
|
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cookieParams := &rest_api_stuff.CookieParams{
|
||||||
|
Name: "auth_cookie",
|
||||||
|
Value: token,
|
||||||
|
MaxAge: int(time.Hour.Seconds() * 2),
|
||||||
|
Path: global.PathForCookies,
|
||||||
|
Domain: global.DomainForCookies,
|
||||||
|
Secure: global.SecureForCookies,
|
||||||
|
HttpOnly: global.HttpOnlyForCookies,
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.Commit(context.Background())
|
||||||
|
rest_api_stuff.SetCookie(c, cookieParams)
|
||||||
|
rest_api_stuff.OkAnswer(c, "User has been created!")
|
||||||
|
}
|
||||||
@ -1,19 +1,12 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"enshi/middleware"
|
||||||
"encoding/binary"
|
"enshi/routes"
|
||||||
rest_api_stuff "enshi/REST_API_stuff"
|
|
||||||
db_repo "enshi/db/go_queries"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-playground/validator/v10"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func testCookie(c *gin.Context) {
|
func testCookie(c *gin.Context) {
|
||||||
@ -21,192 +14,22 @@ func testCookie(c *gin.Context) {
|
|||||||
c.IndentedJSON(http.StatusOK, gin.H{"token": "SLESAR' U STASA " + strings.Split(cock, "_")[0]})
|
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 {
|
func SetupRotes(g *gin.Engine) error {
|
||||||
g.Use(CORSMiddleware())
|
g.Use(middleware.CORSMiddleware())
|
||||||
|
|
||||||
freeGroup := g.Group("/")
|
|
||||||
|
|
||||||
// Free group routes
|
// Free group routes
|
||||||
|
freeGroup := g.Group("/")
|
||||||
|
|
||||||
freeGroup.POST("login", login)
|
|
||||||
freeGroup.GET("getCookie", testCookie)
|
freeGroup.GET("getCookie", testCookie)
|
||||||
freeGroup.POST("registerUser", RegisterUser)
|
|
||||||
|
|
||||||
authGroup := g.Group("/")
|
freeGroup.POST("login", routes.Login)
|
||||||
authGroup.Use(AuthMiddleware())
|
freeGroup.POST("registerUser", routes.RegisterUser)
|
||||||
|
|
||||||
// Auth group routes
|
// Auth group routes
|
||||||
|
authGroup := g.Group("/")
|
||||||
|
authGroup.Use(middleware.AuthMiddleware())
|
||||||
|
|
||||||
|
authGroup.POST("changeUserProfile", routes.ChangeUserProfile)
|
||||||
|
|
||||||
return nil
|
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()
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user