admin / modules /auth /auth.go
AZLABS's picture
Upload folder using huggingface_hub
530729e verified
// Copyright 2019 GoAdmin Core Team. All rights reserved.
// Use of this source code is governed by a Apache-2.0 style
// license that can be found in the LICENSE file.
package auth
import (
"log"
"sync"
"github.com/GoAdminGroup/go-admin/modules/db/dialect"
"github.com/GoAdminGroup/go-admin/modules/logger"
"github.com/GoAdminGroup/go-admin/context"
"github.com/GoAdminGroup/go-admin/modules/db"
"github.com/GoAdminGroup/go-admin/modules/service"
"github.com/GoAdminGroup/go-admin/plugins/admin/models"
"github.com/GoAdminGroup/go-admin/plugins/admin/modules"
"golang.org/x/crypto/bcrypt"
)
// Auth get the user model from Context.
func Auth(ctx *context.Context) models.UserModel {
return ctx.User().(models.UserModel)
}
// Check check the password and username and return the user model.
func Check(password string, username string, conn db.Connection) (user models.UserModel, ok bool) {
user = models.User().SetConn(conn).FindByUserName(username)
if user.IsEmpty() {
ok = false
} else {
if comparePassword(password, user.Password) {
ok = true
user = user.WithRoles().WithPermissions().WithMenus()
user.UpdatePwd(EncodePassword([]byte(password)))
} else {
ok = false
}
}
return
}
func comparePassword(comPwd, pwdHash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(pwdHash), []byte(comPwd))
return err == nil
}
// EncodePassword encode the password.
func EncodePassword(pwd []byte) string {
hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
if err != nil {
return ""
}
return string(hash)
}
// SetCookie set the cookie.
func SetCookie(ctx *context.Context, user models.UserModel, conn db.Connection) error {
ses, err := InitSession(ctx, conn)
if err != nil {
return err
}
return ses.Add("user_id", user.Id)
}
// DelCookie delete the cookie from Context.
func DelCookie(ctx *context.Context, conn db.Connection) error {
ses, err := InitSession(ctx, conn)
if err != nil {
return err
}
return ses.Clear()
}
type TokenService struct {
tokens CSRFToken
lock sync.Mutex
conn db.Connection
}
func (s *TokenService) Name() string {
return TokenServiceKey
}
func InitCSRFTokenSrv(conn db.Connection) (string, service.Service) {
list, err := db.WithDriver(conn).Table("goadmin_session").
Where("values", "=", "__csrf_token__").
All()
if db.CheckError(err, db.QUERY) {
logger.Error("csrf token query from database error: ", err)
}
tokens := make(CSRFToken, len(list))
for i := 0; i < len(list); i++ {
tokens[i] = list[i]["sid"].(string)
}
return TokenServiceKey, &TokenService{
tokens: tokens,
conn: conn,
}
}
const (
TokenServiceKey = "token_csrf_helper"
ServiceKey = "auth"
)
func GetTokenService(s interface{}) *TokenService {
if srv, ok := s.(*TokenService); ok {
return srv
}
log.Panicf("wrong service: %+v", s)
return nil
}
// AddToken add the token to the CSRFToken.
func (s *TokenService) AddToken() string {
s.lock.Lock()
defer s.lock.Unlock()
tokenStr := modules.Uuid()
s.tokens = append(s.tokens, tokenStr)
_, err := db.WithDriver(s.conn).Table("goadmin_session").Insert(dialect.H{
"sid": tokenStr,
"values": "__csrf_token__",
})
if db.CheckError(err, db.INSERT) {
logger.Error("csrf token insert into database error: ", err)
}
return tokenStr
}
// CheckToken check the given token with tokens in the CSRFToken, if exist
// return true.
func (s *TokenService) CheckToken(toCheckToken string) (ok bool) {
defer func() {
if ok {
err := db.WithDriver(s.conn).Table("goadmin_session").
Where("sid", "=", toCheckToken).
Where("values", "=", "__csrf_token__").
Delete()
if db.CheckError(err, db.DELETE) {
logger.Error("csrf token delete from database error: ", err)
}
}
}()
for i := 0; i < len(s.tokens); i++ {
if (s.tokens)[i] == toCheckToken {
s.tokens = append((s.tokens)[:i], (s.tokens)[i+1:]...)
ok = true
return
}
}
item, err := db.WithDriver(s.conn).Table("goadmin_session").
Where("sid", "=", toCheckToken).
Where("values", "=", "__csrf_token__").
First()
if item != nil && err == nil {
ok = true
return
}
return
}
// CSRFToken is type of a csrf token list.
type CSRFToken []string
type Processor func(ctx *context.Context) (model models.UserModel, exist bool, msg string)
type Service struct {
P Processor
}
func (s *Service) Name() string {
return "auth"
}
func GetService(s interface{}) *Service {
if srv, ok := s.(*Service); ok {
return srv
}
log.Panicf("wrong service: %+v", s)
return nil
}
func NewService(processor Processor) *Service {
return &Service{
P: processor,
}
}