Skip to content

Commit

Permalink
feat: enable manager user's features (#598)
Browse files Browse the repository at this point in the history
* feat: enable manager user's features

Signed-off-by: Gaius <gaius.qi@gmail.com>
  • Loading branch information
gaius-qi authored Sep 3, 2021
1 parent f208dd7 commit 1186aef
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 44 deletions.
27 changes: 27 additions & 0 deletions manager/handlers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,33 @@ import (
"github.com/gin-gonic/gin"
)

// @Summary Get User
// @Description Get User by id
// @Tags User
// @Accept json
// @Produce json
// @Param id path string true "id"
// @Success 200 {object} model.User
// @Failure 400
// @Failure 404
// @Failure 500
// @Router /users/{id} [get]
func (h *Handlers) GetUser(ctx *gin.Context) {
var params types.UserParams
if err := ctx.ShouldBindUri(&params); err != nil {
ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
return
}

user, err := h.Service.GetUser(params.ID)
if err != nil {
ctx.Error(err)
return
}

ctx.JSON(http.StatusOK, user)
}

// @Summary SignUp user
// @Description signup by json config
// @Tags User
Expand Down
31 changes: 5 additions & 26 deletions manager/middlewares/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ import (
"github.com/gin-gonic/gin"
)

type user struct {
name string
id uint
}

func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
identityKey := "id"

Expand All @@ -46,15 +41,6 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
claims := jwt.ExtractClaims(c)

id, ok := claims[identityKey]
if !ok {
c.JSON(http.StatusUnauthorized, gin.H{
"message": "Unavailable token: require user name",
})
c.Abort()
return nil
}

name, ok := claims["name"]
if !ok {
c.JSON(http.StatusUnauthorized, gin.H{
"message": "Unavailable token: require user id",
Expand All @@ -63,14 +49,8 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
return nil
}

user := &user{
name: name.(string),
id: id.(uint),
}

c.Set("name", user.name)
c.Set("id", user.id)
return user
c.Set("id", id)
return id
},

Authenticator: func(c *gin.Context) (interface{}, error) {
Expand Down Expand Up @@ -101,7 +81,6 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
if user, ok := data.(*model.User); ok {
return jwt.MapClaims{
identityKey: user.ID,
"name": user.Name,
}
}

Expand All @@ -110,7 +89,7 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {

Unauthorized: func(c *gin.Context, code int, message string) {
c.JSON(code, gin.H{
"message": message,
"message": http.StatusText(code),
})
},

Expand Down Expand Up @@ -139,11 +118,11 @@ func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
})
},

TokenLookup: "header: Authorization, cookie: jwt, query: token",
TokenLookup: "cookie: jwt, header: Authorization, query: token",
TokenHeadName: "Bearer",
TimeFunc: time.Now,
SendCookie: true,
CookieHTTPOnly: true,
CookieHTTPOnly: false,
})

