parent
11c0f4f8de
commit
e52b72990b
|
|
@ -158,20 +158,21 @@ func seed(db *gorm.DB) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var adminUserCount int64
|
var rootUserCount int64
|
||||||
var adminUserName = "admin"
|
if err := db.Model(model.User{}).Count(&rootUserCount).Error; err != nil {
|
||||||
if err := db.Model(model.User{}).Where("name = ?", adminUserName).Count(&adminUserCount).Error; err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if adminUserCount <= 0 {
|
if rootUserCount <= 0 {
|
||||||
encryptedPasswordBytes, err := bcrypt.GenerateFromPassword([]byte("Dragonfly2"), bcrypt.MinCost)
|
encryptedPasswordBytes, err := bcrypt.GenerateFromPassword([]byte("dragonfly"), bcrypt.MinCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := db.Create(&model.User{
|
if err := db.Create(&model.User{
|
||||||
|
Model: model.Model{
|
||||||
|
ID: uint(1),
|
||||||
|
},
|
||||||
EncryptedPassword: string(encryptedPasswordBytes),
|
EncryptedPassword: string(encryptedPasswordBytes),
|
||||||
Name: adminUserName,
|
Name: "root",
|
||||||
Email: fmt.Sprintf("%s@Dragonfly2.com", adminUserName),
|
|
||||||
State: model.UserStateEnabled,
|
State: model.UserStateEnabled,
|
||||||
}).Error; err != nil {
|
}).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package handlers
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"d7y.io/dragonfly/v2/manager/types"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -31,154 +30,9 @@ import (
|
||||||
// @Failure 400 {object} HTTPError
|
// @Failure 400 {object} HTTPError
|
||||||
// @Failure 500 {object} HTTPError
|
// @Failure 500 {object} HTTPError
|
||||||
// @Router /permissions [get]
|
// @Router /permissions [get]
|
||||||
|
|
||||||
func (h *Handlers) GetPermissions(g *gin.Engine) func(ctx *gin.Context) {
|
func (h *Handlers) GetPermissions(g *gin.Engine) func(ctx *gin.Context) {
|
||||||
return func(ctx *gin.Context) {
|
return func(ctx *gin.Context) {
|
||||||
|
permissions := h.Service.GetPermissions(g)
|
||||||
permissionGroups := h.Service.GetPermissions(g)
|
ctx.JSON(http.StatusOK, permissions)
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, permissionGroups)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Create Role
|
|
||||||
// @Description Create Role by json config
|
|
||||||
// @Tags role
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200
|
|
||||||
// @Failure 400 {object} HTTPError
|
|
||||||
// @Failure 500 {object} HTTPError
|
|
||||||
// @Router /roles [post]
|
|
||||||
|
|
||||||
func (h *Handlers) CreateRole(ctx *gin.Context) {
|
|
||||||
var json types.CreateRolePermissionRequest
|
|
||||||
if err := ctx.ShouldBindJSON(&json); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err := h.Service.CreateRole(json)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Status(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Update Role
|
|
||||||
// @Description Remove Role Permission by json config
|
|
||||||
// @Tags role
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200
|
|
||||||
// @Failure 400 {object} HTTPError
|
|
||||||
// @Failure 500 {object} HTTPError
|
|
||||||
// @Router /roles/:role_name/permission [delete]
|
|
||||||
|
|
||||||
func (h *Handlers) RemoveRolePermission(ctx *gin.Context) {
|
|
||||||
|
|
||||||
var params types.RoleParams
|
|
||||||
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var json types.ObjectPermission
|
|
||||||
if err := ctx.ShouldBindJSON(&json); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err := h.Service.RemoveRolePermission(params.RoleName, json)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Status(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Update Role
|
|
||||||
// @Description Add Role Permission by json config
|
|
||||||
// @Tags role
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200
|
|
||||||
// @Failure 400 {object} HTTPError
|
|
||||||
// @Failure 500 {object} HTTPError
|
|
||||||
// @Router /roles/:role_name/permission [post]
|
|
||||||
|
|
||||||
func (h *Handlers) AddRolePermission(ctx *gin.Context) {
|
|
||||||
|
|
||||||
var params types.RoleParams
|
|
||||||
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var json types.ObjectPermission
|
|
||||||
if err := ctx.ShouldBindJSON(&json); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err := h.Service.AddRolePermission(params.RoleName, json)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Status(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Get Roles
|
|
||||||
// @Description Get Roles by name
|
|
||||||
// @Tags role
|
|
||||||
// @Accept text
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200
|
|
||||||
// @Failure 400 {object} HTTPError
|
|
||||||
// @Failure 500 {object} HTTPError
|
|
||||||
// @Router /roles [get]
|
|
||||||
|
|
||||||
func (h *Handlers) GetRoles(ctx *gin.Context) {
|
|
||||||
roles := h.Service.GetRoles()
|
|
||||||
ctx.JSON(http.StatusOK, roles)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Get Role
|
|
||||||
// @Description Get Role
|
|
||||||
// @Tags permission
|
|
||||||
// @Accept text
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200
|
|
||||||
// @Failure 400 {object} HTTPError
|
|
||||||
// @Failure 500 {object} HTTPError
|
|
||||||
// @Router /roles/:role_name [get]
|
|
||||||
|
|
||||||
func (h *Handlers) GetRole(ctx *gin.Context) {
|
|
||||||
var params types.RoleParams
|
|
||||||
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(http.StatusOK, h.Service.GetRole(params.RoleName))
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Destroy Permission
|
|
||||||
// @Description Destroy Permission by json config
|
|
||||||
// @Tags permission
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200
|
|
||||||
// @Failure 400 {object} HTTPError
|
|
||||||
// @Failure 500 {object} HTTPError
|
|
||||||
// @Router /role/:role_name [delete]
|
|
||||||
|
|
||||||
func (h *Handlers) DestroyRole(ctx *gin.Context) {
|
|
||||||
var params types.RoleParams
|
|
||||||
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err := h.Service.DestroyRole(params.RoleName)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Status(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The Dragonfly Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"d7y.io/dragonfly/v2/manager/types"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Summary Create Role
|
||||||
|
// @Description Create Role by json config
|
||||||
|
// @Tags role
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200
|
||||||
|
// @Failure 400 {object} HTTPError
|
||||||
|
// @Failure 500 {object} HTTPError
|
||||||
|
// @Router /roles [post]
|
||||||
|
func (h *Handlers) CreateRole(ctx *gin.Context) {
|
||||||
|
var json types.CreateRoleRequest
|
||||||
|
if err := ctx.ShouldBindJSON(&json); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.Service.CreateRole(json); err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Destroy Role
|
||||||
|
// @Description Destroy role by json config
|
||||||
|
// @Tags permission
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param role path string true "role"
|
||||||
|
// @Success 200
|
||||||
|
// @Failure 400 {object} HTTPError
|
||||||
|
// @Failure 500 {object} HTTPError
|
||||||
|
// @Router /role/:role [delete]
|
||||||
|
func (h *Handlers) DestroyRole(ctx *gin.Context) {
|
||||||
|
var params types.RoleParams
|
||||||
|
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok, err := h.Service.DestroyRole(params.Role); err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
} else if !ok {
|
||||||
|
ctx.Status(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Get Role
|
||||||
|
// @Description Get Role
|
||||||
|
// @Tags permission
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200
|
||||||
|
// @Failure 400 {object} HTTPError
|
||||||
|
// @Failure 500 {object} HTTPError
|
||||||
|
// @Router /roles/:role [get]
|
||||||
|
func (h *Handlers) GetRole(ctx *gin.Context) {
|
||||||
|
var params types.RoleParams
|
||||||
|
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, h.Service.GetRole(params.Role))
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Get Roles
|
||||||
|
// @Description Get roles
|
||||||
|
// @Tags role
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200
|
||||||
|
// @Failure 400 {object} HTTPError
|
||||||
|
// @Failure 500 {object} HTTPError
|
||||||
|
// @Router /roles [get]
|
||||||
|
func (h *Handlers) GetRoles(ctx *gin.Context) {
|
||||||
|
roles := h.Service.GetRoles()
|
||||||
|
ctx.JSON(http.StatusOK, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Add Permission For Role
|
||||||
|
// @Description Add Permission by json config
|
||||||
|
// @Tags role
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param Permission body types.AddPermissionForRoleRequest true "Permission"
|
||||||
|
// @Param role path string true "role"
|
||||||
|
// @Success 200
|
||||||
|
// @Failure 400 {object} HTTPError
|
||||||
|
// @Failure 500 {object} HTTPError
|
||||||
|
// @Router /roles/:role/permissions [post]
|
||||||
|
func (h *Handlers) AddPermissionForRole(ctx *gin.Context) {
|
||||||
|
var params types.RoleParams
|
||||||
|
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var json types.AddPermissionForRoleRequest
|
||||||
|
if err := ctx.ShouldBindJSON(&json); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok, err := h.Service.AddPermissionForRole(params.Role, json); err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
} else if !ok {
|
||||||
|
ctx.Status(http.StatusConflict)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Update Role
|
||||||
|
// @Description Remove Role Permission by json config
|
||||||
|
// @Tags role
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param Permission body types.DeletePermissionForRoleRequest true "Permission"
|
||||||
|
// @Param role path string true "role"
|
||||||
|
// @Success 200
|
||||||
|
// @Failure 400 {object} HTTPError
|
||||||
|
// @Failure 500 {object} HTTPError
|
||||||
|
// @Router /roles/:role/permissions [delete]
|
||||||
|
func (h *Handlers) DeletePermissionForRole(ctx *gin.Context) {
|
||||||
|
var params types.RoleParams
|
||||||
|
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var json types.DeletePermissionForRoleRequest
|
||||||
|
if err := ctx.ShouldBindJSON(&json); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok, err := h.Service.DeletePermissionForRole(params.Role, json); err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
} else if !ok {
|
||||||
|
ctx.Status(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
@ -58,63 +58,21 @@ func (h *Handlers) SignUp(ctx *gin.Context) {
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @Failure 400
|
// @Failure 400
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /users/reset_password [post]
|
// @Router /users/:id/reset_password [post]
|
||||||
func (h *Handlers) ResetPassword(ctx *gin.Context) {
|
func (h *Handlers) ResetPassword(ctx *gin.Context) {
|
||||||
|
var params types.UserParams
|
||||||
|
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var json types.ResetPasswordRequest
|
var json types.ResetPasswordRequest
|
||||||
if err := ctx.ShouldBindJSON(&json); err != nil {
|
if err := ctx.ShouldBindJSON(&json); err != nil {
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.Service.ResetPassword(ctx.GetUint("userID"), json); err != nil {
|
if err := h.Service.ResetPassword(params.ID, json); err != nil {
|
||||||
ctx.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Status(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Delete Role For User
|
|
||||||
// @Description delete role by uri config
|
|
||||||
// @Tags users
|
|
||||||
// @Accept text
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200
|
|
||||||
// @Failure 400 {object} HTTPError
|
|
||||||
// @Failure 500 {object} HTTPError
|
|
||||||
// @Router /users/:id/roles/:role_name [delete]
|
|
||||||
func (h *Handlers) DeleteRoleForUser(ctx *gin.Context) {
|
|
||||||
var params types.DeleteRoleForUserParams
|
|
||||||
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := h.Service.DeleteRoleForUser(params); err != nil {
|
|
||||||
ctx.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Status(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Add Role For User
|
|
||||||
// @Description add role to user by uri config
|
|
||||||
// @Tags users
|
|
||||||
// @Accept text
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200
|
|
||||||
// @Failure 400 {object} HTTPError
|
|
||||||
// @Failure 500 {object} HTTPError
|
|
||||||
// @Router /users/:id/roles/:role_name [post]
|
|
||||||
func (h *Handlers) AddRoleToUser(ctx *gin.Context) {
|
|
||||||
var params types.AddRoleForUserParams
|
|
||||||
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
|
||||||
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := h.Service.AddRoleForUser(params); err != nil {
|
|
||||||
ctx.Error(err)
|
ctx.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +84,8 @@ func (h *Handlers) AddRoleToUser(ctx *gin.Context) {
|
||||||
// @Description get roles by json config
|
// @Description get roles by json config
|
||||||
// @Tags User
|
// @Tags User
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} RoutesInfo
|
// @Param id path string true "id"
|
||||||
|
// @Success 200 {object} []string
|
||||||
// @Failure 400 {object} HTTPError
|
// @Failure 400 {object} HTTPError
|
||||||
// @Failure 500 {object} HTTPError
|
// @Failure 500 {object} HTTPError
|
||||||
// @Router /users/:id/roles [get]
|
// @Router /users/:id/roles [get]
|
||||||
|
|
@ -137,7 +96,7 @@ func (h *Handlers) GetRolesForUser(ctx *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
roles, err := h.Service.GetRolesForUser(params.ID, ctx.GetString("userName"))
|
roles, err := h.Service.GetRolesForUser(params.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(err)
|
ctx.Error(err)
|
||||||
return
|
return
|
||||||
|
|
@ -145,3 +104,61 @@ func (h *Handlers) GetRolesForUser(ctx *gin.Context) {
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, roles)
|
ctx.JSON(http.StatusOK, roles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary Add Role For User
|
||||||
|
// @Description add role to user by uri config
|
||||||
|
// @Tags users
|
||||||
|
// @Accept text
|
||||||
|
// @Produce json
|
||||||
|
// @Param id path string true "id"
|
||||||
|
// @Param role path string true "role"
|
||||||
|
// @Success 200
|
||||||
|
// @Failure 400 {object} HTTPError
|
||||||
|
// @Failure 500 {object} HTTPError
|
||||||
|
// @Router /users/:id/roles/:role [put]
|
||||||
|
func (h *Handlers) AddRoleToUser(ctx *gin.Context) {
|
||||||
|
var params types.AddRoleForUserParams
|
||||||
|
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok, err := h.Service.AddRoleForUser(params); err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
} else if !ok {
|
||||||
|
ctx.Status(http.StatusConflict)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Delete Role For User
|
||||||
|
// @Description delete role by uri config
|
||||||
|
// @Tags users
|
||||||
|
// @Accept text
|
||||||
|
// @Produce json
|
||||||
|
// @Param id path string true "id"
|
||||||
|
// @Param role path string true "role"
|
||||||
|
// @Success 200
|
||||||
|
// @Failure 400 {object} HTTPError
|
||||||
|
// @Failure 500 {object} HTTPError
|
||||||
|
// @Router /users/:id/roles/:role [delete]
|
||||||
|
func (h *Handlers) DeleteRoleForUser(ctx *gin.Context) {
|
||||||
|
var params types.DeleteRoleForUserParams
|
||||||
|
if err := ctx.ShouldBindUri(¶ms); err != nil {
|
||||||
|
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok, err := h.Service.DeleteRoleForUser(params); err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
} else if !ok {
|
||||||
|
ctx.Status(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ func New(cfg *config.Config) (*Server, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize roles and check roles
|
// Initialize roles and check roles
|
||||||
err = rbac.InitRole(enforcer, router)
|
err = rbac.InitRBAC(enforcer, router)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type user struct {
|
type user struct {
|
||||||
userName string
|
name string
|
||||||
ID uint
|
id uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
|
func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
|
||||||
var identityKey = "username"
|
identityKey := "id"
|
||||||
|
|
||||||
authMiddleware, err := jwt.New(&jwt.GinJWTMiddleware{
|
authMiddleware, err := jwt.New(&jwt.GinJWTMiddleware{
|
||||||
Realm: "Dragonfly",
|
Realm: "Dragonfly",
|
||||||
Key: []byte("Secret Key"),
|
Key: []byte("Secret Key"),
|
||||||
|
|
@ -44,7 +45,7 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
|
||||||
IdentityHandler: func(c *gin.Context) interface{} {
|
IdentityHandler: func(c *gin.Context) interface{} {
|
||||||
claims := jwt.ExtractClaims(c)
|
claims := jwt.ExtractClaims(c)
|
||||||
|
|
||||||
userName, ok := claims[identityKey]
|
id, ok := claims[identityKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{
|
c.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"message": "Unavailable token: require user name",
|
"message": "Unavailable token: require user name",
|
||||||
|
|
@ -53,7 +54,7 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, ok := claims["ID"]
|
name, ok := claims["name"]
|
||||||
if !ok {
|
if !ok {
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{
|
c.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"message": "Unavailable token: require user id",
|
"message": "Unavailable token: require user id",
|
||||||
|
|
@ -63,12 +64,12 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u := &user{
|
u := &user{
|
||||||
userName: userName.(string),
|
name: name.(string),
|
||||||
ID: userID.(uint),
|
id: id.(uint),
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Set("userName", u.userName)
|
c.Set("name", u.name)
|
||||||
c.Set("userID", u.ID)
|
c.Set("id", u.id)
|
||||||
return u
|
return u
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -89,8 +90,8 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
|
||||||
PayloadFunc: func(data interface{}) jwt.MapClaims {
|
PayloadFunc: func(data interface{}) jwt.MapClaims {
|
||||||
if u, ok := data.(*model.User); ok {
|
if u, ok := data.(*model.User); ok {
|
||||||
return jwt.MapClaims{
|
return jwt.MapClaims{
|
||||||
identityKey: u.Name,
|
identityKey: u.ID,
|
||||||
"ID": u.ID,
|
"name": u.Name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package middlewares
|
package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
logger "d7y.io/dragonfly/v2/internal/dflog"
|
logger "d7y.io/dragonfly/v2/internal/dflog"
|
||||||
|
|
@ -27,47 +28,35 @@ import (
|
||||||
|
|
||||||
func RBAC(e *casbin.Enforcer) gin.HandlerFunc {
|
func RBAC(e *casbin.Enforcer) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
userName := c.GetString("userName")
|
action := rbac.HTTPMethodToAction(c.Request.Method)
|
||||||
// request path
|
permission, err := rbac.GetAPIGroupName(c.Request.URL.Path)
|
||||||
p := c.Request.URL.Path
|
|
||||||
permissionName, err := rbac.GetAPIGroupName(p)
|
|
||||||
if err != nil {
|
|
||||||
c.Next()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// request method
|
|
||||||
m := c.Request.Method
|
|
||||||
action := rbac.HTTPMethodToAction(m)
|
|
||||||
// rbac validation
|
|
||||||
adminRes, err := e.HasRoleForUser(userName, "admin")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.Errorf("get api group name error: %s", err)
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{
|
c.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"message": "permission validate error",
|
"message": "permission validate error!",
|
||||||
})
|
})
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if adminRes {
|
|
||||||
c.Next()
|
ok, err := e.Enforce(fmt.Sprint(c.GetUint("id")), permission, action)
|
||||||
return
|
|
||||||
}
|
|
||||||
res, err := e.Enforce(userName, permissionName, action)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("RBAC validate error: %s", err)
|
logger.Errorf("RBAC validate error: %s", err)
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{
|
c.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"message": "permission validate error, please see log!",
|
"message": "permission validate error!",
|
||||||
})
|
})
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !res {
|
|
||||||
|
if !ok {
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{
|
c.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"message": "permission deny",
|
"message": "permission deny",
|
||||||
})
|
})
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Next()
|
|
||||||
|
|
||||||
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,9 @@ package rbac
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
|
|
||||||
logger "d7y.io/dragonfly/v2/internal/dflog"
|
|
||||||
managermodel "d7y.io/dragonfly/v2/manager/model"
|
managermodel "d7y.io/dragonfly/v2/manager/model"
|
||||||
"d7y.io/dragonfly/v2/pkg/util/stringutils"
|
"d7y.io/dragonfly/v2/pkg/util/stringutils"
|
||||||
"github.com/casbin/casbin/v2"
|
"github.com/casbin/casbin/v2"
|
||||||
|
|
@ -56,93 +53,83 @@ func NewEnforcer(gdb *gorm.DB) (*casbin.Enforcer, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := model.NewModelFromString(modelText)
|
m, err := model.NewModelFromString(modelText)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
enforcer, err := casbin.NewEnforcer(m, adapter)
|
enforcer, err := casbin.NewEnforcer(m, adapter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return enforcer, nil
|
return enforcer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitRole(e *casbin.Enforcer, g *gin.Engine) error {
|
func InitRBAC(e *casbin.Enforcer, g *gin.Engine) error {
|
||||||
systemRoles := SystemRoles(g)
|
permissions := GetPermissions(g)
|
||||||
|
for _, permission := range permissions {
|
||||||
var err error
|
if _, err := e.AddPermissionForUser("root", permission.Object, "*"); err != nil {
|
||||||
for _, role := range systemRoles {
|
|
||||||
roleInfo := strings.Split(role, ":")
|
|
||||||
_, err = e.AddPolicy(role, roleInfo[0], roleInfo[1])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// init admin permissions
|
|
||||||
_, err = e.AddPolicy("admin", roleInfo[0], "*")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err := e.AddRoleForUser("admin", "admin"); err != nil {
|
|
||||||
|
if _, err := e.AddRoleForUser("1", "root"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logger.Info("init and check role success")
|
|
||||||
return nil
|
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Permission struct {
|
||||||
|
Object string
|
||||||
|
Action string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPermissions(g *gin.Engine) []Permission {
|
||||||
|
permissions := []Permission{}
|
||||||
|
actions := []string{"read", "*"}
|
||||||
|
for _, permission := range GetAPIGroupNames(g) {
|
||||||
|
for _, action := range actions {
|
||||||
|
permissions = append(permissions, Permission{
|
||||||
|
Object: permission,
|
||||||
|
Action: action,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAPIGroupNames(g *gin.Engine) []string {
|
||||||
|
apiGroupNames := []string{}
|
||||||
|
for _, route := range g.Routes() {
|
||||||
|
name, err := GetAPIGroupName(route.Path)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !stringutils.Contains(apiGroupNames, name) {
|
||||||
|
apiGroupNames = append(apiGroupNames, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiGroupNames
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAPIGroupName(path string) (string, error) {
|
func GetAPIGroupName(path string) (string, error) {
|
||||||
apiGroupRegexp := regexp.MustCompile(`^/api/v[0-9]+/([-_a-zA-Z]*)[/.*]*`)
|
apiGroupRegexp := regexp.MustCompile(`^/api/v[0-9]+/([-_a-zA-Z]*)[/.*]*`)
|
||||||
matchs := apiGroupRegexp.FindStringSubmatch(path)
|
matchs := apiGroupRegexp.FindStringSubmatch(path)
|
||||||
if len(matchs) != 2 {
|
if len(matchs) != 2 {
|
||||||
return "", errors.New("faild to find api group")
|
return "", errors.New("cannot find group name")
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchs[1], nil
|
return matchs[1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RoleName(object, action string) string {
|
|
||||||
if object == "admin" {
|
|
||||||
return "admin"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s:%s", object, action)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAPIGroupNames(g *gin.Engine) []string {
|
|
||||||
APIGroups := []string{}
|
|
||||||
for _, route := range g.Routes() {
|
|
||||||
apiGroupName, err := GetAPIGroupName(route.Path)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !stringutils.Contains(APIGroups, apiGroupName) {
|
|
||||||
APIGroups = append(APIGroups, apiGroupName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return APIGroups
|
|
||||||
}
|
|
||||||
|
|
||||||
func SystemRoles(g *gin.Engine) []string {
|
|
||||||
Roles := []string{}
|
|
||||||
policyKeys := []string{"read", "*"}
|
|
||||||
|
|
||||||
for _, apiGroup := range GetAPIGroupNames(g) {
|
|
||||||
for _, p := range policyKeys {
|
|
||||||
if !stringutils.Contains(Roles, apiGroup+":"+p) {
|
|
||||||
Roles = append(Roles, apiGroup+":"+p)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Roles
|
|
||||||
}
|
|
||||||
|
|
||||||
func HTTPMethodToAction(method string) string {
|
func HTTPMethodToAction(method string) string {
|
||||||
action := "read"
|
action := "read"
|
||||||
|
|
||||||
if method == http.MethodDelete || method == http.MethodPatch || method == http.MethodPut || method == http.MethodPost {
|
if method == http.MethodDelete || method == http.MethodPatch || method == http.MethodPut || method == http.MethodPost {
|
||||||
action = "*"
|
action = "*"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ func TestGetApiGroupName(t *testing.T) {
|
||||||
path: "/api/user",
|
path: "/api/user",
|
||||||
expect: func(t *testing.T, data string, err error) {
|
expect: func(t *testing.T, data string, err error) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
assert.EqualError(err, "faild to find api group")
|
assert.EqualError(err, "cannot find group name")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -65,7 +65,7 @@ func TestGetApiGroupName(t *testing.T) {
|
||||||
path: "",
|
path: "",
|
||||||
expect: func(t *testing.T, data string, err error) {
|
expect: func(t *testing.T, data string, err error) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
assert.EqualError(err, "faild to find api group")
|
assert.EqualError(err, "cannot find group name")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -78,32 +78,6 @@ func TestGetApiGroupName(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRoleName(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
object string
|
|
||||||
action string
|
|
||||||
exceptedRoleName string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
object: "users",
|
|
||||||
action: "read",
|
|
||||||
exceptedRoleName: "users:read",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
object: "cdns",
|
|
||||||
action: "*",
|
|
||||||
exceptedRoleName: "cdns:*",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
roleName := RoleName(tt.object, tt.action)
|
|
||||||
if roleName != tt.exceptedRoleName {
|
|
||||||
t.Errorf("RoleName(%v, %v) = %v, want %v", tt.object, tt.action, roleName, tt.exceptedRoleName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
func TestHTTPMethodToAction(t *testing.T) {
|
func TestHTTPMethodToAction(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
method string
|
method string
|
||||||
|
|
@ -129,5 +103,4 @@ func TestHTTPMethodToAction(t *testing.T) {
|
||||||
t.Errorf("HttpMethodToAction(%v) = %v, want %v", tt.method, action, tt.exceptedAction)
|
t.Errorf("HttpMethodToAction(%v) = %v, want %v", tt.method, action, tt.exceptedAction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,14 +79,38 @@ func Init(console bool, verbose bool, publicPath string, service service.REST, e
|
||||||
apiv1 := r.Group("/api/v1")
|
apiv1 := r.Group("/api/v1")
|
||||||
|
|
||||||
// User
|
// User
|
||||||
ai := apiv1.Group("/users")
|
u := apiv1.Group("/users")
|
||||||
ai.POST("/signin", jwt.LoginHandler)
|
u.POST("/signin", jwt.LoginHandler)
|
||||||
ai.POST("/signout", jwt.LogoutHandler)
|
u.POST("/signout", jwt.LogoutHandler)
|
||||||
ai.POST("/signup", h.SignUp)
|
u.POST("/signup", h.SignUp)
|
||||||
ai.POST("/refresh_token", jwt.RefreshHandler)
|
u.POST("/refresh_token", jwt.RefreshHandler)
|
||||||
ai.POST("/reset_password", h.ResetPassword)
|
u.POST("/:id/reset_password", h.ResetPassword)
|
||||||
ai.POST("/:id/roles/:role_name", h.AddRoleToUser, jwt.MiddlewareFunc(), rbac)
|
u.GET("/:id/roles", h.GetRolesForUser)
|
||||||
ai.DELETE("/:id/roles/:role_name", h.DeleteRoleForUser, jwt.MiddlewareFunc(), rbac)
|
u.PUT("/:id/roles/:role", h.AddRoleToUser)
|
||||||
|
u.DELETE("/:id/roles/:role", h.DeleteRoleForUser)
|
||||||
|
|
||||||
|
// Role
|
||||||
|
re := apiv1.Group("/roles")
|
||||||
|
re.POST("", h.CreateRole)
|
||||||
|
re.DELETE("/:role", h.DestroyRole)
|
||||||
|
re.GET("/:role", h.GetRole)
|
||||||
|
re.GET("", h.GetRoles)
|
||||||
|
re.POST("/:role/permissions", h.AddPermissionForRole)
|
||||||
|
re.DELETE("/:role/permissions", h.DeletePermissionForRole)
|
||||||
|
|
||||||
|
// Permission
|
||||||
|
pm := apiv1.Group("/permissions", jwt.MiddlewareFunc(), rbac)
|
||||||
|
pm.GET("", h.GetPermissions(r))
|
||||||
|
|
||||||
|
// Oauth
|
||||||
|
oa := apiv1.Group("/oauth")
|
||||||
|
oa.GET("", h.GetOauths)
|
||||||
|
oa.GET("/:id", h.GetOauth)
|
||||||
|
oa.DELETE("/:id", h.DestroyOauth)
|
||||||
|
oa.PUT("/:id", h.UpdateOauth)
|
||||||
|
oa.POST("", h.CreateOauth)
|
||||||
|
oa.GET("/signin/:oauth_name", h.OauthSignin)
|
||||||
|
oa.GET("/callback/:oauth_name", h.OauthCallback(jwt))
|
||||||
|
|
||||||
// Scheduler Cluster
|
// Scheduler Cluster
|
||||||
sc := apiv1.Group("/scheduler-clusters")
|
sc := apiv1.Group("/scheduler-clusters")
|
||||||
|
|
@ -130,29 +154,6 @@ func Init(console bool, verbose bool, publicPath string, service service.REST, e
|
||||||
c.GET(":id", h.GetCDN)
|
c.GET(":id", h.GetCDN)
|
||||||
c.GET("", h.GetCDNs)
|
c.GET("", h.GetCDNs)
|
||||||
|
|
||||||
// Role
|
|
||||||
re := apiv1.Group("/roles", jwt.MiddlewareFunc(), rbac)
|
|
||||||
re.POST("", h.CreateRole)
|
|
||||||
re.GET("", h.GetRoles)
|
|
||||||
re.DELETE("/:role_name", h.DestroyRole)
|
|
||||||
re.GET("/:role_name", h.GetRole)
|
|
||||||
re.POST("/:role_name/permission", h.AddRolePermission)
|
|
||||||
re.DELETE("/:role_name/permission", h.RemoveRolePermission)
|
|
||||||
|
|
||||||
// Permission
|
|
||||||
pn := apiv1.Group("/permissions", jwt.MiddlewareFunc(), rbac)
|
|
||||||
pn.GET("", h.GetPermissions(r))
|
|
||||||
|
|
||||||
// oauth
|
|
||||||
oa := apiv1.Group("/oauth")
|
|
||||||
oa.GET("", h.GetOauths)
|
|
||||||
oa.GET("/:id", h.GetOauth)
|
|
||||||
oa.DELETE("/:id", h.DestroyOauth)
|
|
||||||
oa.PUT("/:id", h.UpdateOauth)
|
|
||||||
oa.POST("", h.CreateOauth)
|
|
||||||
oa.GET("/signin/:oauth_name", h.OauthSignin)
|
|
||||||
oa.GET("/callback/:oauth_name", h.OauthCallback(jwt))
|
|
||||||
|
|
||||||
// Security Group
|
// Security Group
|
||||||
sg := apiv1.Group("/security-groups")
|
sg := apiv1.Group("/security-groups")
|
||||||
sg.POST("", h.CreateSecurityGroup)
|
sg.POST("", h.CreateSecurityGroup)
|
||||||
|
|
|
||||||
|
|
@ -17,100 +17,10 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
|
|
||||||
logger "d7y.io/dragonfly/v2/internal/dflog"
|
|
||||||
"d7y.io/dragonfly/v2/manager/model"
|
|
||||||
"d7y.io/dragonfly/v2/manager/permission/rbac"
|
"d7y.io/dragonfly/v2/manager/permission/rbac"
|
||||||
"d7y.io/dragonfly/v2/manager/types"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *rest) GetPermissions(g *gin.Engine) types.Permissions {
|
func (s *rest) GetPermissions(g *gin.Engine) []rbac.Permission {
|
||||||
return rbac.GetAPIGroupNames(g)
|
return rbac.GetPermissions(g)
|
||||||
}
|
|
||||||
|
|
||||||
func (s *rest) CreateRole(json types.CreateRolePermissionRequest) error {
|
|
||||||
for _, p := range json.Permissions {
|
|
||||||
res, err := s.enforcer.AddPolicy(json.RoleName, p.Object, p.Action)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !res {
|
|
||||||
logger.Infof("The role %s that %s for %s already exist. skip!", json.RoleName, p.Object, p.Action)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *rest) GetRoles() []string {
|
|
||||||
return s.enforcer.GetAllSubjects()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *rest) AddRolePermission(roleName string, json types.ObjectPermission) error {
|
|
||||||
_, err := s.enforcer.AddPolicy(roleName, json.Object, json.Action)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *rest) RemoveRolePermission(roleName string, json types.ObjectPermission) error {
|
|
||||||
_, err := s.enforcer.RemovePolicy(roleName, json.Object, json.Action)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *rest) DestroyRole(roleName string) error {
|
|
||||||
_, err := s.enforcer.DeleteRole(roleName)
|
|
||||||
s.enforcer.GetAllRoles()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *rest) GetRole(roleName string) []map[string]string {
|
|
||||||
result := []map[string]string{}
|
|
||||||
policies := s.enforcer.GetFilteredPolicy(0, roleName)
|
|
||||||
for _, p := range policies {
|
|
||||||
result = append(result, map[string]string{"object": p[1], "action": p[2]})
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *rest) GetRolesForUser(UserID uint, currentUserName string) ([]string, error) {
|
|
||||||
var results []string
|
|
||||||
var err error
|
|
||||||
user := model.User{}
|
|
||||||
if err := s.db.First(&user, UserID).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
queryUserName := user.Name
|
|
||||||
|
|
||||||
if queryUserName == currentUserName {
|
|
||||||
results, err = s.enforcer.GetRolesForUser(queryUserName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
has, err := s.enforcer.Enforce(currentUserName, "users", "read")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if has {
|
|
||||||
results, err = s.enforcer.GetRolesForUser(queryUserName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("permission deny")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The Dragonfly Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"d7y.io/dragonfly/v2/manager/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *rest) CreateRole(json types.CreateRoleRequest) error {
|
||||||
|
for _, permission := range json.Permissions {
|
||||||
|
_, err := s.enforcer.AddPermissionForUser(json.Role, permission.Object, permission.Action)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rest) DestroyRole(role string) (bool, error) {
|
||||||
|
return s.enforcer.DeleteRole(role)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rest) GetRole(role string) [][]string {
|
||||||
|
return s.enforcer.GetPermissionsForUser(role)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rest) GetRoles() []string {
|
||||||
|
return s.enforcer.GetAllRoles()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rest) AddPermissionForRole(role string, json types.AddPermissionForRoleRequest) (bool, error) {
|
||||||
|
return s.enforcer.AddPermissionForUser(role, json.Object, json.Action)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rest) DeletePermissionForRole(role string, json types.DeletePermissionForRoleRequest) (bool, error) {
|
||||||
|
return s.enforcer.DeletePermissionForUser(role, json.Object, json.Action)
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"d7y.io/dragonfly/v2/manager/database"
|
"d7y.io/dragonfly/v2/manager/database"
|
||||||
"d7y.io/dragonfly/v2/manager/job"
|
"d7y.io/dragonfly/v2/manager/job"
|
||||||
"d7y.io/dragonfly/v2/manager/model"
|
"d7y.io/dragonfly/v2/manager/model"
|
||||||
|
"d7y.io/dragonfly/v2/manager/permission/rbac"
|
||||||
"d7y.io/dragonfly/v2/manager/types"
|
"d7y.io/dragonfly/v2/manager/types"
|
||||||
"github.com/casbin/casbin/v2"
|
"github.com/casbin/casbin/v2"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
@ -33,19 +34,18 @@ type REST interface {
|
||||||
SignIn(types.SignInRequest) (*model.User, error)
|
SignIn(types.SignInRequest) (*model.User, error)
|
||||||
SignUp(types.SignUpRequest) (*model.User, error)
|
SignUp(types.SignUpRequest) (*model.User, error)
|
||||||
ResetPassword(uint, types.ResetPasswordRequest) error
|
ResetPassword(uint, types.ResetPasswordRequest) error
|
||||||
|
GetRolesForUser(uint) ([]string, error)
|
||||||
|
AddRoleForUser(types.AddRoleForUserParams) (bool, error)
|
||||||
|
DeleteRoleForUser(types.DeleteRoleForUserParams) (bool, error)
|
||||||
|
|
||||||
AddRoleForUser(types.AddRoleForUserParams) error
|
CreateRole(json types.CreateRoleRequest) error
|
||||||
DeleteRoleForUser(types.DeleteRoleForUserParams) error
|
DestroyRole(string) (bool, error)
|
||||||
|
GetRole(string) [][]string
|
||||||
GetPermissions(*gin.Engine) types.Permissions
|
|
||||||
|
|
||||||
CreateRole(json types.CreateRolePermissionRequest) error
|
|
||||||
DestroyRole(string) error
|
|
||||||
AddRolePermission(string, types.ObjectPermission) error
|
|
||||||
RemoveRolePermission(string, types.ObjectPermission) error
|
|
||||||
GetRoles() []string
|
GetRoles() []string
|
||||||
GetRole(string) []map[string]string
|
AddPermissionForRole(string, types.AddPermissionForRoleRequest) (bool, error)
|
||||||
GetRolesForUser(uint, string) ([]string, error)
|
DeletePermissionForRole(string, types.DeletePermissionForRoleRequest) (bool, error)
|
||||||
|
|
||||||
|
GetPermissions(*gin.Engine) []rbac.Permission
|
||||||
|
|
||||||
CreateCDNCluster(types.CreateCDNClusterRequest) (*model.CDNCluster, error)
|
CreateCDNCluster(types.CreateCDNClusterRequest) (*model.CDNCluster, error)
|
||||||
CreateCDNClusterWithSecurityGroupDomain(types.CreateCDNClusterRequest) (*model.CDNCluster, error)
|
CreateCDNClusterWithSecurityGroupDomain(types.CreateCDNClusterRequest) (*model.CDNCluster, error)
|
||||||
|
|
|
||||||
|
|
@ -88,18 +88,14 @@ func (s *rest) SignUp(json types.SignUpRequest) (*model.User, error) {
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *rest) AddRoleForUser(json types.AddRoleForUserParams) error {
|
func (s *rest) GetRolesForUser(id uint) ([]string, error) {
|
||||||
if _, err := s.enforcer.AddRoleForUser(fmt.Sprint(json.ID), json.RoleName); err != nil {
|
return s.enforcer.GetRolesForUser(fmt.Sprint(id))
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *rest) DeleteRoleForUser(json types.DeleteRoleForUserParams) error {
|
func (s *rest) AddRoleForUser(json types.AddRoleForUserParams) (bool, error) {
|
||||||
if _, err := s.enforcer.DeleteRoleForUser(fmt.Sprint(json.ID), json.RoleName); err != nil {
|
return s.enforcer.AddRoleForUser(fmt.Sprint(json.ID), json.Role)
|
||||||
return err
|
}
|
||||||
}
|
|
||||||
|
func (s *rest) DeleteRoleForUser(json types.DeleteRoleForUserParams) (bool, error) {
|
||||||
return nil
|
return s.enforcer.DeleteRoleForUser(fmt.Sprint(json.ID), json.Role)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,22 +16,23 @@
|
||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"d7y.io/dragonfly/v2/manager/permission/rbac"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateRoleRequest struct {
|
||||||
|
Role string `json:"role" binding:"required"`
|
||||||
|
Permissions []rbac.Permission `json:"permissions" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
type RoleParams struct {
|
type RoleParams struct {
|
||||||
RoleName string `uri:"role_name" binding:"required,min=1"`
|
Role string `uri:"role" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserParams struct {
|
type AddPermissionForRoleRequest struct {
|
||||||
ID uint `uri:"user_name" binding:"required"`
|
rbac.Permission `json:",inline" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ObjectPermission struct {
|
type DeletePermissionForRoleRequest struct {
|
||||||
Object string `json:"object" binding:"required,min=1"`
|
rbac.Permission `json:",inline" binding:"required"`
|
||||||
Action string `json:"action" binding:"required,oneof=read *"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateRolePermissionRequest struct {
|
|
||||||
RoleName string `json:"role_name" binding:"required"`
|
|
||||||
Permissions []ObjectPermission `json:"permissions" binding:"dive"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Permissions []string
|
|
||||||
|
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
type UserParams struct {
|
||||||
|
ID uint `uri:"id" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
type SignInRequest struct {
|
type SignInRequest struct {
|
||||||
Name string `json:"name" binding:"required,min=3,max=10"`
|
Name string `json:"name" binding:"required,min=3,max=10"`
|
||||||
Password string `json:"password" binding:"required,min=8,max=20"`
|
Password string `json:"password" binding:"required,min=8,max=20"`
|
||||||
|
|
@ -36,11 +40,11 @@ type SignUpRequest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeleteRoleForUserParams struct {
|
type DeleteRoleForUserParams struct {
|
||||||
ID uint `uri:"id" binding:"required"`
|
ID uint `uri:"id" binding:"required"`
|
||||||
RoleName string `uri:"role_name" binding:"required,min=1"`
|
Role string `uri:"role" binding:"required,min=1"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddRoleForUserParams struct {
|
type AddRoleForUserParams struct {
|
||||||
ID uint `uri:"id" binding:"required"`
|
ID uint `uri:"id" binding:"required"`
|
||||||
RoleName string `uri:"role_name" binding:"required,min=1"`
|
Role string `uri:"role" binding:"required,min=1"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue