Skip to content

Commit

Permalink
adding permissions to roles
Browse files Browse the repository at this point in the history
  • Loading branch information
febrihidayan committed Jan 19, 2024
1 parent efcd810 commit d61d745
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 0 deletions.
54 changes: 54 additions & 0 deletions krakend/krakend.json
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,60 @@
}
}
},
{
"endpoint": "/v1/auth/acl/permission/role/{id}",
"method": "GET",
"input_headers": ["Authorization"],
"output_encoding": "no-op",
"backend": [
{
"url_pattern": "/v1/auth/acl/permission/role/{id}",
"host": [
"http://auth-go:8083"
],
"extra_config": {
"backend/http": {
"return_error_code": true
}
}
}
],
"extra_config": {
"auth/validator": {
"alg": "HS256",
"jwk_url": "http://fake_api:8080/jwk/symmetric.json",
"roles": ["superadministrator"],
"disable_jwk_security": true
}
}
},
{
"endpoint": "/v1/auth/acl/permission/role/{id}",
"method": "PUT",
"input_headers": ["Authorization"],
"output_encoding": "no-op",
"backend": [
{
"url_pattern": "/v1/auth/acl/permission/role/{id}",
"host": [
"http://auth-go:8083"
],
"extra_config": {
"backend/http": {
"return_error_code": true
}
}
}
],
"extra_config": {
"auth/validator": {
"alg": "HS256",
"jwk_url": "http://fake_api:8080/jwk/symmetric.json",
"roles": ["superadministrator"],
"disable_jwk_security": true
}
}
},
{
"endpoint": "/v1/auth/acl/roles",
"method": "GET",
Expand Down
5 changes: 5 additions & 0 deletions services/auth/domain/entities/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ type AclUserDto struct {
Roles []string
Permissions []string
}

type AclPermissionDto struct {
RoleId string
Permissions []string
}
2 changes: 2 additions & 0 deletions services/auth/domain/repositories/permission_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ type PermissionRoleRepository interface {
CreateMany(ctx context.Context, payloads []*entities.PermissionRole) error
AllByRoleId(ctx context.Context, roleId string) ([]*entities.PermissionRole, error)
Delete(ctx context.Context, payload *entities.PermissionRole) error
DeleteByPermissionIds(ctx context.Context, ids []string) error
DeleteByRoleId(ctx context.Context, roleId string) error
}
2 changes: 2 additions & 0 deletions services/auth/domain/usecases/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
type AclUsecase interface {
GetAllRole(ctx context.Context) ([]*entities.Role, *exceptions.CustomError)
GetAllPermission(ctx context.Context) ([]*entities.Permission, *exceptions.CustomError)
GetAllPermissionByRole(ctx context.Context, roleId string) ([]*entities.Permission, *exceptions.CustomError)
GetAllUser(ctx context.Context, userId string) (*entities.AclMeta, *exceptions.CustomError)
UpdateUser(ctx context.Context, payload entities.AclUserDto) *exceptions.CustomError
UpdatePermissionByRole(ctx context.Context, payload entities.AclPermissionDto) *exceptions.CustomError
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package acl_handler

import (
"context"
"errors"
"net/http"

"github.com/febrihidayan/go-architecture-monorepo/pkg/exceptions"
"github.com/febrihidayan/go-architecture-monorepo/pkg/utils"
"github.com/febrihidayan/go-architecture-monorepo/services/auth/internal/delivery/http/response"
"github.com/gorilla/mux"
)

func (x *aclHttpHandler) GetAllPermissionByRole(w http.ResponseWriter, r *http.Request) {
var (
ctx = context.Background()
vars = mux.Vars(r)
id = vars["id"]
)

if id == "" {
utils.RespondWithError(w, http.StatusBadRequest, []error{errors.New("param id required")})
return
}

results, err := x.aclUsecase.GetAllPermissionByRole(ctx, id)
if err != nil {
utils.RespondWithError(w, exceptions.MapToHttpStatusCode(err.Status), err.Errors.Errors)
return
}

utils.RespondWithJSON(w, http.StatusOK, response.MapPermissionListResponses(results))
}
2 changes: 2 additions & 0 deletions services/auth/internal/delivery/http/delivery/acl/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ func AclHttpHandler(

r.HandleFunc("/v1/auth/acl/roles", handler.GetAllRole).Methods("GET")
r.HandleFunc("/v1/auth/acl/permissions", handler.GetAllPermission).Methods("GET")
r.HandleFunc("/v1/auth/acl/permission/role/{id}", handler.GetAllPermissionByRole).Methods("GET")
r.HandleFunc("/v1/auth/acl/permission/role/{id}", handler.UpdatePermissionByRole).Methods("PUT")
r.HandleFunc("/v1/auth/acl/access", handler.Access).Methods("GET")
r.HandleFunc("/v1/auth/acl/user/{id}", handler.GetAllUser).Methods("GET")
r.HandleFunc("/v1/auth/acl/user/{id}", handler.UpdateUser).Methods("PUT")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package acl_handler

import (
"context"
"encoding/json"
"errors"
"net/http"

"github.com/febrihidayan/go-architecture-monorepo/pkg/exceptions"
"github.com/febrihidayan/go-architecture-monorepo/pkg/utils"
"github.com/febrihidayan/go-architecture-monorepo/pkg/validator"
"github.com/febrihidayan/go-architecture-monorepo/services/auth/domain/entities"
"github.com/febrihidayan/go-architecture-monorepo/services/auth/internal/delivery/http/request"
"github.com/gorilla/mux"
)

func (x *aclHttpHandler) UpdatePermissionByRole(w http.ResponseWriter, r *http.Request) {
var (
ctx = context.Background()
vars = mux.Vars(r)
id = vars["id"]
payload request.AclUserUpdateRequest
)

if id == "" {
utils.RespondWithError(w, http.StatusBadRequest, []error{errors.New("param id required")})
return
}

decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&payload); err != nil {
utils.RespondWithError(w, http.StatusBadRequest, []error{err})
return
}

if err := validator.Make(payload); err != nil {
validator.ErrorJson(w, http.StatusUnprocessableEntity, err)
return
}

data := entities.AclPermissionDto{
RoleId: id,
Permissions: payload.Permissions,
}

if err := x.aclUsecase.UpdatePermissionByRole(ctx, data); err != nil {
utils.RespondWithError(w, exceptions.MapToHttpStatusCode(err.Status), err.Errors.Errors)
return
}

utils.RespondWithJSON(w, http.StatusOK, nil)
}
4 changes: 4 additions & 0 deletions services/auth/internal/delivery/http/request/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ type AclUserUpdateRequest struct {
Permissions []string `json:"permissions"`
Roles []string `json:"roles"`
}

type AclPermissionUpdateRequest struct {
Permissions []string `json:"permissions"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,19 @@ func (x *PermissionRoleRepository) Delete(ctx context.Context, payload *entities

return err
}

func (x *PermissionRoleRepository) DeleteByPermissionIds(ctx context.Context, ids []string) error {
_, err := x.db.Collection(models.PermissionRole{}.TableName()).DeleteMany(ctx, bson.M{
"permission_id": bson.D{{"$in", ids}},
})

return err
}

func (x *PermissionRoleRepository) DeleteByRoleId(ctx context.Context, roleId string) error {
_, err := x.db.Collection(models.PermissionRole{}.TableName()).DeleteMany(ctx, bson.M{
"role_id": roleId,
})

return err
}
38 changes: 38 additions & 0 deletions services/auth/internal/usecases/acl/get_all_permission_by_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package acl

import (
"context"
"log"

"github.com/febrihidayan/go-architecture-monorepo/pkg/exceptions"
"github.com/febrihidayan/go-architecture-monorepo/services/auth/domain/entities"
"github.com/hashicorp/go-multierror"
)

func (x *aclInteractor) GetAllPermissionByRole(ctx context.Context, roleId string) ([]*entities.Permission, *exceptions.CustomError) {
var (
multilerr *multierror.Error
permissions []*entities.Permission
)

permissionRole, err := x.permissionRoleRepo.AllByRoleId(ctx, roleId)
if err != nil {
log.Println("GetAllPermissionByRole::error#1:", err)
multilerr = multierror.Append(multilerr, err)
return nil, &exceptions.CustomError{
Status: exceptions.ERRREPOSITORY,
Errors: multilerr,
}
}

for _, item := range permissionRole {
permission, _ := x.permissionRepo.Find(ctx, item.PermissionId)
if permission != nil {
permissions = append(permissions, permission)
}
}

log.Println("GetAllPermissionByRole::success#1:", "successfully")

return permissions, nil
}
93 changes: 93 additions & 0 deletions services/auth/internal/usecases/acl/update_permission_by_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package acl

import (
"context"
"log"

"github.com/febrihidayan/go-architecture-monorepo/pkg/exceptions"
"github.com/febrihidayan/go-architecture-monorepo/services/auth/domain/entities"
"github.com/hashicorp/go-multierror"
"golang.org/x/exp/slices"
)

func (x *aclInteractor) UpdatePermissionByRole(ctx context.Context, payload entities.AclPermissionDto) *exceptions.CustomError {
var multilerr *multierror.Error

role, err := x.roleRepo.Find(ctx, payload.RoleId)
if err != nil {
log.Println("UpdatePermissionByRole::error#1:", err)
multilerr = multierror.Append(multilerr, err)
return &exceptions.CustomError{
Status: exceptions.ERRREPOSITORY,
Errors: multilerr,
}
}

allPermissions, err := x.permissionRoleRepo.AllByRoleId(ctx, role.ID.String())
if err != nil {
log.Println("UpdatePermissionByRole::error#2:", err)
multilerr = multierror.Append(multilerr, err)
return &exceptions.CustomError{
Status: exceptions.ERRREPOSITORY,
Errors: multilerr,
}
}

if len(payload.Permissions) > 0 {
var deletes []string

for _, item := range allPermissions {
if !slices.Contains(payload.Permissions, item.PermissionId) {
deletes = append(deletes, item.PermissionId)
} else {
payload.Permissions[slices.Index(payload.Permissions, item.PermissionId)] = payload.Permissions[len(payload.Permissions)-1]
payload.Permissions = payload.Permissions[:len(payload.Permissions)-1]
}
}

permissionRoles := make([]*entities.PermissionRole, 0)
for _, item := range payload.Permissions {
permissionRole := entities.NewPermissionRole(entities.PermissionRoleDto{
PermissionId: item,
RoleId: role.ID.String(),
})
permissionRoles = append(permissionRoles, permissionRole)
}

if len(permissionRoles) > 0 {
if err := x.permissionRoleRepo.CreateMany(ctx, permissionRoles); err != nil {
log.Println("UpdatePermissionByRole::error#3:", err)
multilerr = multierror.Append(multilerr, err)
return &exceptions.CustomError{
Status: exceptions.ERRREPOSITORY,
Errors: multilerr,
}
}
}

if len(deletes) > 0 {
if err := x.permissionRoleRepo.DeleteByPermissionIds(ctx, deletes); err != nil {
log.Println("UpdatePermissionByRole::error#4:", err)
multilerr = multierror.Append(multilerr, err)
return &exceptions.CustomError{
Status: exceptions.ERRREPOSITORY,
Errors: multilerr,
}
}
}

} else if len(allPermissions) > 0 {
if err := x.permissionRoleRepo.DeleteByRoleId(ctx, role.ID.String()); err != nil {
log.Println("UpdatePermissionByRole::error#5:", err)
multilerr = multierror.Append(multilerr, err)
return &exceptions.CustomError{
Status: exceptions.ERRREPOSITORY,
Errors: multilerr,
}
}
}

log.Println("UpdatePermissionByRole::success#1:", "successfully")

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,23 @@ func (x *PermissionRoleRepositoryMock) Delete(ctx context.Context, payload *enti

return
}

func (x *PermissionRoleRepositoryMock) DeleteByPermissionIds(ctx context.Context, ids []string) (err error) {
args := x.Called(ids)

if n, ok := args.Get(0).(error); ok {
err = n
}

return
}

func (x *PermissionRoleRepositoryMock) DeleteByRoleId(ctx context.Context, roleId string) (err error) {
args := x.Called(roleId)

if n, ok := args.Get(0).(error); ok {
err = n
}

return
}

0 comments on commit d61d745

Please sign in to comment.