feat: (rbac) middleware handle error / password bcrypt hash / user update password
This commit is contained in:
parent
7e9f39cb88
commit
f6d4d9fda5
|
@ -3,12 +3,14 @@ package biz
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"infini.sh/console/internal/dto"
|
||||
"infini.sh/console/model/rbac"
|
||||
"infini.sh/framework/core/event"
|
||||
"infini.sh/framework/core/global"
|
||||
"infini.sh/framework/core/orm"
|
||||
"infini.sh/framework/core/util"
|
||||
"src/github.com/golang-jwt/jwt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -26,11 +28,10 @@ type User struct {
|
|||
const Secret = "console"
|
||||
|
||||
func authenticateUser(username string, password string) (user rbac.User, err error) {
|
||||
q := orm.Query{Size: 1000}
|
||||
q.Conds = orm.And(orm.Eq("username", username))
|
||||
|
||||
err, result := orm.Search(rbac.User{}, &q)
|
||||
err, result := orm.GetBy("username", username, rbac.User{})
|
||||
if err != nil {
|
||||
err = ErrNotFound
|
||||
return
|
||||
}
|
||||
if result.Total == 0 {
|
||||
|
@ -38,10 +39,12 @@ func authenticateUser(username string, password string) (user rbac.User, err err
|
|||
return
|
||||
}
|
||||
user = result.Result[0].(rbac.User)
|
||||
if util.MD5digest(password) != user.Password {
|
||||
err = errors.New("password error")
|
||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
|
||||
if err == bcrypt.ErrMismatchedHashAndPassword {
|
||||
err = errors.New("password incorrect")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
func authenticateAdmin(username string, password string) (user rbac.User, err error) {
|
||||
|
@ -62,7 +65,7 @@ func authorize(user rbac.User) (m map[string]interface{}, err error) {
|
|||
User: &User{
|
||||
Username: user.Username,
|
||||
UserId: user.ID,
|
||||
Roles: []string{"admin"},
|
||||
Roles: []string{"admin_user"},
|
||||
},
|
||||
RegisteredClaims: &jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
|
||||
|
@ -76,7 +79,9 @@ func authorize(user rbac.User) (m map[string]interface{}, err error) {
|
|||
m = util.MapStr{
|
||||
"access_token": tokenString,
|
||||
"username": user.Username,
|
||||
"userid": user.ID,
|
||||
"id": user.ID,
|
||||
"expire_in": 86400,
|
||||
"roles": []string{"admin_user"},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -115,7 +120,30 @@ func Login(username string, password string) (m map[string]interface{}, err erro
|
|||
}, nil, nil))
|
||||
return
|
||||
}
|
||||
|
||||
func UpdatePassword(localUser *User, req dto.UpdatePassword) (err error) {
|
||||
user := rbac.User{}
|
||||
user.ID = localUser.UserId
|
||||
_, err = orm.Get(&user)
|
||||
if err != nil {
|
||||
err = ErrNotFound
|
||||
return
|
||||
}
|
||||
err = bcrypt.CompareHashAndPassword([]byte(req.OldPassword), []byte(user.Password))
|
||||
if err == bcrypt.ErrMismatchedHashAndPassword {
|
||||
err = errors.New("old password is not correct")
|
||||
return
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user.Password = string(hash)
|
||||
err = orm.Save(&user)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
func ValidateLogin(authorizationHeader string) (clams *UserClaims, err error) {
|
||||
|
||||
if authorizationHeader == "" {
|
||||
|
@ -151,10 +179,7 @@ func ValidateLogin(authorizationHeader string) (clams *UserClaims, err error) {
|
|||
func ValidatePermission(claims *UserClaims, permissions []string) (err error) {
|
||||
|
||||
reqUser := claims.User
|
||||
if err != nil {
|
||||
|
||||
return
|
||||
}
|
||||
if reqUser.UserId == "" {
|
||||
err = errors.New("user id is empty")
|
||||
return
|
||||
|
|
|
@ -35,7 +35,7 @@ const InstanceProxy = "instance_proxy"
|
|||
|
||||
var Admin = []string{CreateUser, UpdateUser, DeleteUser, GetUser, SearchUser, CreateRole, UpdateRole, DeleteRole, GetRole, SearchRole, ListPermission}
|
||||
var AdminUser = []string{CreateUser, UpdateUser, DeleteUser, GetUser, SearchUser}
|
||||
|
||||
var AdminRole = []string{CreateRole, UpdateRole, DeleteRole, GetRole, SearchRole, ListPermission}
|
||||
var BuildRoles = []rbac.Role{
|
||||
{
|
||||
ORMObjectBase: orm.ORMObjectBase{
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package biz
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"infini.sh/console/internal/biz/enum"
|
||||
)
|
||||
|
||||
var ClusterApis = make([]string, 0)
|
||||
var EsApis = make(map[string][]string)
|
||||
|
@ -38,33 +41,37 @@ type ConsolePermisson struct {
|
|||
}
|
||||
|
||||
func (r ConsoleRole) ListPermission() interface{} {
|
||||
list := []ConsolePermisson{
|
||||
{
|
||||
Id: "cluster_overview",
|
||||
Name: "平台概览",
|
||||
},
|
||||
{
|
||||
Id: "cluster_search",
|
||||
Name: "平台搜索",
|
||||
},
|
||||
{
|
||||
Id: "cluster_elasticsearch",
|
||||
Name: "集群监控",
|
||||
},
|
||||
{
|
||||
Id: "cluster_elasticsearch_refresh",
|
||||
Name: "集群监控刷新",
|
||||
},
|
||||
{
|
||||
Id: "cluster_activities",
|
||||
Name: "集群动态",
|
||||
},
|
||||
{
|
||||
Id: "cluster_activities_search",
|
||||
Name: "集群动态搜索",
|
||||
},
|
||||
}
|
||||
return list
|
||||
//list := []ConsolePermisson{
|
||||
// {
|
||||
// Id: "cluster_overview",
|
||||
// Name: "平台概览",
|
||||
// },
|
||||
// {
|
||||
// Id: "cluster_search",
|
||||
// Name: "平台搜索",
|
||||
// },
|
||||
// {
|
||||
// Id: "cluster_elasticsearch",
|
||||
// Name: "集群监控",
|
||||
// },
|
||||
// {
|
||||
// Id: "cluster_elasticsearch_refresh",
|
||||
// Name: "集群监控刷新",
|
||||
// },
|
||||
// {
|
||||
// Id: "cluster_activities",
|
||||
// Name: "集群动态",
|
||||
// },
|
||||
// {
|
||||
// Id: "cluster_activities_search",
|
||||
// Name: "集群动态搜索",
|
||||
// },
|
||||
//
|
||||
//}
|
||||
m := make(map[string]map[string][]string)
|
||||
m["api"]["用户管理"] = enum.AdminUser
|
||||
m["api"]["角色管理"] = enum.AdminRole
|
||||
return m
|
||||
}
|
||||
func (r ElasticsearchRole) ListPermission() interface{} {
|
||||
list := ElasticsearchPermisson{
|
||||
|
|
|
@ -5,13 +5,11 @@ import (
|
|||
"infini.sh/console/internal/dto"
|
||||
"infini.sh/console/model/rbac"
|
||||
"infini.sh/framework/core/event"
|
||||
log "src/github.com/cihub/seelog"
|
||||
|
||||
"infini.sh/framework/core/orm"
|
||||
"infini.sh/framework/core/util"
|
||||
log "src/github.com/cihub/seelog"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"infini.sh/framework/core/orm"
|
||||
)
|
||||
|
||||
func CreateRole(localUser *User, req dto.CreateRole) (id string, err error) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package biz
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"infini.sh/console/internal/dto"
|
||||
"infini.sh/console/model/rbac"
|
||||
"infini.sh/framework/core/event"
|
||||
|
@ -73,10 +74,15 @@ func CreateUser(localUser *User, req dto.CreateUser) (id string, err error) {
|
|||
Name: v.Name,
|
||||
})
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte("123456"), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
|
||||
return
|
||||
}
|
||||
user := rbac.User{
|
||||
Name: req.Name,
|
||||
Username: req.Username,
|
||||
Password: util.MD5digest(req.Password),
|
||||
Password: string(hash),
|
||||
Email: req.Email,
|
||||
Phone: req.Phone,
|
||||
Roles: roles,
|
||||
|
|
|
@ -4,3 +4,7 @@ type Login struct {
|
|||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
type UpdatePassword struct {
|
||||
OldPassword string `json:"oldPassword"`
|
||||
NewPassword string `json:"newPassword"`
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ func LoginRequired(h httprouter.Handle) httprouter.Handle {
|
|||
|
||||
claims, err := biz.ValidateLogin(r.Header.Get("Authorization"))
|
||||
if err != nil {
|
||||
w = handleError(w, err)
|
||||
w = handleError(w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
r = r.WithContext(biz.NewUserContext(r.Context(), claims))
|
||||
|
@ -24,21 +24,30 @@ func PermissionRequired(h httprouter.Handle, permissions ...string) httprouter.H
|
|||
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
claims, err := biz.ValidateLogin(r.Header.Get("Authorization"))
|
||||
if err != nil {
|
||||
w = handleError(w, err)
|
||||
|
||||
w = handleError(w, http.StatusUnauthorized, err)
|
||||
|
||||
return
|
||||
}
|
||||
err = biz.ValidatePermission(claims, permissions)
|
||||
if err != nil {
|
||||
w = handleError(w, err)
|
||||
w = handleError(w, http.StatusForbidden, err)
|
||||
return
|
||||
}
|
||||
r = r.WithContext(biz.NewUserContext(r.Context(), claims))
|
||||
h(w, r, ps)
|
||||
}
|
||||
}
|
||||
func handleError(w http.ResponseWriter, err error) http.ResponseWriter {
|
||||
func handleError(w http.ResponseWriter, statusCode int, err error) http.ResponseWriter {
|
||||
w.Header().Set("Content-type", util.ContentTypeJson)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte(`{"error":"` + err.Error() + `"}`))
|
||||
w.WriteHeader(statusCode)
|
||||
json := util.ToJson(util.MapStr{
|
||||
"error": util.MapStr{
|
||||
"status": statusCode,
|
||||
"reason": err.Error(),
|
||||
},
|
||||
}, true)
|
||||
w.Write([]byte(json))
|
||||
|
||||
return w
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ func init() {
|
|||
|
||||
api.HandleAPIMethod(api.DELETE, "/account/logout", account.Logout)
|
||||
api.HandleAPIMethod(api.GET, "/account/profile", m.LoginRequired(account.Profile))
|
||||
api.HandleAPIMethod(api.PUT, "/account/password", m.LoginRequired(account.UpdatePassword))
|
||||
}
|
||||
|
||||
const userInSession = "user_in_session"
|
||||
|
@ -101,3 +102,25 @@ func (h Account) Profile(w http.ResponseWriter, r *http.Request, ps httprouter.P
|
|||
h.WriteJSON(w, reqUser, 200)
|
||||
return
|
||||
}
|
||||
func (h Account) UpdatePassword(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
reqUser, err := biz.FromUserContext(r.Context())
|
||||
if err != nil {
|
||||
h.Error(w, err)
|
||||
return
|
||||
}
|
||||
var req dto.UpdatePassword
|
||||
err = h.DecodeJSON(r, &req)
|
||||
if err != nil {
|
||||
h.Error(w, err)
|
||||
return
|
||||
}
|
||||
err = biz.UpdatePassword(reqUser, req)
|
||||
if err != nil {
|
||||
h.Error(w, err)
|
||||
return
|
||||
}
|
||||
h.WriteOKJSON(w, util.MapStr{
|
||||
"status": "ok",
|
||||
})
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue