Skip to content

Commit 7fb5dd7

Browse files
authored
NOISSUE - Refactor listing for rules and reports (#433)
* add access control to rules engine Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * update authorization method Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * revert code Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * initial implementation Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * remove domain from method Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * fix failing linter Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * fix userid parameter Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * update checksuperadmin method Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * revert changes Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * address comments Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> --------- Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
1 parent 2ef8437 commit 7fb5dd7

File tree

16 files changed

+826
-120
lines changed

16 files changed

+826
-120
lines changed

re/handlers.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func (re *re) Handle(msg *messaging.Message) error {
4343
Scheduled: &scheduledFalse,
4444
}
4545
ctx := context.Background()
46-
page, err := re.repo.ListRules(ctx, pm)
46+
page, err := re.repo.ListAllRules(ctx, pm)
4747
if err != nil {
4848
return err
4949
}
@@ -130,7 +130,7 @@ func (re *re) StartScheduler(ctx context.Context) error {
130130
ScheduledBefore: &due,
131131
}
132132

133-
page, err := re.repo.ListRules(ctx, pm)
133+
page, err := re.repo.ListAllRules(ctx, pm)
134134
if err != nil {
135135
re.runInfo <- pkglog.RunInfo{
136136
Level: slog.LevelError,

re/middleware/authorization.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/absmach/supermq/pkg/authn"
1212
smqauthz "github.com/absmach/supermq/pkg/authz"
1313
"github.com/absmach/supermq/pkg/errors"
14+
svcerr "github.com/absmach/supermq/pkg/errors/service"
1415
"github.com/absmach/supermq/pkg/messaging"
1516
"github.com/absmach/supermq/pkg/permissions"
1617
"github.com/absmach/supermq/pkg/policies"
@@ -90,8 +91,12 @@ func (am *authorizationMiddleware) UpdateRuleSchedule(ctx context.Context, sessi
9091
}
9192

9293
func (am *authorizationMiddleware) ListRules(ctx context.Context, session authn.Session, pm re.PageMeta) (re.Page, error) {
93-
if err := am.authorize(ctx, operations.OpListRules, session, policies.DomainType, session.DomainID); err != nil {
94-
return re.Page{}, errors.Wrap(errDomainViewRules, err)
94+
switch err := am.checkSuperAdmin(ctx, session); {
95+
case err == nil:
96+
session.SuperAdmin = true
97+
case errors.Contains(err, svcerr.ErrSuperAdminAction):
98+
default:
99+
return re.Page{}, err
95100
}
96101

97102
return am.svc.ListRules(ctx, session, pm)
@@ -168,3 +173,19 @@ func (am *authorizationMiddleware) authorize(ctx context.Context, op permissions
168173

169174
return nil
170175
}
176+
177+
func (am *authorizationMiddleware) checkSuperAdmin(ctx context.Context, session authn.Session) error {
178+
if session.Role != authn.SuperAdminRole {
179+
return svcerr.ErrSuperAdminAction
180+
}
181+
if err := am.authz.Authorize(ctx, smqauthz.PolicyReq{
182+
SubjectType: policies.UserType,
183+
Subject: session.UserID,
184+
Permission: policies.AdminPermission,
185+
ObjectType: policies.PlatformType,
186+
Object: policies.SuperMQObject,
187+
}, nil); err != nil {
188+
return err
189+
}
190+
return nil
191+
}

re/mocks/repository.go

Lines changed: 92 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

re/postgres/repository.go

Lines changed: 86 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -357,33 +357,10 @@ func (repo *PostgresRepository) RemoveRule(ctx context.Context, id string) error
357357
return nil
358358
}
359359

360-
func (repo *PostgresRepository) ListRules(ctx context.Context, pm re.PageMeta) (re.Page, error) {
361-
pgData := ""
362-
if pm.Limit != 0 {
363-
pgData = "LIMIT :limit"
364-
}
365-
if pm.Offset != 0 {
366-
pgData += " OFFSET :offset"
367-
}
360+
func (repo *PostgresRepository) ListAllRules(ctx context.Context, pm re.PageMeta) (re.Page, error) {
368361
pq := pageRulesQuery(pm)
369-
370-
dir := api.DescDir
371-
if pm.Dir == api.AscDir {
372-
dir = api.AscDir
373-
}
374-
375-
orderClause := ""
376-
377-
switch pm.Order {
378-
case api.NameKey:
379-
orderClause = fmt.Sprintf("ORDER BY name %s, id %s", dir, dir)
380-
case api.CreatedAtOrder:
381-
orderClause = fmt.Sprintf("ORDER BY created_at %s, id %s", dir, dir)
382-
case api.UpdatedAtOrder:
383-
orderClause = fmt.Sprintf("ORDER BY COALESCE(updated_at, created_at) %s, id %s", dir, dir)
384-
default:
385-
orderClause = fmt.Sprintf("ORDER BY COALESCE(updated_at, created_at) %s, id %s", dir, dir)
386-
}
362+
orderClause := rulesOrderClause(pm)
363+
pgData := rulesPageData(pm)
387364

388365
q := fmt.Sprintf(`
389366
SELECT id, name, domain_id, tags, input_channel, input_topic, logic_type, logic_value, outputs,
@@ -425,6 +402,62 @@ func (repo *PostgresRepository) ListRules(ctx context.Context, pm re.PageMeta) (
425402
return ret, nil
426403
}
427404

405+
func (repo *PostgresRepository) ListUserRules(ctx context.Context, userID string, pm re.PageMeta) (re.Page, error) {
406+
pm.UserID = userID
407+
pq := pageRulesQuery(pm)
408+
orderClause := rulesOrderClause(pm)
409+
pgData := rulesPageData(pm)
410+
411+
userJoin := `
412+
INNER JOIN rules_roles rr ON rr.entity_id = r.id
413+
INNER JOIN rules_role_members rrm ON rrm.role_id = rr.id AND rrm.member_id = :user_id
414+
`
415+
416+
innerQ := fmt.Sprintf(`
417+
SELECT DISTINCT r.id, r.name, r.domain_id, r.tags, r.input_channel, r.input_topic, r.logic_type, r.logic_value, r.outputs,
418+
r.start_datetime, r.time, r.recurring, r.recurring_period, r.created_at, r.created_by, r.updated_at, r.updated_by, r.status
419+
FROM rules r
420+
%s
421+
%s
422+
`, userJoin, pq)
423+
424+
q := fmt.Sprintf(`
425+
SELECT * FROM (%s) AS sub %s %s;
426+
`, innerQ, orderClause, pgData)
427+
428+
rows, err := repo.DB.NamedQueryContext(ctx, q, pm)
429+
if err != nil {
430+
return re.Page{}, err
431+
}
432+
defer rows.Close()
433+
434+
var rules []re.Rule
435+
for rows.Next() {
436+
var r dbRule
437+
if err := rows.StructScan(&r); err != nil {
438+
return re.Page{}, errors.Wrap(repoerr.ErrViewEntity, err)
439+
}
440+
ret, err := dbToRule(r)
441+
if err != nil {
442+
return re.Page{}, err
443+
}
444+
rules = append(rules, ret)
445+
}
446+
447+
cq := fmt.Sprintf(`SELECT COUNT(*) FROM (%s) AS count_sub;`, innerQ)
448+
total, err := postgres.Total(ctx, repo.DB, cq, pm)
449+
if err != nil {
450+
return re.Page{}, errors.Wrap(repoerr.ErrViewEntity, err)
451+
}
452+
453+
return re.Page{
454+
Total: total,
455+
Offset: pm.Offset,
456+
Limit: pm.Limit,
457+
Rules: rules,
458+
}, nil
459+
}
460+
428461
func (repo *PostgresRepository) UpdateRuleDue(ctx context.Context, id string, due time.Time) (re.Rule, error) {
429462
q := `
430463
UPDATE rules
@@ -460,6 +493,33 @@ func (repo *PostgresRepository) UpdateRuleDue(ctx context.Context, id string, du
460493
return rule, nil
461494
}
462495

496+
func rulesOrderClause(pm re.PageMeta) string {
497+
dir := api.DescDir
498+
if pm.Dir == api.AscDir {
499+
dir = api.AscDir
500+
}
501+
502+
switch pm.Order {
503+
case api.NameKey:
504+
return fmt.Sprintf("ORDER BY name %s, id %s", dir, dir)
505+
case api.CreatedAtOrder:
506+
return fmt.Sprintf("ORDER BY created_at %s, id %s", dir, dir)
507+
default:
508+
return fmt.Sprintf("ORDER BY COALESCE(updated_at, created_at) %s, id %s", dir, dir)
509+
}
510+
}
511+
512+
func rulesPageData(pm re.PageMeta) string {
513+
pgData := ""
514+
if pm.Limit != 0 {
515+
pgData = "LIMIT :limit"
516+
}
517+
if pm.Offset != 0 {
518+
pgData += " OFFSET :offset"
519+
}
520+
return pgData
521+
}
522+
463523
func pageRulesQuery(pm re.PageMeta) string {
464524
var query []string
465525
if pm.InputChannel != "" {

0 commit comments

Comments
 (0)