if err != nil {
Expand Down
14 changes: 10 additions & 4 deletions manager/middlewares/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,23 @@ func RBAC(e *casbin.Enforcer) gin.HandlerFunc {
return
}

ok, err := e.Enforce(fmt.Sprint(c.GetUint("id")), permission, action)
if err != nil {
logger.Errorf("RBAC validate error: %s", err)
id, ok := c.Get("id")
if !ok {
c.JSON(http.StatusUnauthorized, gin.H{
"message": "permission validate error!",
})
c.Abort()
return
}

if !ok {
if ok, err := e.Enforce(fmt.Sprint(id.(float64)), permission, action); err != nil {
logger.Errorf("RBAC validate error: %s", err)
c.JSON(http.StatusUnauthorized, gin.H{
"message": "permission validate error!",
})
c.Abort()
return
} else if !ok {
c.JSON(http.StatusUnauthorized, gin.H{
"message": "permission deny",
})
Expand Down
2 changes: 1 addition & 1 deletion manager/model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type User struct {
EncryptedPassword string `gorm:"column:encrypted_password;size:1024;comment:encrypted password" json:"-"`
Avatar string `gorm:"column:avatar;type:varchar(256);comment:avatar address" json:"avatar"`
Phone string `gorm:"column:phone;type:varchar(256);comment:phone number" json:"phone"`
PrivateToken string `gorm:"column:private_token;type:varchar(256);comment:private token" json:"private_token"`
PrivateToken string `gorm:"column:private_token;type:varchar(256);comment:private token" json:"-"`
State string `gorm:"column:state;type:varchar(256);default:'enable';comment:state" json:"state"`
Location string `gorm:"column:location;type:varchar(256);comment:location" json:"location"`
BIO string `gorm:"column:bio;type:varchar(256);comment:biography" json:"bio"`
Expand Down
32 changes: 19 additions & 13 deletions manager/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,24 +75,28 @@ func Init(console bool, verbose bool, publicPath string, service service.REST, e
return nil, err
}

// Manager View
r.Use(static.Serve("/", static.LocalFile(publicPath, true)))

// Router
apiv1 := r.Group("/api/v1")

// User
u := apiv1.Group("/users")
u.GET("/:id", jwt.MiddlewareFunc(), rbac, h.GetUser)
u.POST("/signin", jwt.LoginHandler)
u.POST("/signout", jwt.LogoutHandler)
u.POST("/signup", h.SignUp)
u.GET("/signin/:name", h.OauthSignin)
u.GET("/signin/:name/callback", h.OauthSigninCallback(jwt))
u.POST("/refresh_token", jwt.RefreshHandler)
u.POST("/:id/reset_password", h.ResetPassword)
u.GET("/:id/roles", h.GetRolesForUser)
u.PUT("/:id/roles/:role", h.AddRoleToUser)
u.DELETE("/:id/roles/:role", h.DeleteRoleForUser)
u.GET("/:id/roles", jwt.MiddlewareFunc(), rbac, h.GetRolesForUser)
u.PUT("/:id/roles/:role", jwt.MiddlewareFunc(), rbac, h.AddRoleToUser)
u.DELETE("/:id/roles/:role", jwt.MiddlewareFunc(), rbac, h.DeleteRoleForUser)

// Role
re := apiv1.Group("/roles")
re := apiv1.Group("/roles", jwt.MiddlewareFunc(), rbac)
re.POST("", h.CreateRole)
re.DELETE("/:role", h.DestroyRole)
re.GET("/:role", h.GetRole)
Expand All @@ -105,15 +109,15 @@ func Init(console bool, verbose bool, publicPath string, service service.REST, e
pm.GET("", h.GetPermissions(r))

// Oauth
oa := apiv1.Group("/oauth")
oa := apiv1.Group("/oauth", jwt.MiddlewareFunc(), rbac)
oa.POST("", h.CreateOauth)
oa.DELETE(":id", h.DestroyOauth)
oa.PATCH(":id", h.UpdateOauth)
oa.GET(":id", h.GetOauth)
oa.GET("", h.GetOauths)

// Scheduler Cluster
sc := apiv1.Group("/scheduler-clusters")
sc := apiv1.Group("/scheduler-clusters", jwt.MiddlewareFunc(), rbac)
sc.POST("", h.CreateSchedulerCluster)
sc.DELETE(":id", h.DestroySchedulerCluster)
sc.PATCH(":id", h.UpdateSchedulerCluster)
Expand All @@ -122,15 +126,15 @@ func Init(console bool, verbose bool, publicPath string, service service.REST, e
sc.PUT(":id/schedulers/:scheduler_id", h.AddSchedulerToSchedulerCluster)

// Scheduler
s := apiv1.Group("/schedulers")
s := apiv1.Group("/schedulers", jwt.MiddlewareFunc(), rbac)
s.POST("", h.CreateScheduler)
s.DELETE(":id", h.DestroyScheduler)
s.PATCH(":id", h.UpdateScheduler)
s.GET(":id", h.GetScheduler)
s.GET("", h.GetSchedulers)

// CDN Cluster
cc := apiv1.Group("/cdn-clusters")
cc := apiv1.Group("/cdn-clusters", jwt.MiddlewareFunc(), rbac)
cc.POST("", h.CreateCDNCluster)
cc.DELETE(":id", h.DestroyCDNCluster)
cc.PATCH(":id", h.UpdateCDNCluster)
Expand All @@ -140,15 +144,15 @@ func Init(console bool, verbose bool, publicPath string, service service.REST, e
cc.PUT(":id/scheduler-clusters/:scheduler_cluster_id", h.AddSchedulerClusterToCDNCluster)

// CDN
c := apiv1.Group("/cdns")
c := apiv1.Group("/cdns", jwt.MiddlewareFunc(), rbac)
c.POST("", h.CreateCDN)
c.DELETE(":id", h.DestroyCDN)
c.PATCH(":id", h.UpdateCDN)
c.GET(":id", h.GetCDN)
c.GET("", h.GetCDNs)

// Security Group
sg := apiv1.Group("/security-groups")
sg := apiv1.Group("/security-groups", jwt.MiddlewareFunc(), rbac)
sg.POST("", h.CreateSecurityGroup)
sg.DELETE(":id", h.DestroySecurityGroup)
sg.PATCH(":id", h.UpdateSecurityGroup)
Expand All @@ -165,12 +169,14 @@ func Init(console bool, verbose bool, publicPath string, service service.REST, e
// Health Check
r.GET("/healthy/*action", h.GetHealth)

// Manager View
r.Use(static.Serve("/", static.LocalFile(publicPath, false)))

// Swagger
apiSeagger := ginSwagger.URL("/swagger/doc.json")
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, apiSeagger))

// Fallback To Manager View
r.NoRoute(func(c *gin.Context) {
c.File(filepath.Join(publicPath, "index.html"))
})

return r, nil
}
5 changes: 5 additions & 0 deletions manager/service/cdn.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ func (s *rest) CreateCDN(json types.CreateCDNRequest) (*model.CDN, error) {
}

func (s *rest) DestroyCDN(id uint) error {
cdn := model.CDN{}
if err := s.db.First(&cdn, id).Error; err != nil {
return err
}

if err := s.db.Unscoped().Delete(&model.CDN{}, id).Error; err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions manager/service/cdn_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ func (s *rest) CreateCDNCluster(json types.CreateCDNClusterRequest) (*model.CDNC
}

func (s *rest) DestroyCDNCluster(id uint) error {
cdnCluster := model.CDNCluster{}
if err := s.db.First(&cdnCluster, id).Error; err != nil {
return err
}

if err := s.db.Unscoped().Delete(&model.CDNCluster{}, id).Error; err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions manager/service/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ func (s *rest) CreateOauth(json types.CreateOauthRequest) (*model.Oauth, error)
}

func (s *rest) DestroyOauth(id uint) error {
oauth := model.Oauth{}
if err := s.db.First(&oauth, id).Error; err != nil {
return err
}

if err := s.db.Unscoped().Delete(&model.Oauth{}, id).Error; err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions manager/service/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ func (s *rest) CreateScheduler(json types.CreateSchedulerRequest) (*model.Schedu
}

func (s *rest) DestroyScheduler(id uint) error {
scheduler := model.Scheduler{}
if err := s.db.First(&scheduler, id).Error; err != nil {
return err
}

if err := s.db.Unscoped().Delete(&model.Scheduler{}, id).Error; err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions manager/service/scheduler_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ func (s *rest) CreateSchedulerClusterWithSecurityGroupDomain(json types.CreateSc
}

func (s *rest) DestroySchedulerCluster(id uint) error {
schedulerCluster := model.SchedulerCluster{}
if err := s.db.First(&schedulerCluster, id).Error; err != nil {
return err
}

if err := s.db.Unscoped().Delete(&model.SchedulerCluster{}, id).Error; err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions manager/service/security_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ func (s *rest) CreateSecurityGroup(json types.CreateSecurityGroupRequest) (*mode
}

func (s *rest) DestroySecurityGroup(id uint) error {
securityGroup := model.SecurityGroup{}
if err := s.db.First(&securityGroup, id).Error; err != nil {
return err
}

if err := s.db.Unscoped().Delete(&model.SecurityGroup{}, id).Error; err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions manager/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
)

type REST interface {
GetUser(uint) (*model.User, error)
SignIn(types.SignInRequest) (*model.User, error)
SignUp(types.SignUpRequest) (*model.User, error)
OauthSignin(string) (string, error)
Expand Down
9 changes: 9 additions & 0 deletions manager/service/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ import (
"golang.org/x/crypto/bcrypt"
)

func (s *rest) GetUser(id uint) (*model.User, error) {
user := model.User{}
if err := s.db.First(&user, id).Error; err != nil {
return nil, err
}

return &user, nil
}

func (s *rest) SignIn(json types.SignInRequest) (*model.User, error) {
user := model.User{}
if err := s.db.First(&user, model.User{
Expand Down

0 comments on commit 1186aef

Please sign in to comment.