Passed
Pull Request — main (#166)
by Yume
02:08
created

v2.*JwtMiddleware.AuthorizeUser   A

Complexity

Conditions 2

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
package v2
2
3
import (
4
	"errors"
5
	"net/http"
6
	"strconv"
7
8
	"github.com/getsentry/sentry-go"
9
	"github.com/labstack/echo/v4"
10
	"github.com/memnix/memnix-rest/domain"
11
	"github.com/memnix/memnix-rest/infrastructures"
12
	"github.com/memnix/memnix-rest/pkg/jwt"
13
	"github.com/memnix/memnix-rest/services/user"
14
)
15
16
// JwtMiddleware is the controller for the jwt routes.
17
type JwtMiddleware struct {
18
	user.IUseCase
19
}
20
21
// NewJwtController creates a new jwt controller.
22
func NewJwtMiddleware(user user.IUseCase) JwtMiddleware {
23
	return JwtMiddleware{IUseCase: user}
24
}
25
26
// VerifyPermissions checks if the user has the required permissions.
27
func (*JwtMiddleware) VerifyPermissions(user domain.User, p domain.Permission) bool {
28
	return user.HasPermission(p)
29
}
30
31
func (j *JwtMiddleware) AuthorizeUser(next echo.HandlerFunc) echo.HandlerFunc {
32
	return func(c echo.Context) error {
33
		return j.IsConnectedMiddleware(domain.PermissionUser, next)(c)
34
	}
35
}
36
37
func (j *JwtMiddleware) AuthorizeVip(next echo.HandlerFunc) echo.HandlerFunc {
38
	return func(c echo.Context) error {
39
		return j.IsConnectedMiddleware(domain.PermissionVip, next)(c)
40
	}
41
}
42
43
func (j *JwtMiddleware) AuthorizeAdmin(next echo.HandlerFunc) echo.HandlerFunc {
44
	return func(c echo.Context) error {
45
		return j.IsConnectedMiddleware(domain.PermissionAdmin, next)(c)
46
	}
47
}
48
49
func (j *JwtMiddleware) IsConnectedMiddleware(p domain.Permission, next echo.HandlerFunc) func(c echo.Context) error {
50
	return func(c echo.Context) error {
51
		_, span := infrastructures.GetTracerInstance().Tracer().Start(c.Request().Context(), "IsConnectedMiddleware")
52
		defer span.End()
53
54
		// get the token from the request header
55
		tokenHeader := c.Request().Header.Get("Authorization")
56
		// if the token is empty, the userModel is not connected, and we return an error
57
		if tokenHeader == "" {
58
			return c.JSON(http.StatusUnauthorized, errors.New("unauthorized: token missing"))
59
		}
60
61
		userID, err := jwt.GetJwtInstance().GetJwt().GetConnectedUserID(c.Request().Context(), tokenHeader)
62
		if err != nil {
63
			return c.JSON(http.StatusUnauthorized, errors.New("unauthorized: invalid token"))
64
		}
65
66
		userModel, err := j.IUseCase.GetByID(c.Request().Context(), userID)
67
		if err != nil {
68
			return c.JSON(http.StatusUnauthorized, errors.New("unauthorized: invalid user"))
69
		}
70
71
		sentry.ConfigureScope(func(scope *sentry.Scope) {
72
			scope.SetUser(sentry.User{
73
				ID:       strconv.Itoa(int(userModel.ID)),
74
				Username: userModel.Username,
75
				Email:    userModel.Email,
76
			})
77
		})
78
79
		// Check permissions
80
		if !j.VerifyPermissions(userModel, p) {
81
			return c.JSON(http.StatusUnauthorized, errors.New("unauthorized: invalid user"))
82
		}
83
84
		// Set userModel in locals
85
		SetUserToContext(c, userModel)
86
		span.End()
87
		return next(c)
88
	}
89
}
90
91
func SetUserToContext(c echo.Context, user domain.User) {
92
	c.Set("user", user)
93
}
94
95
func GetUserFromContext(c echo.Context) (domain.User, error) {
96
	if c.Get("user") == nil {
97
		return domain.User{}, errors.New("user is not initialized")
98
	}
99
	return c.Get("user").(domain.User), nil
100
}
101