Skip to content

Commit

Permalink
Merge pull request #297 from cho4036/mod_permissions
Browse files Browse the repository at this point in the history
User에 대한 Permission 리스트 출력 API 개발
  • Loading branch information
ktkfree authored Mar 25, 2024
2 parents 6ae52b4 + 47fff12 commit b6dce8a
Show file tree
Hide file tree
Showing 10 changed files with 875 additions and 220 deletions.
2 changes: 1 addition & 1 deletion internal/delivery/api/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const (
VerifyIdentityForLostId
VerifyIdentityForLostPassword
VerifyToken
DeleteToken

// User
CreateUser
Expand Down Expand Up @@ -195,6 +194,7 @@ const (
GetPermissionTemplates
GetPermissionsByRoleId
UpdatePermissionsByRoleId
GetPermissionsByAccountId

// Admin_User
Admin_CreateUser
Expand Down
70 changes: 70 additions & 0 deletions internal/delivery/api/endpoints_permission_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package api_test

import (
"github.com/openinfradev/tks-api/internal/delivery/api"
"github.com/openinfradev/tks-api/internal/model"
"testing"
)

func TestEndpointsUsage(t *testing.T) {
var allEndpoints []string
for _, v := range api.ApiMap {
allEndpoints = append(allEndpoints, v.Name)
}
//allEndpoints := []Endpoint{
// Login, Logout, RefreshToken, FindId, // 계속해서 모든 Endpoint 추가
// // 나머지 Endpoint 상수들을 여기에 추가
//}
usageCount := make(map[string]int)
ps := model.NewAdminPermissionSet()

permissions := []*model.Permission{
ps.Dashboard,
ps.Notification,
ps.Configuration,
ps.ProjectManagement,
ps.Stack,
ps.Policy,
ps.Common,
ps.Admin,
}

leafPermissions := make([]*model.Permission, 0)

for _, perm := range permissions {
leafPermissions = model.GetEdgePermission(perm, leafPermissions, nil)
}

// Permission 설정에서 Endpoint 사용 횟수 카운트
for _, perm := range leafPermissions {
countEndpoints(perm, usageCount)
}

var unusedEndpoints, duplicatedEndpoints []string

// 미사용 또는 중복 사용된 Endpoint 확인 및 출력
for _, endpoint := range allEndpoints {
count, exists := usageCount[endpoint]
if !exists {
unusedEndpoints = append(unusedEndpoints, endpoint)
} else if count > 1 {
duplicatedEndpoints = append(duplicatedEndpoints, endpoint)
}
}

for _, endpoint := range unusedEndpoints {
t.Logf("Unused Endpoint: %s", endpoint)
}

t.Logf("\n")
for _, endpoint := range duplicatedEndpoints {
t.Logf("Duplicated Endpoint: %s", endpoint)
}

}

func countEndpoints(perm *model.Permission, usageCount map[string]int) {
for _, endpoint := range perm.Endpoints {
usageCount[endpoint.Name]++
}
}
16 changes: 8 additions & 8 deletions internal/delivery/api/generated_endpoints.go.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ var ApiMap = map[Endpoint]EndpointInfo{
Name: "VerifyToken",
Group: "Auth",
},
DeleteToken: {
Name: "DeleteToken",
Group: "Auth",
},
CreateUser: {
Name: "CreateUser",
Group: "User",
Expand Down Expand Up @@ -603,6 +599,10 @@ var ApiMap = map[Endpoint]EndpointInfo{
Name: "UpdatePermissionsByRoleId",
Group: "Permission",
},
GetPermissionsByAccountId: {
Name: "GetPermissionsByAccountId",
Group: "Permission",
},
Admin_CreateUser: {
Name: "Admin_CreateUser",
Group: "Admin_User",
Expand Down Expand Up @@ -826,8 +826,6 @@ func (e Endpoint) String() string {
return "VerifyIdentityForLostPassword"
case VerifyToken:
return "VerifyToken"
case DeleteToken:
return "DeleteToken"
case CreateUser:
return "CreateUser"
case ListUser:
Expand Down Expand Up @@ -1110,6 +1108,8 @@ func (e Endpoint) String() string {
return "GetPermissionsByRoleId"
case UpdatePermissionsByRoleId:
return "UpdatePermissionsByRoleId"
case GetPermissionsByAccountId:
return "GetPermissionsByAccountId"
case Admin_CreateUser:
return "Admin_CreateUser"
case Admin_ListUser:
Expand Down Expand Up @@ -1234,8 +1234,6 @@ func GetEndpoint(name string) Endpoint {
return VerifyIdentityForLostPassword
case "VerifyToken":
return VerifyToken
case "DeleteToken":
return DeleteToken
case "CreateUser":
return CreateUser
case "ListUser":
Expand Down Expand Up @@ -1518,6 +1516,8 @@ func GetEndpoint(name string) Endpoint {
return GetPermissionsByRoleId
case "UpdatePermissionsByRoleId":
return UpdatePermissionsByRoleId
case "GetPermissionsByAccountId":
return GetPermissionsByAccountId
case "Admin_CreateUser":
return Admin_CreateUser
case "Admin_ListUser":
Expand Down
171 changes: 145 additions & 26 deletions internal/delivery/http/permission.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
package http

import (
"context"
"net/http"

"github.com/gorilla/mux"
"github.com/openinfradev/tks-api/internal/model"
"github.com/openinfradev/tks-api/internal/serializer"
"github.com/openinfradev/tks-api/internal/usecase"
"github.com/openinfradev/tks-api/pkg/domain"
"github.com/openinfradev/tks-api/pkg/httpErrors"
"github.com/openinfradev/tks-api/pkg/log"
)

type IPermissionHandler interface {
GetPermissionTemplates(w http.ResponseWriter, r *http.Request)
GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request)
UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request)
GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request)
}

type PermissionHandler struct {
permissionUsecase usecase.IPermissionUsecase
userUsecase usecase.IUserUsecase
}

func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler {
func NewPermissionHandler(usecase usecase.Usecase) IPermissionHandler {
return &PermissionHandler{
permissionUsecase: usecase.Permission,
userUsecase: usecase.User,
}
}

Expand All @@ -41,20 +43,110 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler {
func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) {
permissionSet := model.NewDefaultPermissionSet()

var premissionSetResponse domain.PermissionSetResponse
if err := serializer.Map(r.Context(), permissionSet, &premissionSetResponse); err != nil {
log.Info(r.Context(), err)
var out domain.GetPermissionTemplatesResponse
out.Permissions = new(domain.PermissionTemplateResponse)

out.Permissions.Dashboard = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Dashboard)
out.Permissions.Stack = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Stack)
out.Permissions.Policy = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Policy)
out.Permissions.ProjectManagement = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.ProjectManagement)
out.Permissions.Notification = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Notification)
out.Permissions.Configuration = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Configuration)

ResponseJSON(w, r, http.StatusOK, out)
}

func convertModelToPermissionTemplateResponse(ctx context.Context, permission *model.Permission) *domain.TemplateResponse {
var permissionResponse domain.TemplateResponse

permissionResponse.Key = permission.Key
permissionResponse.Name = permission.Name
if permission.IsAllowed != nil {
permissionResponse.IsAllowed = permission.IsAllowed
}

var out domain.GetPermissionTemplatesResponse
out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard)
out.Permissions = append(out.Permissions, premissionSetResponse.Stack)
out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy)
out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement)
out.Permissions = append(out.Permissions, premissionSetResponse.Notification)
out.Permissions = append(out.Permissions, premissionSetResponse.Configuration)
for _, child := range permission.Children {
permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionTemplateResponse(ctx, child))
}

