-
Notifications
You must be signed in to change notification settings - Fork 0
/
security_controller.go
122 lines (99 loc) · 3.09 KB
/
security_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package security
import (
"github.com/gin-gonic/gin"
"github.com/mgjules/api-er/helper"
"github.com/mgjules/api-er/user"
csrf "github.com/utrack/gin-csrf"
)
// TODO: add proper validation
type loginJSON struct {
Username string `json:"username" binding:"required,min=8"`
Password string `json:"password" binding:"required,min=8"`
}
// Controller represents the security controller
type Controller struct {
userRepo *user.Repository
userSvc *user.Service
}
// NewController returns a new Security
func NewController(userRepo *user.Repository, userSvc *user.Service) *Controller {
return &Controller{userRepo: userRepo, userSvc: userSvc}
}
// AttachRoutes attaches the controller's routes to gin.RouterGroup
func (c *Controller) AttachRoutes(r *gin.RouterGroup) {
r.GET("/csrf-token", c.Token)
r.POST("/login", c.Login)
r.POST("/logout", c.Logout)
r.GET("/me", c.Me)
r.GET("/status", c.Status)
}
// TokenMismatch is used for ErrorFunc of CSRF middleware
func (c *Controller) TokenMismatch(ctx *gin.Context) {
helper.ResponseBadRequest(ctx, "csrftoken:invalid")
}
// Token replies with a CSRF token
func (c *Controller) Token(ctx *gin.Context) {
helper.ResponseSuccessPayload(ctx, "csrftoken:retrieved", csrf.GetToken(ctx))
}
// Login authenticates the user
func (c *Controller) Login(ctx *gin.Context) {
if _, ok := c.userSvc.UserFromContext(ctx); ok {
helper.ResponseBadRequest(ctx, "auth:alreadyloggedin")
return
}
var json loginJSON
if err := ctx.ShouldBindJSON(&json); err != nil {
helper.ResponseBadRequest(ctx, err.Error())
return
}
userModel := &user.Model{}
userModel.Username = json.Username
userModel, err := c.userRepo.Get(ctx, userModel)
if err != nil {
if err == user.ErrUserNotFound {
helper.ResponseNotFound(ctx, "auth:user:notfound")
return
}
helper.ResponseInternalServerError(ctx, "auth:user:internalerror")
return
}
if err := c.userSvc.ComparePassword([]byte(userModel.Password), []byte(json.Password)); err != nil {
helper.ResponseUnauthorized(ctx, err.Error())
return
}
// TODO: when I get the register user done
// if !userModel.Verified {
// helper.ResponseUnauthorized(ctx, "auth:user:notverified")
// return
// }
if err := c.userSvc.SetUserIDSessionContext(ctx, userModel.ID.Hex()); err != nil {
helper.ResponseInternalServerError(ctx, err.Error())
return
}
helper.ResponseSuccess(ctx, "auth:loggedin")
}
// Logout deauthenticates the user
func (c *Controller) Logout(ctx *gin.Context) {
if _, ok := c.userSvc.UserFromContext(ctx); !ok {
helper.ResponseBadRequest(ctx, "auth:notloggedin")
return
}
if err := c.userSvc.DeleteUserIDSessionContext(ctx); err != nil {
helper.ResponseInternalServerError(ctx, err.Error())
return
}
helper.ResponseSuccess(ctx, "auth:loggedout")
}
// Me returns self user
func (c *Controller) Me(ctx *gin.Context) {
user, ok := c.userSvc.UserFromContext(ctx)
if !ok {
helper.ResponseBadRequest(ctx, "auth:notloggedin")
return
}
helper.ResponseSuccessPayload(ctx, "auth:me", user)
}
// Status confirms if logged in
func (c *Controller) Status(ctx *gin.Context) {
helper.ResponseSuccess(ctx, "auth:ok")
}