user.go
2.82 KB
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
package main
import (
"context"
"net/http"
"strings"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/go-sql-driver/mysql"
"github.com/labstack/echo/v4"
"golang.org/x/crypto/sha3"
)
type User struct {
No uint64 `json:"no"`
ID string `json:"id"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
ExpiredAt time.Time `json:"expired_at"`
}
func (app *App) PostUsers(c echo.Context) error {
body := struct {
ID string `json:"id"`
Password string `json:"password"`
Name string `json:"name"`
}{}
if c.Bind(&body) != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Failed to parse request json")
}
hash := sha3.Sum256([]byte(body.Password))
res, err := app.db.Exec("INSERT INTO users (`id`, `password`, `name`) VALUES (?, ?, ?)", body.ID, hash[:], body.Name)
if err != nil {
if merr, ok := err.(*mysql.MySQLError); ok {
if merr.Number == 1062 {
return echo.NewHTTPError(http.StatusConflict, "Already registered")
}
}
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to register")
}
no, _ := res.LastInsertId()
return c.JSON(http.StatusOK, echo.Map{"user_no": no})
}
type AuthClaims struct {
UserNo uint64 `json:"user_no"`
jwt.StandardClaims
}
func (app *App) PostTokens(c echo.Context) error {
body := struct {
ID string `json:"id"`
Password string `json:"password"`
}{}
if c.Bind(&body) != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Failed to parse request json")
}
hash := sha3.Sum256([]byte(body.Password))
rows, err := app.db.Query("SELECT `no` FROM users WHERE `id`=? AND `password`=?", body.ID, hash[:])
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to register")
}
if !rows.Next() {
return echo.NewHTTPError(http.StatusUnauthorized, "Login failed")
}
no := uint64(0)
rows.Scan(&no)
token := jwt.NewWithClaims(jwt.SigningMethodHS256, AuthClaims{UserNo: no})
auth, err := token.SignedString([]byte(app.Config.TokenSecret))
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Login failed")
}
return c.JSON(http.StatusOK, map[string]interface{}{"token": auth})
}
func (app *App) Authenticate(next func(http.ResponseWriter, *http.Request)) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
auth := r.Header.Get("Authorization")
if len(auth) > 6 && strings.Index(auth, "Bearer ") == 0 {
token, err := jwt.ParseWithClaims(auth[7:], &AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(app.Config.TokenSecret), nil
})
if err == nil {
claims := token.Claims.(*AuthClaims)
ctx := context.WithValue(r.Context(), PropUserNo, claims.UserNo)
next(w, r.WithContext(ctx))
return
}
}
WriteError(w, http.StatusUnauthorized, "Authorization failed")
})
}