Albirew/nyaa-pantsu
Archivé
1
0
Bifurcation 0
Ce dépôt a été archivé le 2022-05-07. Vous pouvez voir ses fichiers ou le cloner, mais pas ouvrir de ticket ou de demandes d'ajout, ni soumettre de changements.
nyaa-pantsu/service/user/cookie_helper.go

173 lignes
4,9 Kio
Go
Brut Vue normale Historique

package userService
import (
"errors"
"net/http"
"strconv"
"time"
2017-05-17 07:58:40 +02:00
"github.com/NyaaPantsu/nyaa/db"
"github.com/NyaaPantsu/nyaa/model"
formStruct "github.com/NyaaPantsu/nyaa/service/user/form"
2017-05-21 20:20:40 +02:00
msg "github.com/NyaaPantsu/nyaa/util/messages"
2017-05-17 07:58:40 +02:00
"github.com/NyaaPantsu/nyaa/util/modelHelper"
"github.com/NyaaPantsu/nyaa/util/timeHelper"
2017-05-20 13:45:15 +02:00
"github.com/gorilla/context"
2017-05-09 19:23:21 +02:00
"github.com/gorilla/securecookie"
"golang.org/x/crypto/bcrypt"
)
2017-05-20 13:45:15 +02:00
const (
// CookieName : Name of cookie
CookieName = "session"
// UserContextKey : key for user context
2017-05-20 13:45:15 +02:00
UserContextKey = "user"
2017-05-24 09:11:13 +02:00
)
2017-05-12 12:40:31 +02:00
// 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))
// DecodeCookie : Encoding & Decoding of the cookie value
func DecodeCookie(cookieValue string) (uint, error) {
2017-05-12 12:40:31 +02:00
value := make(map[string]string)
err := cookieHandler.Decode(CookieName, cookieValue, &value)
if err != nil {
2017-05-12 12:40:31 +02:00
return 0, err
}
timeInt, _ := strconv.ParseInt(value["t"], 10, 0)
if timeHelper.IsExpired(time.Unix(timeInt, 0)) {
2017-05-12 12:40:31 +02:00
return 0, errors.New("Cookie is expired")
}
2017-05-12 12:40:31 +02:00
ret, err := strconv.ParseUint(value["u"], 10, 0)
return uint(ret), err
}
// EncodeCookie : Encoding of the cookie value
func EncodeCookie(userID uint) (string, error) {
2017-05-12 12:40:31 +02:00
validUntil := timeHelper.FewDaysLater(7) // 1 week
value := map[string]string{
"u": strconv.FormatUint(uint64(userID), 10),
2017-05-12 12:40:31 +02:00
"t": strconv.FormatInt(validUntil.Unix(), 10),
}
2017-05-12 12:40:31 +02:00
return cookieHandler.Encode(CookieName, value)
}
// ClearCookie : Erase cookie session
func ClearCookie(w http.ResponseWriter) (int, error) {
cookie := &http.Cookie{
2017-05-17 07:58:40 +02:00
Name: CookieName,
Value: "",
Path: "/",
2017-05-12 12:40:31 +02:00
HttpOnly: true,
2017-05-17 07:58:40 +02:00
MaxAge: -1,
}
http.SetCookie(w, cookie)
return http.StatusOK, nil
}
2017-05-12 12:40:31 +02:00
// SetCookieHandler sets the authentication cookie
2017-05-21 20:20:40 +02:00
func SetCookieHandler(w http.ResponseWriter, r *http.Request, email string, pass string) (int, error) {
2017-05-12 12:40:31 +02:00
if email == "" || pass == "" {
return http.StatusNotFound, errors.New("No username/password entered")
}
var user model.User
2017-05-21 20:20:40 +02:00
messages := msg.GetMessages(r)
2017-05-12 12:40:31 +02:00
// search by email or username
isValidEmail := formStruct.EmailValidation(email, messages)
2017-05-12 12:40:31 +02:00
if isValidEmail {
if db.ORM.Where("email = ?", email).First(&user).RecordNotFound() {
return http.StatusNotFound, errors.New("User not found")
}
2017-05-12 12:40:31 +02:00
} else {
if db.ORM.Where("username = ?", email).First(&user).RecordNotFound() {
return http.StatusNotFound, errors.New("User not found")
}
}
2017-05-12 12:40:31 +02:00
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(pass))
if err != nil {
return http.StatusUnauthorized, errors.New("Password incorrect")
}
if user.IsBanned() {
2017-05-12 12:40:31 +02:00
return http.StatusUnauthorized, errors.New("Account banned")
}
encoded, err := EncodeCookie(user.ID)
if err != nil {
return http.StatusInternalServerError, err
}
cookie := &http.Cookie{
2017-05-17 07:58:40 +02:00
Name: CookieName,
Value: encoded,
Path: "/",
2017-05-12 12:40:31 +02:00
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.
2017-05-21 20:20:40 +02:00
func RegisterHanderFromForm(w http.ResponseWriter, r *http.Request, registrationForm formStruct.RegistrationForm) (int, error) {
username := registrationForm.Username // email isn't set at this point
pass := registrationForm.Password
2017-05-21 20:20:40 +02:00
return SetCookieHandler(w, r, 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(&registrationForm, r)
2017-05-21 20:20:40 +02:00
return RegisterHanderFromForm(w, r, registrationForm)
}
2017-05-20 13:45:15 +02:00
// CurrentUser determines the current user from the request or context
func CurrentUser(r *http.Request) (model.User, error) {
var user model.User
2017-05-12 12:40:31 +02:00
var encoded string
2017-05-24 00:23:50 +02:00
2017-05-12 12:40:31 +02:00
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
}
2017-05-12 12:40:31 +02:00
encoded = cookie.Value
}
userID, err := DecodeCookie(encoded)
2017-05-12 12:40:31 +02:00
if err != nil {
return user, err
}
2017-05-20 13:45:15 +02:00
userFromContext := getUserFromContext(r)
if userFromContext.ID > 0 && userID == userFromContext.ID {
2017-05-20 13:45:15 +02:00
user = userFromContext
} else {
if db.ORM.Preload("Notifications").Where("user_id = ?", userID).First(&user).RecordNotFound() { // We only load unread notifications
2017-05-20 13:45:15 +02:00
return user, errors.New("User not found")
}
setUserToContext(r, user)
2017-05-12 12:40:31 +02:00
}
if user.IsBanned() {
2017-05-12 12:40:31 +02:00
// recheck as user might've been banned in the meantime
return user, errors.New("Account banned")
}
2017-05-12 12:40:31 +02:00
return user, nil
}
2017-05-20 13:45:15 +02:00
func getUserFromContext(r *http.Request) model.User {
if rv := context.Get(r, UserContextKey); rv != nil {
2017-05-24 09:11:13 +02:00
return rv.(model.User)
}
return model.User{}
2017-05-20 13:45:15 +02:00
}
func setUserToContext(r *http.Request, val model.User) {
2017-05-24 09:11:13 +02:00
context.Set(r, UserContextKey, val)
2017-05-24 00:23:50 +02:00
}