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/utils/cookies/user.go

185 lignes
5,5 Kio
Go
Brut Vue normale Historique

package cookies
import (
2017-07-02 18:00:12 +02:00
"errors"
"fmt"
2017-07-02 18:00:12 +02:00
"net/http"
"strconv"
"time"
2017-07-02 18:00:12 +02:00
"github.com/NyaaPantsu/nyaa/config"
"github.com/NyaaPantsu/nyaa/models"
"github.com/NyaaPantsu/nyaa/models/users"
OAuth API [done] (#1275) * Initial Commit for OAuth API This builds and run and return the right error. Need to test it and then adding all users as possible client * Added mising dependency * just compile already... * Fixing template test * Imrpovements Moved db stuff in models Added some tests Added form in modpanel to add/update a client Added controllers for add/update of client * Added Forms + speed improvements Controller oauth client listing + html Controller oauth client delete + messages Messages on comment delete New ES config that disable ES if set to false. Improve load speed on local development Fix a load config bug Fix index admin & translation string sign_out broken by @ewhal * Sanitize empty strig in form array + css Multiple empty array of strings are sanitized for the oauth client create form Added some css for the form display * Upload and Create form works * Fix splitting response types * Removing required on secret when updating * fix travis error * Fix travis template test * Update dependency * Moved to jinzhu instead of azhao * randomizen secret on creation * Final touch on oath api improved display name fix grant form csrf fix login csrf on oauth * Fix gorm test * fix template test * Fixing deleted dependency issue * Make travis faster * Fix typo * Fix csrf for api calls * This shouldn't be exempt * Removing hard coded hash @ewhal Don't forget to replace the hash in tokens.go with another one * Added an example on how to use OAuth middleware * Renamed fosite utils to oauth2 utils
2017-07-28 05:46:40 +02:00
"github.com/NyaaPantsu/nyaa/utils/log"
2017-07-02 18:00:12 +02:00
"github.com/NyaaPantsu/nyaa/utils/timeHelper"
"github.com/NyaaPantsu/nyaa/utils/validator/user"
"github.com/gin-gonic/gin"
"github.com/gorilla/securecookie"
)
const (
// CookieName : Name of cookie
CookieName = "session"
// UserContextKey : key for user context
UserContextKey = "nyaapantsu.user"
)
2017-07-02 18:00:12 +02:00
// NewCurrentUserRetriever create CurrentUserRetriever Struct for languages
func NewCurrentUserRetriever() *CurrentUserRetriever {
return &CurrentUserRetriever{}
}
// CurrentUserRetriever struct for languages
type CurrentUserRetriever struct{}
// RetrieveCurrentUser retrieve current user for languages
func (*CurrentUserRetriever) RetrieveCurrentUser(c *gin.Context) (*models.User, error) {
user, _, err := CurrentUser(c)
2017-07-03 01:22:54 +02:00
if user == nil {
return &models.User{}, err
}
return user, err
}
// CreateUserAuthentication creates user authentication.
2017-07-02 18:00:12 +02:00
func CreateUserAuthentication(c *gin.Context, form *userValidator.LoginForm) (*models.User, int, error) {
username := form.Username
pass := form.Password
user, status, err := users.Exists(username, pass)
if err != nil {
2017-07-02 18:00:12 +02:00
return user, status, err
}
status, err = SetLogin(c, user)
2017-07-02 18:00:12 +02:00
return user, status, err
}
// If you want to keep login cookies between restarts you need to make these permanent
var cookieHandler = securecookie.New(
getOrGenerateKey(config.Get().Cookies.HashKey, 64),
getOrGenerateKey(config.Get().Cookies.EncryptionKey, 32))
func getOrGenerateKey(key string, requiredLen int) []byte {
data := []byte(key)
if len(data) == 0 {
OAuth API [done] (#1275) * Initial Commit for OAuth API This builds and run and return the right error. Need to test it and then adding all users as possible client * Added mising dependency * just compile already... * Fixing template test * Imrpovements Moved db stuff in models Added some tests Added form in modpanel to add/update a client Added controllers for add/update of client * Added Forms + speed improvements Controller oauth client listing + html Controller oauth client delete + messages Messages on comment delete New ES config that disable ES if set to false. Improve load speed on local development Fix a load config bug Fix index admin & translation string sign_out broken by @ewhal * Sanitize empty strig in form array + css Multiple empty array of strings are sanitized for the oauth client create form Added some css for the form display * Upload and Create form works * Fix splitting response types * Removing required on secret when updating * fix travis error * Fix travis template test * Update dependency * Moved to jinzhu instead of azhao * randomizen secret on creation * Final touch on oath api improved display name fix grant form csrf fix login csrf on oauth * Fix gorm test * fix template test * Fixing deleted dependency issue * Make travis faster * Fix typo * Fix csrf for api calls * This shouldn't be exempt * Removing hard coded hash @ewhal Don't forget to replace the hash in tokens.go with another one * Added an example on how to use OAuth middleware * Renamed fosite utils to oauth2 utils
2017-07-28 05:46:40 +02:00
log.Infof("No cookie key '%s' is set in config files. The users won't be kept logged in during restart and accross websites.", key)
data = securecookie.GenerateRandomKey(requiredLen)
} else if len(data) != requiredLen {
panic(fmt.Sprintf("failed to load cookie key. required key length is %d bytes and the provided key length is %d bytes.", requiredLen, len(data)))
}
return data
}
// Decode : Encoding & Decoding of the cookie value
func Decode(cookieValue string) (uint, error) {
value := make(map[string]string)
err := cookieHandler.Decode(CookieName, cookieValue, &value)
if err != nil {
return 0, err
}
timeInt, _ := strconv.ParseInt(value["t"], 10, 0)
if timeHelper.IsExpired(time.Unix(timeInt, 0)) {
return 0, errors.New("Cookie is expired")
}
ret, err := strconv.ParseUint(value["u"], 10, 0)
return uint(ret), err
}
// Encode : Encoding of the cookie value
func Encode(userID uint, validUntil time.Time) (string, error) {
value := map[string]string{
"u": strconv.FormatUint(uint64(userID), 10),
"t": strconv.FormatInt(validUntil.Unix(), 10),
}
return cookieHandler.Encode(CookieName, value)
}
// Clear : Erase cookie session
func Clear(c *gin.Context) {
c.SetCookie(CookieName, "", -1, "/", "", false, true)
}
// SetLogin sets the authentication cookie
func SetLogin(c *gin.Context, user *models.User) (int, error) {
maxAge := getMaxAge(false)
if c.PostForm("remember_me") == "remember" {
maxAge = getMaxAge(true)
}
validUntil := timeHelper.FewDurationLater(time.Duration(maxAge) * time.Second)
encoded, err := Encode(user.ID, validUntil)
if err != nil {
return http.StatusInternalServerError, err
}
//Delete session cookie shared between nyaa & sukebei (or current session cookie if no domain name in config) because it should not exist and used to for some users
http.SetCookie(c.Writer, &http.Cookie{Name: "session", Value: "", Domain: getDomainName(), Path: "/", Expires: time.Now().AddDate(-1, -1, -1)})
c.SetCookie(CookieName, encoded, maxAge, "/", "", false, true)
// also set response header for convenience
c.Header("X-Auth-Token", encoded)
return http.StatusOK, nil
}
// CurrentUser retrieves a current user.
2017-07-03 02:03:57 +02:00
func CurrentUser(c *gin.Context) (*models.User, int, error) {
encoded := c.Request.Header.Get("X-Auth-Token")
2017-07-03 02:03:57 +02:00
var user = &models.User{}
if len(encoded) == 0 {
// check cookie instead
2017-07-03 02:03:57 +02:00
cookie, err := c.Cookie(CookieName)
if err != nil {
return user, http.StatusInternalServerError, err
}
encoded = cookie
}
userID, err := Decode(encoded)
if err != nil {
2017-07-03 02:03:57 +02:00
return user, http.StatusInternalServerError, err
}
userFromContext := getUserFromContext(c)
if userFromContext.ID > 0 && userID == userFromContext.ID {
2017-07-03 02:03:57 +02:00
user = userFromContext
} else {
2017-07-03 02:03:57 +02:00
user, _, _ = users.SessionByID(userID)
setUserToContext(c, user)
}
if user.IsBanned() {
// recheck as user might've been banned in the meantime
2017-07-03 02:03:57 +02:00
return user, http.StatusUnauthorized, errors.New("account_banned")
}
if err != nil {
2017-07-03 02:03:57 +02:00
return user, http.StatusInternalServerError, err
}
2017-07-03 02:03:57 +02:00
return user, http.StatusOK, nil
}
2017-07-03 02:03:57 +02:00
func getUserFromContext(c *gin.Context) *models.User {
2017-08-02 22:15:59 +02:00
if rv, ok := c.Get(UserContextKey); ok {
2017-07-03 02:03:57 +02:00
return rv.(*models.User)
}
2017-07-03 02:03:57 +02:00
return &models.User{}
}
2017-07-03 02:03:57 +02:00
func setUserToContext(c *gin.Context, val *models.User) {
2017-08-02 22:15:59 +02:00
c.Set(UserContextKey, val)
}
2017-07-23 07:46:29 +02:00
// RetrieveUserFromRequest retrieves a user.
func RetrieveUserFromRequest(c *gin.Context, id uint) (*models.User, bool, uint, int, error) {
var user models.User
var currentUserID uint
var isAuthor bool
if models.ORM.First(&user, id).RecordNotFound() {
return nil, isAuthor, currentUserID, http.StatusNotFound, errors.New("user_not_found")
}
currentUser, _, err := CurrentUser(c)
if err == nil {
currentUserID = currentUser.ID
isAuthor = currentUser.ID == user.ID
}
return &user, isAuthor, currentUserID, http.StatusOK, nil
}