mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 07:10:19 +00:00
362a4fc76d
* update go mod file Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * fix rules endpoint tests Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * fix yaml file Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * fix build Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * address comments Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * remove roles from alarms Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * change approach for schema combaine Signed-off-by: Arvindh <arvindh91@gmail.com> * change approach for schema combaine Signed-off-by: Arvindh <arvindh91@gmail.com> * fix permissions for rules Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * fix authorization file Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * fix linter Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> * fix linter Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> --------- Signed-off-by: nyagamunene <stevenyaga2014@gmail.com> Signed-off-by: Arvindh <arvindh91@gmail.com> Co-authored-by: Arvindh <arvindh91@gmail.com>
223 lines
6.2 KiB
Go
223 lines
6.2 KiB
Go
// Copyright (c) Abstract Machines
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package re
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
grpcReadersV1 "github.com/absmach/magistrala/api/grpc/readers/v1"
|
|
"github.com/absmach/magistrala/pkg/emailer"
|
|
pkglog "github.com/absmach/magistrala/pkg/logger"
|
|
"github.com/absmach/magistrala/pkg/ticker"
|
|
"github.com/absmach/magistrala/re/operations"
|
|
"github.com/absmach/supermq"
|
|
"github.com/absmach/supermq/pkg/authn"
|
|
"github.com/absmach/supermq/pkg/errors"
|
|
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
|
"github.com/absmach/supermq/pkg/messaging"
|
|
"github.com/absmach/supermq/pkg/policies"
|
|
"github.com/absmach/supermq/pkg/roles"
|
|
)
|
|
|
|
var ErrGoroutinesNotAllowed = errors.New("goroutines are not allowed in Go scripts")
|
|
|
|
type re struct {
|
|
repo Repository
|
|
runInfo chan pkglog.RunInfo
|
|
idp supermq.IDProvider
|
|
rePubSub messaging.PubSub
|
|
writersPub messaging.Publisher
|
|
alarmsPub messaging.Publisher
|
|
ticker ticker.Ticker
|
|
email emailer.Emailer
|
|
readers grpcReadersV1.ReadersServiceClient
|
|
roles.ProvisionManageService
|
|
}
|
|
|
|
func NewService(repo Repository, runInfo chan pkglog.RunInfo, policy policies.Service, idp supermq.IDProvider, rePubSub messaging.PubSub, writersPub, alarmsPub messaging.Publisher, tck ticker.Ticker, emailer emailer.Emailer, readers grpcReadersV1.ReadersServiceClient, availableActions []roles.Action, builtInRoles map[roles.BuiltInRoleName][]roles.Action) (Service, error) {
|
|
rpms, err := roles.NewProvisionManageService(operations.EntityType, repo, policy, idp, availableActions, builtInRoles)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &re{
|
|
repo: repo,
|
|
idp: idp,
|
|
runInfo: runInfo,
|
|
rePubSub: rePubSub,
|
|
writersPub: writersPub,
|
|
alarmsPub: alarmsPub,
|
|
ticker: tck,
|
|
email: emailer,
|
|
readers: readers,
|
|
ProvisionManageService: rpms,
|
|
}, nil
|
|
}
|
|
|
|
func (re *re) AddRule(ctx context.Context, session authn.Session, r Rule) (retRule Rule, retErr error) {
|
|
if r.Logic.Type == GoType && goKeywordRegex.MatchString(r.Logic.Value) {
|
|
return Rule{}, errors.Wrap(svcerr.ErrMalformedEntity, ErrGoroutinesNotAllowed)
|
|
}
|
|
|
|
id, err := re.idp.ID()
|
|
if err != nil {
|
|
return Rule{}, err
|
|
}
|
|
now := time.Now().UTC()
|
|
r.CreatedAt = now
|
|
r.ID = id
|
|
r.CreatedBy = session.UserID
|
|
r.DomainID = session.DomainID
|
|
r.Status = EnabledStatus
|
|
|
|
if !r.Schedule.StartDateTime.IsZero() {
|
|
r.Schedule.StartDateTime = now
|
|
}
|
|
r.Schedule.Time = r.Schedule.StartDateTime
|
|
|
|
rule, err := re.repo.AddRule(ctx, r)
|
|
if err != nil {
|
|
return Rule{}, errors.Wrap(svcerr.ErrCreateEntity, err)
|
|
}
|
|
|
|
defer func() {
|
|
if retErr != nil {
|
|
if errRollBack := re.repo.RemoveRule(ctx, rule.ID); errRollBack != nil {
|
|
retErr = errors.Wrap(retErr, errors.Wrap(svcerr.ErrRollbackRepo, errRollBack))
|
|
}
|
|
}
|
|
}()
|
|
|
|
newBuiltInRoleMembers := map[roles.BuiltInRoleName][]roles.Member{
|
|
BuiltInRoleAdmin: {roles.Member(session.UserID)},
|
|
}
|
|
|
|
optionalPolicies := []policies.Policy{
|
|
{
|
|
SubjectType: policies.DomainType,
|
|
Subject: session.DomainID,
|
|
Relation: policies.DomainRelation,
|
|
ObjectType: operations.EntityType,
|
|
Object: rule.ID,
|
|
},
|
|
}
|
|
|
|
_, err = re.AddNewEntitiesRoles(ctx, session.DomainID, session.UserID, []string{rule.ID}, optionalPolicies, newBuiltInRoleMembers)
|
|
if err != nil {
|
|
return Rule{}, errors.Wrap(svcerr.ErrAddPolicies, err)
|
|
}
|
|
|
|
return rule, nil
|
|
}
|
|
|
|
func (re *re) ViewRule(ctx context.Context, session authn.Session, id string, withRoles bool) (Rule, error) {
|
|
var rule Rule
|
|
var err error
|
|
switch withRoles {
|
|
case true:
|
|
rule, err = re.repo.RetrieveByIDWithRoles(ctx, id, session.UserID)
|
|
default:
|
|
rule, err = re.repo.ViewRule(ctx, id)
|
|
}
|
|
if err != nil {
|
|
return Rule{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
|
}
|
|
|
|
return rule, nil
|
|
}
|
|
|
|
func (re *re) UpdateRule(ctx context.Context, session authn.Session, r Rule) (Rule, error) {
|
|
if r.Logic.Type == GoType && goKeywordRegex.MatchString(r.Logic.Value) {
|
|
return Rule{}, errors.Wrap(svcerr.ErrMalformedEntity, ErrGoroutinesNotAllowed)
|
|
}
|
|
|
|
r.UpdatedAt = time.Now().UTC()
|
|
r.UpdatedBy = session.UserID
|
|
rule, err := re.repo.UpdateRule(ctx, r)
|
|
if err != nil {
|
|
return Rule{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
|
}
|
|
|
|
return rule, nil
|
|
}
|
|
|
|
func (re *re) UpdateRuleTags(ctx context.Context, session authn.Session, r Rule) (Rule, error) {
|
|
r.UpdatedAt = time.Now().UTC()
|
|
r.UpdatedBy = session.UserID
|
|
rule, err := re.repo.UpdateRuleTags(ctx, r)
|
|
if err != nil {
|
|
return Rule{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
|
}
|
|
|
|
return rule, nil
|
|
}
|
|
|
|
func (re *re) UpdateRuleSchedule(ctx context.Context, session authn.Session, r Rule) (Rule, error) {
|
|
r.UpdatedAt = time.Now().UTC()
|
|
r.UpdatedBy = session.UserID
|
|
rule, err := re.repo.UpdateRuleSchedule(ctx, r)
|
|
if err != nil {
|
|
return Rule{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
|
}
|
|
|
|
return rule, nil
|
|
}
|
|
|
|
func (re *re) ListRules(ctx context.Context, session authn.Session, pm PageMeta) (Page, error) {
|
|
pm.Domain = session.DomainID
|
|
page, err := re.repo.ListRules(ctx, pm)
|
|
if err != nil {
|
|
return Page{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
|
}
|
|
return page, nil
|
|
}
|
|
|
|
func (re *re) RemoveRule(ctx context.Context, session authn.Session, id string) error {
|
|
if err := re.repo.RemoveRule(ctx, id); err != nil {
|
|
return errors.Wrap(svcerr.ErrRemoveEntity, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (re *re) EnableRule(ctx context.Context, session authn.Session, id string) (Rule, error) {
|
|
status, err := ToStatus(Enabled)
|
|
if err != nil {
|
|
return Rule{}, err
|
|
}
|
|
r := Rule{
|
|
ID: id,
|
|
UpdatedAt: time.Now().UTC(),
|
|
UpdatedBy: session.UserID,
|
|
Status: status,
|
|
}
|
|
rule, err := re.repo.UpdateRuleStatus(ctx, r)
|
|
if err != nil {
|
|
return Rule{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
|
}
|
|
return rule, nil
|
|
}
|
|
|
|
func (re *re) DisableRule(ctx context.Context, session authn.Session, id string) (Rule, error) {
|
|
status, err := ToStatus(Disabled)
|
|
if err != nil {
|
|
return Rule{}, err
|
|
}
|
|
r := Rule{
|
|
ID: id,
|
|
UpdatedAt: time.Now().UTC(),
|
|
UpdatedBy: session.UserID,
|
|
Status: status,
|
|
}
|
|
rule, err := re.repo.UpdateRuleStatus(ctx, r)
|
|
if err != nil {
|
|
return Rule{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
|
}
|
|
return rule, nil
|
|
}
|
|
|
|
func (re *re) Cancel() error {
|
|
return nil
|
|
}
|