Skip to content

Commit

Permalink
Support grant & revoke user role
Browse files Browse the repository at this point in the history
  • Loading branch information
slhmy committed Aug 2, 2024
1 parent 810cbf3 commit e01be54
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 4 deletions.
63 changes: 62 additions & 1 deletion cmd/web_server/handler/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"net/http"
"strconv"
"strings"

"github.com/gin-gonic/gin"
"github.com/oj-lab/oj-lab-platform/cmd/web_server/middleware"
Expand All @@ -22,13 +23,27 @@ func SetupUserRouter(baseRoute *gin.RouterGroup) {
GetUserList,
)
g.GET("/me", middleware.HandleRequireLogin, me)
g.POST("/:account/role",
middleware.HandleRequireLogin,
middleware.BuildCasbinEnforceHandlerWithDomain("system"),
grantUserRole,
)
g.DELETE("/:account/role",
middleware.HandleRequireLogin,
middleware.BuildCasbinEnforceHandlerWithDomain("system"),
revokeUserRole,
)
}
}

func AddUserCasbinPolicies() error {
enforcer := casbin_agent.GetDefaultCasbinEnforcer()
_, err := enforcer.AddPolicies([][]string{
{`role_admin`, `true`, `system`, `/api/v1/user/*any`, http.MethodGet, "allow"},
{
casbin_agent.RoleSubjectPrefix + `admin`, `true`, `system`,
`/api/v1/user/*any`, strings.Join([]string{http.MethodGet, http.MethodPost, http.MethodDelete}, "|"),
"allow",
},
})
if err != nil {
return err
Expand Down Expand Up @@ -85,3 +100,49 @@ func me(ginCtx *gin.Context) {

ginCtx.JSON(http.StatusOK, user)
}

type grantUserRoleBody struct {
Role string `json:"role" example:"admin"`
Domain string `json:"domain" example:"system"`
}

func grantUserRole(ginCtx *gin.Context) {
account := ginCtx.Param("account")
body := &grantUserRoleBody{}
err := ginCtx.BindJSON(body)
if err != nil {
modules.NewInvalidParamError("body", "invalid body").AppendToGin(ginCtx)
return
}

err = user_service.GrantUserRole(ginCtx, account, body.Role, body.Domain)
if err != nil {
modules.NewInternalError(fmt.Sprintf("failed to grant user role: %v", err)).AppendToGin(ginCtx)
return
}

ginCtx.Status(http.StatusOK)
}

type revokeUserRoleBody struct {
Role string `json:"role" example:"admin"`
Domain string `json:"domain" example:"system"`
}

func revokeUserRole(ginCtx *gin.Context) {
account := ginCtx.Param("account")
body := &revokeUserRoleBody{}
err := ginCtx.BindJSON(body)
if err != nil {
modules.NewInvalidParamError("body", "invalid body").AppendToGin(ginCtx)
return
}

err = user_service.RevokeUserRole(ginCtx, account, body.Role, body.Domain)
if err != nil {
modules.NewInternalError(fmt.Sprintf("failed to revoke user role: %v", err)).AppendToGin(ginCtx)
return
}

ginCtx.Status(http.StatusOK)
}
4 changes: 1 addition & 3 deletions cmd/web_server/middleware/casbin.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
log_module "github.com/oj-lab/oj-lab-platform/modules/log"
)

const UserSubPrefix = "user_"

func BuildCasbinEnforceHandlerWithDomain(domain string) gin.HandlerFunc {
return func(ginCtx *gin.Context) {
enforcer := casbin_agent.GetDefaultCasbinEnforcer()
Expand All @@ -21,7 +19,7 @@ func BuildCasbinEnforceHandlerWithDomain(domain string) gin.HandlerFunc {
return
}

allow, err := enforcer.Enforce(UserSubPrefix+ls.Key.Account, "_", domain, path, method)
allow, err := enforcer.Enforce(casbin_agent.UserSubjectPrefix+ls.Key.Account, "_", domain, path, method)
if err != nil {
log_module.AppLogger().Errorf("Failed to enforce: %v", err)
modules.NewInternalError("Failed to enforce").AppendToGin(ginCtx)
Expand Down
31 changes: 31 additions & 0 deletions services/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,37 @@ func GrantUserRole(ctx context.Context, account, role, domain string) error {
if !notDuplicated {
return fmt.Errorf("role already granted")
}
err = enforcer.SavePolicy()
if err != nil {
return err
}

return nil
}

func RevokeUserRole(ctx context.Context, account, role, domain string) error {
exist, err := CheckUserExist(ctx, account)
if err != nil {
return err
}
if !exist {
return fmt.Errorf("user not exist")
}

enforcer := casbin_agent.GetDefaultCasbinEnforcer()
account = casbin_agent.UserSubjectPrefix + account
role = casbin_agent.RoleSubjectPrefix + role
notDuplicated, err := enforcer.DeleteRoleForUserInDomain(account, role, domain)
if err != nil {
return err
}
if !notDuplicated {
return fmt.Errorf("role not granted")
}
err = enforcer.SavePolicy()
if err != nil {
return err
}

return nil
}
Expand Down

0 comments on commit e01be54

Please sign in to comment.