github.com/kotovmak/go-admin@v1.1.1/modules/auth/auth.go (about) 1 // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 // Use of this source code is governed by a Apache-2.0 style 3 // license that can be found in the LICENSE file. 4 5 package auth 6 7 import ( 8 "sync" 9 10 "github.com/kotovmak/go-admin/modules/db/dialect" 11 "github.com/kotovmak/go-admin/modules/logger" 12 13 "github.com/kotovmak/go-admin/context" 14 "github.com/kotovmak/go-admin/modules/db" 15 "github.com/kotovmak/go-admin/modules/service" 16 "github.com/kotovmak/go-admin/plugins/admin/models" 17 "github.com/kotovmak/go-admin/plugins/admin/modules" 18 "golang.org/x/crypto/bcrypt" 19 ) 20 21 // Auth get the user model from Context. 22 func Auth(ctx *context.Context) models.UserModel { 23 return ctx.User().(models.UserModel) 24 } 25 26 // Check check the password and username and return the user model. 27 func Check(password string, username string, conn db.Connection) (user models.UserModel, ok bool) { 28 29 user = models.User().SetConn(conn).FindByUserName(username) 30 31 if user.IsEmpty() { 32 ok = false 33 } else { 34 if comparePassword(password, user.Password) { 35 ok = true 36 user = user.WithRoles().WithPermissions().WithMenus() 37 user.UpdatePwd(EncodePassword([]byte(password))) 38 } else { 39 ok = false 40 } 41 } 42 return 43 } 44 45 func comparePassword(comPwd, pwdHash string) bool { 46 err := bcrypt.CompareHashAndPassword([]byte(pwdHash), []byte(comPwd)) 47 return err == nil 48 } 49 50 // EncodePassword encode the password. 51 func EncodePassword(pwd []byte) string { 52 hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost) 53 if err != nil { 54 return "" 55 } 56 return string(hash) 57 } 58 59 // SetCookie set the cookie. 60 func SetCookie(ctx *context.Context, user models.UserModel, conn db.Connection) error { 61 ses, err := InitSession(ctx, conn) 62 63 if err != nil { 64 return err 65 } 66 67 return ses.Add("user_id", user.Id) 68 } 69 70 // DelCookie delete the cookie from Context. 71 func DelCookie(ctx *context.Context, conn db.Connection) error { 72 ses, err := InitSession(ctx, conn) 73 74 if err != nil { 75 return err 76 } 77 78 return ses.Clear() 79 } 80 81 type TokenService struct { 82 tokens CSRFToken 83 lock sync.Mutex 84 conn db.Connection 85 } 86 87 func (s *TokenService) Name() string { 88 return TokenServiceKey 89 } 90 91 func InitCSRFTokenSrv(conn db.Connection) (string, service.Service) { 92 list, err := db.WithDriver(conn).Table("goadmin_session"). 93 Where("values", "=", "__csrf_token__"). 94 All() 95 if db.CheckError(err, db.QUERY) { 96 logger.Error("csrf token query from database error: ", err) 97 } 98 tokens := make(CSRFToken, len(list)) 99 for i := 0; i < len(list); i++ { 100 tokens[i] = list[i]["sid"].(string) 101 } 102 return TokenServiceKey, &TokenService{ 103 tokens: tokens, 104 conn: conn, 105 } 106 } 107 108 const ( 109 TokenServiceKey = "token_csrf_helper" 110 ServiceKey = "auth" 111 ) 112 113 func GetTokenService(s interface{}) *TokenService { 114 if srv, ok := s.(*TokenService); ok { 115 return srv 116 } 117 panic("wrong service") 118 } 119 120 // AddToken add the token to the CSRFToken. 121 func (s *TokenService) AddToken() string { 122 s.lock.Lock() 123 defer s.lock.Unlock() 124 tokenStr := modules.Uuid() 125 s.tokens = append(s.tokens, tokenStr) 126 _, err := db.WithDriver(s.conn).Table("goadmin_session").Insert(dialect.H{ 127 "sid": tokenStr, 128 "values": "__csrf_token__", 129 }) 130 if db.CheckError(err, db.INSERT) { 131 logger.Error("csrf token insert into database error: ", err) 132 } 133 return tokenStr 134 } 135 136 // CheckToken check the given token with tokens in the CSRFToken, if exist 137 // return true. 138 func (s *TokenService) CheckToken(toCheckToken string) bool { 139 for i := 0; i < len(s.tokens); i++ { 140 if (s.tokens)[i] == toCheckToken { 141 s.tokens = append((s.tokens)[:i], (s.tokens)[i+1:]...) 142 err := db.WithDriver(s.conn).Table("goadmin_session"). 143 Where("sid", "=", toCheckToken). 144 Where("values", "=", "__csrf_token__"). 145 Delete() 146 if db.CheckError(err, db.DELETE) { 147 logger.Error("csrf token delete from database error: ", err) 148 } 149 return true 150 } 151 } 152 return false 153 } 154 155 // CSRFToken is type of a csrf token list. 156 type CSRFToken []string 157 158 type Processor func(ctx *context.Context) (model models.UserModel, exist bool, msg string) 159 160 type Service struct { 161 P Processor 162 } 163 164 func (s *Service) Name() string { 165 return "auth" 166 } 167 168 func GetService(s interface{}) *Service { 169 if srv, ok := s.(*Service); ok { 170 return srv 171 } 172 panic("wrong service") 173 } 174 175 func NewService(processor Processor) *Service { 176 return &Service{ 177 P: processor, 178 } 179 }