Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: permission issues and sidebar item defaults #211

Open
wants to merge 2 commits into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 0 additions & 43 deletions modules/core/domain/entities/permission/rbac.go

This file was deleted.

12 changes: 10 additions & 2 deletions modules/core/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,24 @@ func (m *Module) Register(app application.Application) error {
userRepo := persistence.NewUserRepository(uploadRepo)
roleRepo := persistence.NewRoleRepository()

// Create services
userService := services.NewUserService(userRepo, app.EventPublisher())
tabService := services.NewTabService(persistence.NewTabRepository())

// Set up dependencies
userService.SetTabService(tabService)
userService.SetApplication(app)

app.RegisterServices(
services.NewUploadService(uploadRepo, fsStorage, app.EventPublisher()),
services.NewUserService(userRepo, app.EventPublisher()),
userService,
services.NewSessionService(persistence.NewSessionRepository(), app.EventPublisher()),
)
app.RegisterServices(
services.NewAuthService(app),
services.NewCurrencyService(persistence.NewCurrencyRepository(), app.EventPublisher()),
services.NewRoleService(roleRepo, app.EventPublisher()),
services.NewTabService(persistence.NewTabRepository()),
tabService,
services.NewGroupService(persistence.NewGroupRepository(userRepo, roleRepo), app.EventPublisher()),
)
app.RegisterControllers(
Expand Down
11 changes: 7 additions & 4 deletions modules/core/presentation/controllers/dtos/role_dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package dtos
import (
"context"
"fmt"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"

"github.com/iota-uz/iota-sdk/modules/core/domain/aggregates/role"
"github.com/iota-uz/iota-sdk/modules/core/domain/entities/permission"
"github.com/iota-uz/iota-sdk/pkg/composables"
"github.com/iota-uz/iota-sdk/pkg/constants"
"github.com/iota-uz/iota-sdk/pkg/rbac"

"github.com/go-playground/validator/v10"
"github.com/google/uuid"
"github.com/nicksnyder/go-i18n/v2/i18n"
)

Expand Down Expand Up @@ -42,7 +45,7 @@ func (r *CreateRoleDTO) Ok(ctx context.Context) (map[string]string, bool) {
return errorMessages, len(errorMessages) == 0
}

func (r *CreateRoleDTO) ToEntity(rbac permission.RBAC) (role.Role, error) {
func (r *CreateRoleDTO) ToEntity(rbac rbac.RBAC) (role.Role, error) {
perms := make([]*permission.Permission, 0, len(r.Permissions))
for permID := range r.Permissions {
permUUID, err := uuid.Parse(permID)
Expand Down Expand Up @@ -90,7 +93,7 @@ func (r *UpdateRoleDTO) Ok(ctx context.Context) (map[string]string, bool) {
return errorMessages, len(errorMessages) == 0
}

func (r *UpdateRoleDTO) ToEntity(roleEntity role.Role, rbac permission.RBAC) (role.Role, error) {
func (r *UpdateRoleDTO) ToEntity(roleEntity role.Role, rbac rbac.RBAC) (role.Role, error) {
perms := make([]*permission.Permission, 0, len(r.Permissions))
for permID := range r.Permissions {
permUUID, err := uuid.Parse(permID)
Expand Down
87 changes: 85 additions & 2 deletions modules/core/services/user_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ import (
"context"

"github.com/iota-uz/iota-sdk/modules/core/domain/aggregates/user"
"github.com/iota-uz/iota-sdk/modules/core/domain/entities/tab"
"github.com/iota-uz/iota-sdk/modules/core/permissions"
"github.com/iota-uz/iota-sdk/pkg/application"
"github.com/iota-uz/iota-sdk/pkg/composables"
"github.com/iota-uz/iota-sdk/pkg/constants"
"github.com/iota-uz/iota-sdk/pkg/eventbus"
"github.com/iota-uz/iota-sdk/pkg/types"
"github.com/nicksnyder/go-i18n/v2/i18n"
)

type UserService struct {
repo user.Repository
publisher eventbus.EventBus
repo user.Repository
publisher eventbus.EventBus
app application.Application
tabService *TabService
}

func NewUserService(repo user.Repository, publisher eventbus.EventBus) *UserService {
Expand All @@ -20,6 +28,58 @@ func NewUserService(repo user.Repository, publisher eventbus.EventBus) *UserServ
}
}

func (s *UserService) SetTabService(tabService *TabService) {
s.tabService = tabService
}

func (s *UserService) SetApplication(app application.Application) {
s.app = app
}

func (s *UserService) getAccessibleNavItems(items []types.NavigationItem, user user.User) []string {
var result []string

for _, item := range items {
if item.HasPermission(user) {
if item.Href != "" {
result = append(result, item.Href)
}

if len(item.Children) > 0 {
childItems := s.getAccessibleNavItems(item.Children, user)
result = append(result, childItems...)
}
}
}

return result
}

func (s *UserService) createUserTabs(ctx context.Context, user user.User) error {
if s.app == nil || s.tabService == nil {
return nil
}

items := s.app.NavItems(i18n.NewLocalizer(s.app.Bundle(), string(user.UILanguage())))
hrefs := s.getAccessibleNavItems(items, user)

tabs := make([]*tab.CreateDTO, 0, len(hrefs))
for i, href := range hrefs {
tabs = append(tabs, &tab.CreateDTO{
Href: href,
UserID: user.ID(),
Position: uint(i),
})
}

if len(tabs) > 0 {
ctxWithUser := context.WithValue(ctx, constants.UserKey, user)
_, err := s.tabService.CreateManyUserTabs(ctxWithUser, user.ID(), tabs)
return err
}
return nil
}

func (s *UserService) GetByEmail(ctx context.Context, email string) (user.User, error) {
return s.repo.GetByEmail(ctx, email)
}
Expand All @@ -33,14 +93,23 @@ func (s *UserService) GetAll(ctx context.Context) ([]user.User, error) {
}

func (s *UserService) GetByID(ctx context.Context, id uint) (user.User, error) {
if err := composables.CanUser(ctx, permissions.UserRead); err != nil {
return nil, err
}
return s.repo.GetByID(ctx, id)
}

func (s *UserService) GetPaginated(ctx context.Context, params *user.FindParams) ([]user.User, error) {
if err := composables.CanUser(ctx, permissions.UserRead); err != nil {
return nil, err
}
return s.repo.GetPaginated(ctx, params)
}

func (s *UserService) GetPaginatedWithTotal(ctx context.Context, params *user.FindParams) ([]user.User, int64, error) {
if err := composables.CanUser(ctx, permissions.UserRead); err != nil {
return nil, 0, err
}
us, err := s.repo.GetPaginated(ctx, params)
if err != nil {
return nil, 0, err
Expand All @@ -53,6 +122,9 @@ func (s *UserService) GetPaginatedWithTotal(ctx context.Context, params *user.Fi
}

func (s *UserService) Create(ctx context.Context, data user.User) error {
if err := composables.CanUser(ctx, permissions.UserCreate); err != nil {
return err
}
tx, err := composables.BeginTx(ctx)
if err != nil {
return err
Expand All @@ -70,6 +142,11 @@ func (s *UserService) Create(ctx context.Context, data user.User) error {
if err != nil {
return err
}

if err := s.createUserTabs(ctx, created); err != nil {
return err
}

if err := tx.Commit(ctx); err != nil {
return err
}
Expand All @@ -87,6 +164,9 @@ func (s *UserService) UpdateLastLogin(ctx context.Context, id uint) error {
}

func (s *UserService) Update(ctx context.Context, data user.User) error {
if err := composables.CanUser(ctx, permissions.UserUpdate); err != nil {
return err
}
tx, err := composables.BeginTx(ctx)
if err != nil {
return err
Expand Down Expand Up @@ -114,6 +194,9 @@ func (s *UserService) Update(ctx context.Context, data user.User) error {
}

func (s *UserService) Delete(ctx context.Context, id uint) (user.User, error) {
if err := composables.CanUser(ctx, permissions.UserDelete); err != nil {
return nil, err
}
tx, err := composables.BeginTx(ctx)
if err != nil {
return nil, err
Expand Down
8 changes: 4 additions & 4 deletions pkg/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"

"github.com/iota-uz/iota-sdk/modules/core/domain/entities/permission"
"github.com/iota-uz/iota-sdk/pkg/configuration"
"github.com/iota-uz/iota-sdk/pkg/eventbus"
"github.com/iota-uz/iota-sdk/pkg/rbac"
"github.com/iota-uz/iota-sdk/pkg/spotlight"
"github.com/iota-uz/iota-sdk/pkg/types"
)
Expand Down Expand Up @@ -93,7 +93,7 @@ func New(pool *pgxpool.Pool, eventPublisher eventbus.EventBus) Application {
return &application{
pool: pool,
eventPublisher: eventPublisher,
rbac: permission.NewRbac(),
rbac: rbac.NewRbac(),
controllers: make(map[string]Controller),
services: make(map[reflect.Type]interface{}),
spotlight: spotlight.New(),
Expand All @@ -106,7 +106,7 @@ func New(pool *pgxpool.Pool, eventPublisher eventbus.EventBus) Application {
type application struct {
pool *pgxpool.Pool
eventPublisher eventbus.EventBus
rbac permission.RBAC
rbac rbac.RBAC
services map[reflect.Type]interface{}
controllers map[string]Controller
middleware []mux.MiddlewareFunc
Expand All @@ -131,7 +131,7 @@ func (app *application) RegisterNavItems(items ...types.NavigationItem) {
app.navItems = append(app.navItems, items...)
}

func (app *application) RBAC() permission.RBAC {
func (app *application) RBAC() rbac.RBAC {
return app.rbac
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/application/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import (
"embed"
"reflect"

"github.com/iota-uz/iota-sdk/modules/core/domain/entities/permission"
"github.com/iota-uz/iota-sdk/pkg/eventbus"
"github.com/iota-uz/iota-sdk/pkg/rbac"
"github.com/iota-uz/iota-sdk/pkg/spotlight"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/iota-uz/iota-sdk/pkg/types"

"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/executor"
"github.com/benbjohnson/hashfs"
"github.com/gorilla/mux"
"github.com/iota-uz/iota-sdk/pkg/eventbus"
"github.com/iota-uz/iota-sdk/pkg/types"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/nicksnyder/go-i18n/v2/i18n"
)

Expand All @@ -32,7 +32,7 @@ type Application interface {
Middleware() []mux.MiddlewareFunc
Assets() []*embed.FS
HashFsAssets() []*hashfs.FS
RBAC() permission.RBAC
RBAC() rbac.RBAC
Spotlight() spotlight.Spotlight
Migrations() MigrationManager
NavItems(localizer *i18n.Localizer) []types.NavigationItem
Expand Down
17 changes: 14 additions & 3 deletions pkg/composables/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/iota-uz/iota-sdk/modules/core/domain/entities/permission"
"github.com/iota-uz/iota-sdk/modules/core/domain/entities/session"
"github.com/iota-uz/iota-sdk/pkg/constants"
"github.com/iota-uz/iota-sdk/pkg/rbac"
)

var (
Expand Down Expand Up @@ -41,11 +42,21 @@ func MustUseUser(ctx context.Context) user.User {
func CanUser(ctx context.Context, permission *permission.Permission) error {
u, err := UseUser(ctx)
if err != nil {
return err
return nil
}
if !u.Can(permission) {
return nil
// return service.ErrForbidden
return ErrForbidden
}
return nil
}

func CanUserAll(ctx context.Context, perms ...rbac.Permission) error {
u, err := UseUser(ctx)
if err != nil || len(perms) == 0 {
return nil // don't check if the user isn't in the context
}
if !rbac.And(perms...).Can(u) {
return ErrForbidden
}
return nil
}
Expand Down
Loading