return &permissionResponse
}

// GetPermissionsByAccountId godoc
//
// @Tags Permission
// @Summary Get Permissions By Account ID
// @Description Get Permissions By Account ID
// @Accept json
// @Produce json
// @Success 200 {object} domain.GetUsersPermissionsResponse
// @Router /organizations/{organizationId}/users/{accountId}/permissions [get]
// @Security JWT
func (h PermissionHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) {
var organizationId, accountId string

vars := mux.Vars(r)
if v, ok := vars["accountId"]; !ok {
ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", ""))
return
} else {
accountId = v
}
if v, ok := vars["organizationId"]; !ok {
ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", ""))
return
} else {
organizationId = v
}

user, err := h.userUsecase.GetByAccountId(r.Context(), accountId, organizationId)
if err != nil {
ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", ""))
return
}

var roles []*model.Role
roles = append(roles, &user.Role)

var permissionSets []*model.PermissionSet
for _, role := range roles {
permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID)
if err != nil {
ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", ""))
return
}
permissionSets = append(permissionSets, permissionSet)
}

mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...)

var permissions domain.MergedPermissionSetResponse
permissions.Dashboard = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard)
permissions.Stack = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack)
permissions.Policy = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy)
permissions.ProjectManagement = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement)
permissions.Notification = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification)
permissions.Configuration = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration)

