forked from techschool/simplebank
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuser.go
123 lines (106 loc) · 3.01 KB
/
user.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
123
package api
import (
"database/sql"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/lib/pq"
db "github.com/techschool/simplebank/db/sqlc"
"github.com/techschool/simplebank/util"
)
type createUserRequest struct {
Username string `json:"username" binding:"required,alphanum"`
Password string `json:"password" binding:"required,min=6"`
FullName string `json:"full_name" binding:"required"`
Email string `json:"email" binding:"required,email"`
}
type userResponse struct {
Username string `json:"username"`
FullName string `json:"full_name"`
Email string `json:"email"`
PasswordChangedAt time.Time `json:"password_changed_at"`
CreatedAt time.Time `json:"created_at"`
}
func newUserResponse(user db.User) userResponse {
return userResponse{
Username: user.Username,
FullName: user.FullName,
Email: user.Email,
PasswordChangedAt: user.PasswordChangedAt,
CreatedAt: user.CreatedAt,
}
}
func (server *Server) createUser(ctx *gin.Context) {
var req createUserRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
ctx.JSON(http.StatusBadRequest, errorResponse(err))
return
}
hashedPassword, err := util.HashPassword(req.Password)
if err != nil {
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}
arg := db.CreateUserParams{
Username: req.Username,
HashedPassword: hashedPassword,
FullName: req.FullName,
Email: req.Email,
}
user, err := server.store.CreateUser(ctx, arg)
if err != nil {
if pqErr, ok := err.(*pq.Error); ok {
switch pqErr.Code.Name() {
case "unique_violation":
ctx.JSON(http.StatusForbidden, errorResponse(err))
return
}
}
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}
rsp := newUserResponse(user)
ctx.JSON(http.StatusOK, rsp)
}
type loginUserRequest struct {
Username string `json:"username" binding:"required,alphanum"`
Password string `json:"password" binding:"required,min=6"`
}
type loginUserResponse struct {
AccessToken string `json:"access_token"`
User userResponse `json:"user"`
}
func (server *Server) loginUser(ctx *gin.Context) {
var req loginUserRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
ctx.JSON(http.StatusBadRequest, errorResponse(err))
return
}
user, err := server.store.GetUser(ctx, req.Username)
if err != nil {
if err == sql.ErrNoRows {
ctx.JSON(http.StatusNotFound, errorResponse(err))
return
}
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}
err = util.CheckPassword(req.Password, user.HashedPassword)
if err != nil {
ctx.JSON(http.StatusUnauthorized, errorResponse(err))
return
}
accessToken, err := server.tokenMaker.CreateToken(
user.Username,
server.config.AccessTokenDuration,
)
if err != nil {
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}
rsp := loginUserResponse{
AccessToken: accessToken,
User: newUserResponse(user),
}
ctx.JSON(http.StatusOK, rsp)
}