-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
430 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Database credentials | ||
DB_HOST="<<DB_HOST>>" | ||
DB_PORT="<<DB_PORT>>" | ||
DB_USER="<<DB_USER>>" | ||
DB_PASSWORD="<<DB_PASSWORD>>" | ||
DB_NAME=shop | ||
SSL_MODE=disable | ||
PGADMIN_DEFAULT_EMAIL="<<PGADMIN_ADMIN_USER_EMAIL>>" | ||
PGADMIN_DEFAULT_PASSWORD="<<PGADMIN_ADMIN_PASSWORD>>" | ||
|
||
# Authentication credentials | ||
TOKEN_TTL="3000" | ||
JWT_PRIVATE_KEY="<<VERY_STRONG_KEY>>" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package controller | ||
|
||
import ( | ||
"database/sql" | ||
"net/http" | ||
|
||
"github.com/gin-gonic/gin" | ||
"github.com/shayja/go-template-api/helper" | ||
"github.com/shayja/go-template-api/model" | ||
repository "github.com/shayja/go-template-api/repository/user" | ||
"github.com/shayja/go-template-api/utils" | ||
) | ||
|
||
type AuthenticationController struct { | ||
Db *sql.DB | ||
} | ||
|
||
func CreateUserController(db *sql.DB) AuthenticationInterface { | ||
return &AuthenticationController{Db: db} | ||
} | ||
|
||
func (m *AuthenticationController) Register(c *gin.Context) { | ||
|
||
AddRequestHeader(c) | ||
DB := m.Db | ||
|
||
var userReq model.User | ||
if err := c.ShouldBindJSON(&userReq); err != nil { | ||
|
||
c.JSON(http.StatusBadRequest, gin.H{"status": "failed", "msg": err}) | ||
return | ||
} | ||
|
||
repository := repository.NewUserRepository(DB) | ||
|
||
insertedId, err := repository.Create(userReq) | ||
|
||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"status": "failed", "msg": err}) | ||
return | ||
} | ||
|
||
if utils.IsValidUUID(insertedId) { | ||
c.JSON(http.StatusCreated, gin.H{"status": "success", "msg": nil, "id": insertedId}) | ||
} else { | ||
c.JSON(http.StatusInternalServerError, gin.H{"status": "failed", "msg": "insert product failed"}) | ||
} | ||
} | ||
|
||
func (m *AuthenticationController) Login(c *gin.Context) { | ||
var input model.AuthenticateRequest | ||
|
||
if err := c.ShouldBindJSON(&input); err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"status": "failed", "msg": err}) | ||
return | ||
} | ||
|
||
AddRequestHeader(c) | ||
DB := m.Db | ||
|
||
repository := repository.NewUserRepository(DB) | ||
|
||
user, err := repository.GetByUsername(input.Username) | ||
|
||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"status": "failed", "msg": err}) | ||
return | ||
} | ||
|
||
err = repository.ValidatePassword(user, input.Password) | ||
|
||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"status": "failed", "msg": err}) | ||
return | ||
} | ||
|
||
jwt, err := helper.GenerateJWT(user) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"status": "failed", "msg": err}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, gin.H{"jwt": jwt}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package controller | ||
|
||
import "github.com/gin-gonic/gin" | ||
|
||
type AuthenticationInterface interface { | ||
Login(*gin.Context) | ||
Register(*gin.Context) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package helper | ||
|
||
import ( | ||
"database/sql" | ||
"errors" | ||
"fmt" | ||
"log" | ||
"os" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/gin-gonic/gin" | ||
"github.com/golang-jwt/jwt/v4" | ||
"github.com/shayja/go-template-api/model" | ||
"github.com/shayja/go-template-api/service" | ||
) | ||
|
||
var privateKey = []byte(os.Getenv("JWT_PRIVATE_KEY")) | ||
|
||
type JwtHelper struct { | ||
Db *sql.DB | ||
} | ||
|
||
func GenerateJWT(user model.User) (string, error) { | ||
tokenTTL, _ := strconv.Atoi(os.Getenv("TOKEN_TTL")) | ||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ | ||
"id": user.Id, | ||
"iat": time.Now().Unix(), | ||
"eat": time.Now().Add(time.Second * time.Duration(tokenTTL)).Unix(), | ||
}) | ||
return token.SignedString(privateKey) | ||
} | ||
|
||
func ValidateJWT(context *gin.Context) error { | ||
token, err := getToken(context) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
_, ok := token.Claims.(jwt.MapClaims) | ||
|
||
if ok && token.Valid { | ||
return nil | ||
} | ||
|
||
return errors.New("invalid client token provided") | ||
} | ||
|
||
|
||
func(m *JwtHelper) CurrentUser(context *gin.Context) (model.User, error) { | ||
err := ValidateJWT(context) | ||
if err != nil { | ||
return model.User{}, err | ||
} | ||
|
||
token, _ := getToken(context) | ||
claims, _ := token.Claims.(jwt.MapClaims) | ||
userId := string(claims["id"].(string)) | ||
|
||
|
||
service := service.CreateUserService(m.Db) | ||
|
||
user, err := service.GetById(userId) | ||
if err != nil { | ||
return model.User{}, err | ||
} | ||
return user, nil | ||
} | ||
|
||
func getToken(context *gin.Context) (*jwt.Token, error) { | ||
tokenString := getTokenFromRequest(context) | ||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { | ||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { | ||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) | ||
} | ||
|
||
return privateKey, nil | ||
}) | ||
return token, err | ||
} | ||
|
||
func getTokenFromRequest(context *gin.Context) string { | ||
bearerToken := context.Request.Header.Get("Authorization") | ||
splitToken := strings.Split(bearerToken, " ") | ||
if len(splitToken) == 2 { | ||
return splitToken[1] | ||
} | ||
return "" | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package middleware | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/gin-gonic/gin" | ||
"github.com/shayja/go-template-api/helper" | ||
) | ||
|
||
func JWTAuthMiddleware() gin.HandlerFunc { | ||
return func(context *gin.Context) { | ||
err := helper.ValidateJWT(context) | ||
if err != nil { | ||
context.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication required"}) | ||
fmt.Println(err) | ||
context.Abort() | ||
return | ||
} | ||
context.Next() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package model | ||
|
||
type AuthenticateRequest struct { | ||
Username string `json:"username" validate:"required"` | ||
Password string `json:"password" validate:"required"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package model | ||
|
||
import "time" | ||
|
||
type User struct { | ||
Id string `json:"id"` | ||
Username string `json:"username" validate:"required"` | ||
Password string `json:"passhash" validate:"required"` | ||
Mobile string `json:"mobile"` | ||
Name string `json:"name"` | ||
Email string `json:"email"` | ||
CreatedAt time.Time `json:"created_at"` | ||
UpdatedAt time.Time `json:"updated_at"` | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.