Skip to content

Commit

Permalink
update internal pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukmanern committed Jan 23, 2024
1 parent 84c5b77 commit b4158a5
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 144 deletions.
3 changes: 1 addition & 2 deletions domain/entity/all_entities.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ var allTables = []any{
&UserHasRoles{},
&Role{},

// ...
// Add more tables/structs
// add more tables/structs
}

func AllTables() []any {
Expand Down
27 changes: 17 additions & 10 deletions domain/model/user.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package model

import "github.com/Lukmanern/gost/domain/entity"
import (
"time"

"github.com/Lukmanern/gost/domain/entity"
)

type UserRegister struct {
Name string `validate:"required,min=2,max=60" json:"name"`
Expand Down Expand Up @@ -39,19 +43,22 @@ type UserPasswordUpdate struct {
}

type UserProfile struct {
Email string
Name string
Roles []string
Email string
Name string
ActivatedAt *time.Time
Roles []string
}

type UserResponse struct {
ID int
Name string
ID int
Name string
ActivatedAt *time.Time
}

type UserResponseDetail struct {
ID int
Email string
Name string
Roles []entity.Role
ID int
Email string
Name string
ActivatedAt *time.Time
Roles []entity.Role
}
19 changes: 0 additions & 19 deletions internal/constants/constants.go

This file was deleted.

31 changes: 31 additions & 0 deletions internal/consts/consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package consts

const (
SuccessCreated = "data successfully created"
SuccessLoaded = "data successfully loaded"
Unauthorized = "unauthorized"
BadRequest = "bad request, please check your request and try again"
NotFound = "data not found"
)

const (
InvalidJSONBody = "invalid JSON body"
InvalidUserID = "invalid user ID"
InvalidID = "invalid ID"

RedisNil = "redis nil value"

ErrGetIDFromJWT = "error while getting user ID from JWT-Claims"
ErrHashing = "error while hashing password, please try again"
)

const (
ShouldErr = "should error"
ShouldNotErr = "should not error"
ShouldNil = "should nil"
ShouldNotNil = "should not nil"
ShouldEqual = "should equal"
ShouldNotEqual = "should not equal"

LoginShouldSuccess = "login should success"
)
12 changes: 6 additions & 6 deletions internal/helper/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"net"
"testing"

"github.com/Lukmanern/gost/internal/constants"
"github.com/Lukmanern/gost/internal/consts"
"github.com/stretchr/testify/assert"
)

Expand All @@ -27,27 +27,27 @@ func TestRandomIPAddress(t *testing.T) {
for i := 0; i < 20; i++ {
ipRand := RandomIPAddress()
ip := net.ParseIP(ipRand)
assert.NotNil(t, ip, constants.ShouldNotNil)
assert.NotNil(t, ip, consts.ShouldNotNil)
}
}

func TestValidateEmails(t *testing.T) {
err1 := ValidateEmails("f", "a")
assert.Error(t, err1, constants.ShouldErr)
assert.Error(t, err1, consts.ShouldErr)

err2 := ValidateEmails("[email protected]")
assert.NoError(t, err2, "should not error")

err3 := ValidateEmails("[email protected]", "[email protected]")
assert.Error(t, err3, constants.ShouldErr)
assert.Error(t, err3, consts.ShouldErr)

err4 := ValidateEmails("[email protected]", "[email protected]", "[email protected].")
assert.Error(t, err4, constants.ShouldErr)
assert.Error(t, err4, consts.ShouldErr)
}

func TestNewFiberCtx(t *testing.T) {
c := NewFiberCtx()
assert.NotNil(t, c, constants.ShouldNotNil)
assert.NotNil(t, c, consts.ShouldNotNil)
}

func TestToTitle(t *testing.T) {
Expand Down
48 changes: 8 additions & 40 deletions internal/middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package middleware

import (
"crypto/rsa"
"errors"
"fmt"
"log"
"strings"
Expand All @@ -28,11 +27,11 @@ type JWTHandler struct {

// Claims struct will be generated as token,contains
// user data like ID, email, role and permissions.
// You can add new field if you want.
type Claims struct {
ID int `json:"id"`
Email string `json:"email"`
Role string `json:"role"`
Permissions map[int]int `json:"permissions"`
ID int `json:"id"`
Email string `json:"email"`
Role string `json:"role"`
jwt.RegisteredClaims
}

Expand Down Expand Up @@ -67,16 +66,12 @@ func NewJWTHandler() *JWTHandler {
}

// GenerateJWT func generate new token with expire time for user
func (j *JWTHandler) GenerateJWT(id int, email, role string, permissions map[int]int, expired time.Time) (t string, err error) {
if email == "" || role == "" || len(permissions) < 1 {
return "", errors.New("email/ role/ permission too short or void")
}
func (j *JWTHandler) GenerateJWT(id int, email, role string, expired time.Time) (t string, err error) {
// Create Claims
claims := Claims{
ID: id,
Email: email,
Role: role,
Permissions: permissions,
ID: id,
Email: email,
Role: role,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: &jwt.NumericDate{Time: expired},
NotBefore: &jwt.NumericDate{Time: time.Now()},
Expand Down Expand Up @@ -211,25 +206,6 @@ func CheckHasPermission(requirePermID int, userPermissions map[int]int) bool {
return true
}

// HasPermission func extracts and checks for claims from fiber Ctx
func (j JWTHandler) HasPermission(c *fiber.Ctx, endpointPermID int) error {
claims, ok := c.Locals("claims").(*Claims)
if !ok {
return response.Unauthorized(c)
}
userPermissions := claims.Permissions
endpointBits := BuildBitGroups(endpointPermID)
// it seems O(n), but it's actually O(1)
// because length of $endpointBits is 1
for key, requiredBits := range endpointBits {
userBits, ok := userPermissions[key]
if !ok || requiredBits&userBits == 0 {
return response.Unauthorized(c)
}
}
return c.Next()
}

// HasRole func check claims-role equal or not with require role
func (j JWTHandler) HasRole(c *fiber.Ctx, role string) error {
claims, ok := c.Locals("claims").(*Claims)
Expand All @@ -239,14 +215,6 @@ func (j JWTHandler) HasRole(c *fiber.Ctx, role string) error {
return c.Next()
}

// CheckHasPermission func is handler/middleware that
// called before the controller for checks the fiber ctx
func (j JWTHandler) CheckHasPermission(endpointPermID int) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
return j.HasPermission(c, endpointPermID)
}
}

// CheckHasRole func is handler/middleware that
// called before the controller for checks the fiber ctx
func (j JWTHandler) CheckHasRole(role string) func(c *fiber.Ctx) error {
Expand Down
46 changes: 12 additions & 34 deletions internal/middleware/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"testing"
"time"

"github.com/Lukmanern/gost/internal/constants"
"github.com/Lukmanern/gost/internal/consts"
"github.com/Lukmanern/gost/internal/env"
"github.com/Lukmanern/gost/internal/helper"
"github.com/gofiber/fiber/v2"
Expand Down Expand Up @@ -63,7 +63,7 @@ func TestNewJWTHandler(t *testing.T) {

func TestGenerateClaims(t *testing.T) {
jwtHandler := NewJWTHandler()
token, err := jwtHandler.GenerateJWT(1, params.Email, params.Role, params.Per, params.Exp)
token, err := jwtHandler.GenerateJWT(1, params.Email, params.Role, params.Exp)
if err != nil || token == "" {
t.Fatal("should not error")
}
Expand Down Expand Up @@ -95,7 +95,7 @@ func TestGenerateClaims(t *testing.T) {

func TestJWTHandlerInvalidateToken(t *testing.T) {
jwtHandler := NewJWTHandler()
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Per, params.Exp)
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Exp)
if err != nil {
t.Error("error while generating token")
}
Expand All @@ -119,7 +119,7 @@ func TestJWTHandlerIsBlacklisted(t *testing.T) {
jwtHandler := NewJWTHandler()
cookie, err := jwtHandler.GenerateJWT(1000,
helper.RandomEmail(), "example-role",
params.Per, time.Now().Add(1*time.Hour))
time.Now().Add(1*time.Hour))
if err != nil {
t.Error("generate cookie/token should not error")
}
Expand Down Expand Up @@ -151,7 +151,7 @@ func TestJWTHandlerIsBlacklisted(t *testing.T) {

func TestJWTHandlerIsAuthenticated(t *testing.T) {
jwtHandler := NewJWTHandler()
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Per, params.Exp)
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Exp)
if err != nil {
t.Error("error while generating token")
}
Expand Down Expand Up @@ -187,26 +187,9 @@ func TestJWTHandlerIsAuthenticated(t *testing.T) {
}()
}

func TestJWTHandlerHasPermission(t *testing.T) {
jwtHandler := NewJWTHandler()
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Per, params.Exp)
if err != nil {
t.Error("Error while generating token:", err)
}
if token == "" {
t.Error("Error: Token is empty")
}
c := helper.NewFiberCtx()
c.Request().Header.Add(fiber.HeaderAuthorization, "Bearer "+token)
jwtHandler.HasPermission(c, 25)
if c.Response().Header.StatusCode() != fiber.StatusUnauthorized {
t.Error("Should authorized")
}
}

func TestJWTHandlerHasRole(t *testing.T) {
jwtHandler := NewJWTHandler()
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Per, params.Exp)
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Exp)
if err != nil {
t.Error("Error while generating token:", err)
}
Expand All @@ -217,39 +200,34 @@ func TestJWTHandlerHasRole(t *testing.T) {
c.Request().Header.Add(fiber.HeaderAuthorization, "Bearer "+token)
jwtHandler.HasRole(c, "test-role")
if c.Response().Header.StatusCode() != fiber.StatusUnauthorized {
t.Error(constants.Unauthorized)
t.Error(consts.Unauthorized)
}
}

func TestJWTHandlerCheckHasPermission(t *testing.T) {
jwtHandler := NewJWTHandler()
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Per, params.Exp)
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Exp)
if err != nil {
t.Error("Error while generating token:", err)
}
if token == "" {
t.Error("Error: Token is empty")
}

err2 := jwtHandler.CheckHasPermission(9999)
if err2 == nil {
t.Error(constants.Unauthorized)
}
}

func TestJWTHandlerCheckHasRole(t *testing.T) {
jwtHandler := NewJWTHandler()
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Per, params.Exp)
token, err := jwtHandler.GenerateJWT(params.ID, params.Email, params.Role, params.Exp)
if err != nil {
t.Error("Error while generating token:", err)
}
if token == "" {
t.Error("Error: Token is empty")
}

err2 := jwtHandler.CheckHasRole("permission-1")
if err2 == nil {
t.Error(constants.Unauthorized)
checkErr := jwtHandler.CheckHasRole("permission-1")
if checkErr == nil {
t.Error(consts.Unauthorized)
}
}

Expand Down
Loading

0 comments on commit b4158a5

Please sign in to comment.