var out domain.GetUsersPermissionsResponse
out.Permissions = &permissions
ResponseJSON(w, r, http.StatusOK, out)

}

func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse {
var permissionResponse domain.MergePermissionResponse

permissionResponse.Key = permission.Key
if permission.IsAllowed != nil {
permissionResponse.IsAllowed = permission.IsAllowed
}

for _, child := range permission.Children {
permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child))
}

return &permissionResponse
}

// GetPermissionsByRoleId godoc
Expand Down Expand Up @@ -85,22 +177,50 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http
return
}

var premissionSetResponse domain.PermissionSetResponse
if err := serializer.Map(r.Context(), permissionSet, &premissionSetResponse); err != nil {
log.Info(r.Context(), err)
}
var permissionSetResponse domain.PermissionSetResponse
permissionSetResponse.Dashboard = convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard)
permissionSetResponse.Stack = convertModelToPermissionResponse(r.Context(), permissionSet.Stack)
permissionSetResponse.Policy = convertModelToPermissionResponse(r.Context(), permissionSet.Policy)
permissionSetResponse.ProjectManagement = convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement)
permissionSetResponse.Notification = convertModelToPermissionResponse(r.Context(), permissionSet.Notification)
permissionSetResponse.Configuration = convertModelToPermissionResponse(r.Context(), permissionSet.Configuration)

var out domain.GetPermissionsByRoleIdResponse
out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard)
out.Permissions = append(out.Permissions, premissionSetResponse.Stack)
out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy)
out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement)
out.Permissions = append(out.Permissions, premissionSetResponse.Notification)
out.Permissions = append(out.Permissions, premissionSetResponse.Configuration)
out.Permissions = &permissionSetResponse

ResponseJSON(w, r, http.StatusOK, out)
}

func convertModelToPermissionResponse(ctx context.Context, permission *model.Permission) *domain.PermissionResponse {
var permissionResponse domain.PermissionResponse

permissionResponse.ID = permission.ID
permissionResponse.Key = permission.Key
permissionResponse.Name = permission.Name
if permission.IsAllowed != nil {
permissionResponse.IsAllowed = permission.IsAllowed
}

for _, endpoint := range permission.Endpoints {
permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint))
}

for _, child := range permission.Children {
permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child))
}

return &permissionResponse
}

func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoint) *domain.EndpointResponse {
var endpointResponse domain.EndpointResponse

endpointResponse.Name = endpoint.Name
endpointResponse.Group = endpoint.Group

return &endpointResponse
}

// UpdatePermissionsByRoleId godoc
//
// @Tags Permission
Expand All @@ -124,9 +244,8 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h

for _, permissionResponse := range input.Permissions {
var permission model.Permission
if err := serializer.Map(r.Context(), permissionResponse, &permission); err != nil {
log.Info(r.Context(), err)
}
permission.ID = permissionResponse.ID
permission.IsAllowed = permissionResponse.IsAllowed

if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil {
ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", ""))
Expand Down
Loading

0 comments on commit b6dce8a

Please sign in to comment.