forked from NyaaPantsu/nyaa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cookieHelper.go
143 lines (129 loc) · 4.03 KB
/
cookieHelper.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package userService
import (
"errors"
"github.com/ewhal/nyaa/db"
"github.com/ewhal/nyaa/model"
formStruct "github.com/ewhal/nyaa/service/user/form"
"github.com/ewhal/nyaa/util/modelHelper"
"github.com/ewhal/nyaa/util/timeHelper"
"github.com/gorilla/securecookie"
"golang.org/x/crypto/bcrypt"
"net/http"
"strconv"
"time"
)
const CookieName = "session"
// If you want to keep login cookies between restarts you need to make these permanent
var cookieHandler = securecookie.New(
securecookie.GenerateRandomKey(64),
securecookie.GenerateRandomKey(32))
// Encoding & Decoding of the cookie value
func DecodeCookie(cookie_value string) (uint, error) {
value := make(map[string]string)
err := cookieHandler.Decode(CookieName, cookie_value, &value)
if err != nil {
return 0, err
}
time_int, _ := strconv.ParseInt(value["t"], 10, 0)
if timeHelper.IsExpired(time.Unix(time_int, 0)) {
return 0, errors.New("Cookie is expired")
}
ret, err := strconv.ParseUint(value["u"], 10, 0)
return uint(ret), err
}
func EncodeCookie(user_id uint) (string, error) {
validUntil := timeHelper.FewDaysLater(7) // 1 week
value := map[string]string{
"u": strconv.FormatUint(uint64(user_id), 10),
"t": strconv.FormatInt(validUntil.Unix(), 10),
}
return cookieHandler.Encode(CookieName, value)
}
func ClearCookie(w http.ResponseWriter) (int, error) {
cookie := &http.Cookie{
Name: CookieName,
Value: "",
Path: "/",
HttpOnly: true,
MaxAge: -1,
}
http.SetCookie(w, cookie)
return http.StatusOK, nil
}
// SetCookieHandler sets the authentication cookie
func SetCookieHandler(w http.ResponseWriter, email string, pass string) (int, error) {
if email == "" || pass == "" {
return http.StatusNotFound, errors.New("No username/password entered")
}
var user model.User
// search by email or username
isValidEmail, _ := formStruct.EmailValidation(email, formStruct.NewErrors())
if isValidEmail {
if db.ORM.Where("email = ?", email).First(&user).RecordNotFound() {
return http.StatusNotFound, errors.New("User not found")
}
} else {
if db.ORM.Where("username = ?", email).First(&user).RecordNotFound() {
return http.StatusNotFound, errors.New("User not found")
}
}
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(pass))
if err != nil {
return http.StatusUnauthorized, errors.New("Password incorrect")
}
if user.Status == -1 {
return http.StatusUnauthorized, errors.New("Account banned")
}
encoded, err := EncodeCookie(user.ID)
if err != nil {
return http.StatusInternalServerError, err
}
cookie := &http.Cookie{
Name: CookieName,
Value: encoded,
Path: "/",
HttpOnly: true,
}
http.SetCookie(w, cookie)
// also set response header for convenience
w.Header().Set("X-Auth-Token", encoded)
return http.StatusOK, nil
}
// RegisterHanderFromForm sets cookie from a RegistrationForm.
func RegisterHanderFromForm(w http.ResponseWriter, registrationForm formStruct.RegistrationForm) (int, error) {
username := registrationForm.Username // email isn't set at this point
pass := registrationForm.Password
return SetCookieHandler(w, username, pass)
}
// RegisterHandler sets a cookie when user registered.
func RegisterHandler(w http.ResponseWriter, r *http.Request) (int, error) {
var registrationForm formStruct.RegistrationForm
modelHelper.BindValueForm(®istrationForm, r)
return RegisterHanderFromForm(w, registrationForm)
}
// CurrentUser determines the current user from the request
func CurrentUser(r *http.Request) (model.User, error) {
var user model.User
var encoded string
encoded = r.Header.Get("X-Auth-Token")
if len(encoded) == 0 {
// check cookie instead
cookie, err := r.Cookie(CookieName)
if err != nil {
return user, err
}
encoded = cookie.Value
}
user_id, err := DecodeCookie(encoded)
if err != nil {
return user, err
}
if db.ORM.Where("user_id = ?", user_id).First(&user).RecordNotFound() {
return user, errors.New("User not found")
}
if user.Status == -1 {
// recheck as user might've been banned in the meantime
return user, errors.New("Account banned")
}
return user, nil
}