mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 04:00:27 +00:00
MG-370 - Add fine grained access control to rules engine (#402)
* 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>
This commit is contained in:
@@ -51,7 +51,7 @@ jobs:
|
||||
- name: Run linters
|
||||
uses: golangci/golangci-lint-action@v9
|
||||
with:
|
||||
version: v2.4.0
|
||||
version: latest
|
||||
args: --config ./tools/config/.golangci.yaml
|
||||
|
||||
run-tests:
|
||||
|
||||
+124
-15
@@ -20,33 +20,47 @@ import (
|
||||
"github.com/absmach/magistrala/internal/email"
|
||||
"github.com/absmach/magistrala/pkg/emailer"
|
||||
pkglog "github.com/absmach/magistrala/pkg/logger"
|
||||
"github.com/absmach/magistrala/pkg/prometheus"
|
||||
"github.com/absmach/magistrala/pkg/ticker"
|
||||
"github.com/absmach/magistrala/re"
|
||||
httpapi "github.com/absmach/magistrala/re/api"
|
||||
"github.com/absmach/magistrala/re/events"
|
||||
"github.com/absmach/magistrala/re/middleware"
|
||||
"github.com/absmach/magistrala/re/operations"
|
||||
repg "github.com/absmach/magistrala/re/postgres"
|
||||
grpcClient "github.com/absmach/magistrala/readers/api/grpc"
|
||||
"github.com/absmach/supermq"
|
||||
dpostgres "github.com/absmach/supermq/domains/postgres"
|
||||
smqlog "github.com/absmach/supermq/logger"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
authnsvc "github.com/absmach/supermq/pkg/authn/authsvc"
|
||||
mgauthz "github.com/absmach/supermq/pkg/authz"
|
||||
authzsvc "github.com/absmach/supermq/pkg/authz/authsvc"
|
||||
"github.com/absmach/supermq/pkg/callout"
|
||||
dconsumer "github.com/absmach/supermq/pkg/domains/events/consumer"
|
||||
domainsAuthz "github.com/absmach/supermq/pkg/domains/grpcclient"
|
||||
"github.com/absmach/supermq/pkg/grpcclient"
|
||||
jaegerclient "github.com/absmach/supermq/pkg/jaeger"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
smqbrokers "github.com/absmach/supermq/pkg/messaging/brokers"
|
||||
brokerstracing "github.com/absmach/supermq/pkg/messaging/brokers/tracing"
|
||||
"github.com/absmach/supermq/pkg/permissions"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
"github.com/absmach/supermq/pkg/policies/spicedb"
|
||||
pgclient "github.com/absmach/supermq/pkg/postgres"
|
||||
"github.com/absmach/supermq/pkg/roles"
|
||||
"github.com/absmach/supermq/pkg/server"
|
||||
httpserver "github.com/absmach/supermq/pkg/server/http"
|
||||
spicedbdecoder "github.com/absmach/supermq/pkg/spicedb"
|
||||
"github.com/absmach/supermq/pkg/uuid"
|
||||
"github.com/authzed/authzed-go/v1"
|
||||
"github.com/authzed/grpcutil"
|
||||
"github.com/caarlos0/env/v11"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -67,15 +81,21 @@ const (
|
||||
const channBuffer = 256
|
||||
|
||||
type config struct {
|
||||
LogLevel string `env:"MG_RE_LOG_LEVEL" envDefault:"info"`
|
||||
InstanceID string `env:"MG_RE_INSTANCE_ID" envDefault:""`
|
||||
JaegerURL url.URL `env:"SMQ_JAEGER_URL" envDefault:"http://localhost:4318/v1/traces"`
|
||||
SendTelemetry bool `env:"SMQ_SEND_TELEMETRY" envDefault:"true"`
|
||||
ESURL string `env:"SMQ_ES_URL" envDefault:"nats://localhost:4222"`
|
||||
CacheURL string `env:"MG_RE_CACHE_URL" envDefault:"redis://localhost:6379/0"`
|
||||
CacheKeyDuration time.Duration `env:"MG_RE_CACHE_KEY_DURATION" envDefault:"10m"`
|
||||
TraceRatio float64 `env:"SMQ_JAEGER_TRACE_RATIO" envDefault:"1.0"`
|
||||
BrokerURL string `env:"SMQ_MESSAGE_BROKER_URL" envDefault:"nats://localhost:4222"`
|
||||
LogLevel string `env:"MG_RE_LOG_LEVEL" envDefault:"info"`
|
||||
InstanceID string `env:"MG_RE_INSTANCE_ID" envDefault:""`
|
||||
JaegerURL url.URL `env:"SMQ_JAEGER_URL" envDefault:"http://localhost:4318/v1/traces"`
|
||||
SendTelemetry bool `env:"SMQ_SEND_TELEMETRY" envDefault:"true"`
|
||||
ESURL string `env:"SMQ_ES_URL" envDefault:"nats://localhost:4222"`
|
||||
ESConsumerName string `env:"MG_RE_EVENT_CONSUMER" envDefault:"rules_engine"`
|
||||
CacheURL string `env:"MG_RE_CACHE_URL" envDefault:"redis://localhost:6379/0"`
|
||||
CacheKeyDuration time.Duration `env:"MG_RE_CACHE_KEY_DURATION" envDefault:"10m"`
|
||||
TraceRatio float64 `env:"SMQ_JAEGER_TRACE_RATIO" envDefault:"1.0"`
|
||||
BrokerURL string `env:"SMQ_MESSAGE_BROKER_URL" envDefault:"nats://localhost:4222"`
|
||||
SpicedbHost string `env:"SMQ_SPICEDB_HOST" envDefault:"localhost"`
|
||||
SpicedbPort string `env:"SMQ_SPICEDB_PORT" envDefault:"50051"`
|
||||
SpicedbPreSharedKey string `env:"SMQ_SPICEDB_PRE_SHARED_KEY" envDefault:"12345678"`
|
||||
SpicedbSchemaFile string `env:"SMQ_SPICEDB_SCHEMA_FILE" envDefault:"schema.zed"`
|
||||
PermissionsFile string `env:"SMQ_PERMISSIONS_FILE" envDefault:"permission.yaml"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -126,7 +146,14 @@ func main() {
|
||||
|
||||
return
|
||||
}
|
||||
db, err := pgclient.Setup(dbConfig, *repg.Migration())
|
||||
migration, err := repg.Migration()
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
exitCode = 1
|
||||
|
||||
return
|
||||
}
|
||||
db, err := pgclient.Setup(dbConfig, *migration)
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
exitCode = 1
|
||||
@@ -238,6 +265,16 @@ func main() {
|
||||
logger.Info("AuthZ successfully connected to auth gRPC server " + authnClient.Secure())
|
||||
|
||||
database := pgclient.NewDatabase(db, dbConfig, tracer)
|
||||
|
||||
ddatabase := pgclient.NewDatabase(db, dbConfig, tracer)
|
||||
drepo := dpostgres.NewRepository(ddatabase)
|
||||
|
||||
if err := dconsumer.DomainsEventsSubscribe(ctx, drepo, cfg.ESURL, cfg.ESConsumerName, logger); err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to create domains event store : %s", err))
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
regrpcCfg := grpcclient.Config{}
|
||||
if err := env.ParseWithOptions(®rpcCfg, env.Options{Prefix: envPrefixGrpc}); err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to load clients gRPC client configuration : %s", err))
|
||||
@@ -255,7 +292,7 @@ func main() {
|
||||
readersClient := grpcClient.NewReadersClient(client.Connection(), regrpcCfg.Timeout)
|
||||
logger.Info("Readers gRPC client successfully connected to readers gRPC server " + client.Secure())
|
||||
|
||||
svc, err := newService(ctx, database, runInfo, msgSub, writersPub, alarmsPub, authz, ec, logger, readersClient, callout, cfg)
|
||||
svc, err := newService(ctx, cfg, database, runInfo, msgSub, writersPub, alarmsPub, authz, ec, logger, readersClient, callout, tracer)
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to create services: %s", err))
|
||||
exitCode = 1
|
||||
@@ -307,7 +344,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func newService(ctx context.Context, db pgclient.Database, runInfo chan pkglog.RunInfo, rePubSub messaging.PubSub, writersPub, alarmsPub messaging.Publisher, authz mgauthz.Authorization, ec email.Config, logger *slog.Logger, readersClient grpcReadersV1.ReadersServiceClient, callout callout.Callout, cfg config) (re.Service, error) {
|
||||
func newService(ctx context.Context, cfg config, db pgclient.Database, runInfo chan pkglog.RunInfo, rePubSub messaging.PubSub, writersPub, alarmsPub messaging.Publisher, authz mgauthz.Authorization, ec email.Config, logger *slog.Logger, readersClient grpcReadersV1.ReadersServiceClient, callout callout.Callout, tracer trace.Tracer) (re.Service, error) {
|
||||
repo := repg.NewRepository(db)
|
||||
idp := uuid.New()
|
||||
|
||||
@@ -316,21 +353,93 @@ func newService(ctx context.Context, db pgclient.Database, runInfo chan pkglog.R
|
||||
logger.Error(fmt.Sprintf("failed to configure e-mailing util: %s", err.Error()))
|
||||
}
|
||||
|
||||
csvc := re.NewService(repo, runInfo, idp, rePubSub, writersPub, alarmsPub, ticker.NewTicker(time.Second*30), emailerClient, readersClient)
|
||||
policyService, err := newSpiceDBPolicyServiceEvaluator(cfg, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logger.Info("Policy service successfully connected to SpiceDB gRPC server")
|
||||
|
||||
availableActions, builtInRoles, err := availableActionsAndBuiltInRoles(cfg.SpicedbSchemaFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get available actions and built-in roles: %w", err)
|
||||
}
|
||||
|
||||
csvc, err := re.NewService(repo, runInfo, policyService, idp, rePubSub, writersPub, alarmsPub, ticker.NewTicker(time.Second*30), emailerClient, readersClient, availableActions, builtInRoles)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create RE service: %w", err)
|
||||
}
|
||||
|
||||
csvc, err = events.NewEventStoreMiddleware(ctx, csvc, cfg.ESURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to init re event store middleware: %w", err)
|
||||
}
|
||||
|
||||
csvc, err = middleware.AuthorizationMiddleware(csvc, authz)
|
||||
permConfig, err := permissions.ParsePermissionsFile(cfg.PermissionsFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse permissions file: %w", err)
|
||||
}
|
||||
|
||||
ruleOps, ruleRoleOps, err := permConfig.GetEntityPermissions(operations.EntityType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get rule permissions: %w", err)
|
||||
}
|
||||
|
||||
entitiesOps, err := permissions.NewEntitiesOperations(
|
||||
permissions.EntitiesPermission{
|
||||
operations.EntityType: ruleOps,
|
||||
},
|
||||
permissions.EntitiesOperationDetails[permissions.Operation]{
|
||||
operations.EntityType: operations.OperationDetails(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create entities operations: %w", err)
|
||||
}
|
||||
|
||||
roleOps, err := permissions.NewOperations(roles.Operations(), ruleRoleOps)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create role operations: %w", err)
|
||||
}
|
||||
|
||||
csvc, err = middleware.AuthorizationMiddleware(csvc, authz, entitiesOps, roleOps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
csvc, err = middleware.NewCallout(csvc, callout)
|
||||
csvc, err = middleware.NewCallout(csvc, callout, entitiesOps, roleOps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
csvc = middleware.LoggingMiddleware(csvc, logger)
|
||||
counter, latency := prometheus.MakeMetrics("re", "api")
|
||||
csvc = middleware.NewMetricsMiddleware(counter, latency, csvc)
|
||||
csvc = middleware.NewTracingMiddleware(tracer, csvc)
|
||||
|
||||
return csvc, nil
|
||||
}
|
||||
|
||||
func newSpiceDBPolicyServiceEvaluator(cfg config, logger *slog.Logger) (policies.Service, error) {
|
||||
client, err := authzed.NewClientWithExperimentalAPIs(
|
||||
fmt.Sprintf("%s:%s", cfg.SpicedbHost, cfg.SpicedbPort),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpcutil.WithInsecureBearerToken(cfg.SpicedbPreSharedKey),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ps := spicedb.NewPolicyService(client, logger)
|
||||
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func availableActionsAndBuiltInRoles(spicedbSchemaFile string) ([]roles.Action, map[roles.BuiltInRoleName][]roles.Action, error) {
|
||||
availableActions, err := spicedbdecoder.GetActionsFromSchema(spicedbSchemaFile, operations.EntityType)
|
||||
if err != nil {
|
||||
return []roles.Action{}, map[roles.BuiltInRoleName][]roles.Action{}, err
|
||||
}
|
||||
|
||||
builtInRoles := map[roles.BuiltInRoleName][]roles.Action{
|
||||
re.BuiltInRoleAdmin: availableActions,
|
||||
}
|
||||
|
||||
return availableActions, builtInRoles, err
|
||||
}
|
||||
|
||||
+4
-1
@@ -85,11 +85,14 @@ SMQ_SPICEDB_DB_PORT=5432
|
||||
|
||||
### SpiceDB config
|
||||
SMQ_SPICEDB_PRE_SHARED_KEY="12345678"
|
||||
SMQ_SPICEDB_SCHEMA_FILE="/schema.zed"
|
||||
SMQ_SPICEDB_SCHEMA_FILE="/schemas/combined-schema.zed"
|
||||
SMQ_SPICEDB_HOST=supermq-spicedb
|
||||
SMQ_SPICEDB_PORT=50051
|
||||
SMQ_SPICEDB_DATASTORE_ENGINE=postgres
|
||||
|
||||
### Permissions
|
||||
SMQ_PERMISSIONS_FILE=/schemas/permission.yaml
|
||||
|
||||
### UI
|
||||
SMQ_UI_PATH_PREFIX=/ui
|
||||
|
||||
|
||||
@@ -253,6 +253,7 @@ services:
|
||||
container_name: magistrala-re
|
||||
depends_on:
|
||||
- re-db
|
||||
- spicedb-migrate
|
||||
restart: on-failure
|
||||
environment:
|
||||
MG_RE_LOG_LEVEL: ${MG_RE_LOG_LEVEL}
|
||||
@@ -290,6 +291,8 @@ services:
|
||||
SMQ_SPICEDB_PRE_SHARED_KEY: ${SMQ_SPICEDB_PRE_SHARED_KEY}
|
||||
SMQ_SPICEDB_HOST: ${SMQ_SPICEDB_HOST}
|
||||
SMQ_SPICEDB_PORT: ${SMQ_SPICEDB_PORT}
|
||||
SMQ_SPICEDB_SCHEMA_FILE: ${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
SMQ_PERMISSIONS_FILE: ${SMQ_PERMISSIONS_FILE}
|
||||
MG_RE_INSTANCE_ID: ${MG_RE_INSTANCE_ID}
|
||||
MG_EMAIL_HOST: ${MG_EMAIL_HOST}
|
||||
MG_EMAIL_PORT: ${MG_EMAIL_PORT}
|
||||
@@ -314,6 +317,8 @@ services:
|
||||
networks:
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ./permission.yaml:${SMQ_PERMISSIONS_FILE}
|
||||
- ./spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
- ./templates/${MG_RE_EMAIL_TEMPLATE}:/email.tmpl
|
||||
# Auth gRPC client certificates
|
||||
- type: bind
|
||||
@@ -353,6 +358,7 @@ services:
|
||||
container_name: magistrala-alarms
|
||||
depends_on:
|
||||
- alarms-db
|
||||
- spicedb-migrate
|
||||
restart: on-failure
|
||||
environment:
|
||||
MG_ALARMS_LOG_LEVEL: ${MG_ALARMS_LOG_LEVEL}
|
||||
@@ -382,6 +388,11 @@ services:
|
||||
SMQ_DOMAINS_GRPC_CLIENT_CERT: ${SMQ_DOMAINS_GRPC_CLIENT_CERT:+/domains-grpc-client.crt}
|
||||
SMQ_DOMAINS_GRPC_CLIENT_KEY: ${SMQ_DOMAINS_GRPC_CLIENT_KEY:+/domains-grpc-client.key}
|
||||
SMQ_DOMAINS_GRPC_SERVER_CA_CERTS: ${SMQ_DOMAINS_GRPC_SERVER_CA_CERTS:+/domains-grpc-server-ca.crt}
|
||||
SMQ_SPICEDB_PRE_SHARED_KEY: ${SMQ_SPICEDB_PRE_SHARED_KEY}
|
||||
SMQ_SPICEDB_HOST: ${SMQ_SPICEDB_HOST}
|
||||
SMQ_SPICEDB_PORT: ${SMQ_SPICEDB_PORT}
|
||||
SMQ_SPICEDB_SCHEMA_FILE: ${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
SMQ_PERMISSIONS_FILE: ${SMQ_PERMISSIONS_FILE}
|
||||
MG_ALARMS_INSTANCE_ID: ${MG_ALARMS_INSTANCE_ID}
|
||||
SMQ_ALLOW_UNVERIFIED_USER: ${SMQ_ALLOW_UNVERIFIED_USER}
|
||||
ports:
|
||||
@@ -389,6 +400,8 @@ services:
|
||||
networks:
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ./permission.yaml:${SMQ_PERMISSIONS_FILE}
|
||||
- ./spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
# Auth gRPC client certificates
|
||||
- type: bind
|
||||
source: ${SMQ_AUTH_GRPC_CLIENT_CERT:-ssl/certs/dummy/client_cert}
|
||||
@@ -442,6 +455,7 @@ services:
|
||||
container_name: magistrala-reports
|
||||
depends_on:
|
||||
- reports-db
|
||||
- spicedb-migrate
|
||||
restart: on-failure
|
||||
environment:
|
||||
MG_REPORTS_LOG_LEVEL: ${MG_REPORTS_LOG_LEVEL}
|
||||
@@ -472,6 +486,8 @@ services:
|
||||
SMQ_SPICEDB_PRE_SHARED_KEY: ${SMQ_SPICEDB_PRE_SHARED_KEY}
|
||||
SMQ_SPICEDB_HOST: ${SMQ_SPICEDB_HOST}
|
||||
SMQ_SPICEDB_PORT: ${SMQ_SPICEDB_PORT}
|
||||
SMQ_SPICEDB_SCHEMA_FILE: ${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
SMQ_PERMISSIONS_FILE: ${SMQ_PERMISSIONS_FILE}
|
||||
MG_REPORTS_INSTANCE_ID: ${MG_RE_INSTANCE_ID}
|
||||
MG_EMAIL_HOST: ${MG_EMAIL_HOST}
|
||||
MG_EMAIL_PORT: ${MG_EMAIL_PORT}
|
||||
@@ -496,6 +512,8 @@ services:
|
||||
networks:
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ./permission.yaml:${SMQ_PERMISSIONS_FILE}
|
||||
- ./spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
- ./templates/${MG_REPORTS_EMAIL_TEMPLATE}:/email.tmpl
|
||||
# Auth gRPC client certificates
|
||||
- type: bind
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
alarm:
|
||||
operations:
|
||||
- add: alarm_create_permission
|
||||
- list: alarm_read_permission
|
||||
- view: read_permission
|
||||
- update: update_permission
|
||||
- enable: update_permission
|
||||
- disable: update_permission
|
||||
- delete: delete_permission
|
||||
|
||||
rule:
|
||||
operations:
|
||||
- add: rule_create_permission
|
||||
- list: rule_read_permission
|
||||
- view: read_permission
|
||||
- update: update_permission
|
||||
- update_tags: update_permission
|
||||
- update_schedule: update_permission
|
||||
- enable: update_permission
|
||||
- disable: update_permission
|
||||
- delete: delete_permission
|
||||
roles_operations:
|
||||
- add: manage_role_permission
|
||||
- remove: manage_role_permission
|
||||
- update: manage_role_permission
|
||||
- retrieve: view_role_users_permission
|
||||
- retrieve_all: view_role_users_permission
|
||||
- add_actions: manage_role_permission
|
||||
- list_actions: view_role_users_permission
|
||||
- check_actions_exists: view_role_users_permission
|
||||
- remove_actions: manage_role_permission
|
||||
- remove_all_actions: manage_role_permission
|
||||
- add_members: add_role_users_permission
|
||||
- list_members: view_role_users_permission
|
||||
- check_members_exists: view_role_users_permission
|
||||
- remove_members: remove_role_users_permission
|
||||
- remove_all_members: remove_role_users_permission
|
||||
|
||||
report:
|
||||
operations:
|
||||
- add: report_create_permission
|
||||
- list: report_read_permission
|
||||
- generate: report_create_permission
|
||||
- view: read_permission
|
||||
- update: update_permission
|
||||
- update_schedule: update_permission
|
||||
- enable: update_permission
|
||||
- disable: update_permission
|
||||
- delete: delete_permission
|
||||
- update_template: update_permission
|
||||
- view_template: read_permission
|
||||
- delete_template: delete_permission
|
||||
roles_operations:
|
||||
- add: manage_role_permission
|
||||
- remove: manage_role_permission
|
||||
- update: manage_role_permission
|
||||
- retrieve: view_role_users_permission
|
||||
- retrieve_all: view_role_users_permission
|
||||
- add_actions: manage_role_permission
|
||||
- list_actions: view_role_users_permission
|
||||
- check_actions_exists: view_role_users_permission
|
||||
- remove_actions: manage_role_permission
|
||||
- remove_all_actions: manage_role_permission
|
||||
- add_members: add_role_users_permission
|
||||
- list_members: view_role_users_permission
|
||||
- check_members_exists: view_role_users_permission
|
||||
- remove_members: remove_role_users_permission
|
||||
- remove_all_members: remove_role_users_permission
|
||||
@@ -0,0 +1,706 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Code generated by scripts/combine-schema.sh. DO NOT EDIT.
|
||||
//
|
||||
// Combined from:
|
||||
// - docker/supermq-docker/spicedb/schema.zed
|
||||
// - docker/spicedb/override-schema.zed
|
||||
|
||||
definition user {}
|
||||
|
||||
|
||||
definition role {
|
||||
relation entity: domain | group | channel | client
|
||||
relation member: user
|
||||
relation built_in_role: domain | group | channel | client
|
||||
|
||||
permission delete = entity->manage_role_permission - built_in_role->manage_role_permission
|
||||
permission update = entity->manage_role_permission - built_in_role->manage_role_permission
|
||||
permission read = entity->manage_role_permission - built_in_role->manage_role_permission
|
||||
|
||||
permission add_user = entity->add_role_users_permission
|
||||
permission remove_user = entity->remove_role_users_permission
|
||||
permission view_user = entity->view_role_users_permission
|
||||
}
|
||||
|
||||
definition client {
|
||||
relation domain: domain // This can't be clubbed with parent_group, but if parent_group is unassigned then we could not track belongs to which domain, so it safe to add domain
|
||||
relation parent_group: group
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation delete: role#member
|
||||
relation set_parent_group: role#member
|
||||
relation connect_to_channel: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
permission update_permission = update + parent_group->client_update_permission + domain->client_update_permission
|
||||
permission read_permission = read + parent_group->client_read_permission + domain->client_read_permission
|
||||
permission delete_permission = delete + parent_group->client_delete_permission + domain->client_delete_permission
|
||||
permission set_parent_group_permission = set_parent_group + parent_group->client_set_parent_group_permission + domain->client_set_parent_group_permission
|
||||
permission connect_to_channel_permission = connect_to_channel + parent_group->client_connect_to_channel_permission + domain->client_connect_to_channel_permission
|
||||
|
||||
permission manage_role_permission = manage_role + parent_group->client_manage_role_permission + domain->client_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + parent_group->client_add_role_users_permission + domain->client_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + parent_group->client_remove_role_users_permission + domain->client_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + parent_group->client_view_role_users_permission + domain->client_view_role_users_permission
|
||||
}
|
||||
|
||||
definition channel {
|
||||
relation domain: domain // This can't be clubbed with parent_group, but if parent_group is unassigned then we could not track belongs to which domain, so it safe to add domain
|
||||
relation parent_group: group
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation delete: role#member
|
||||
relation set_parent_group: role#member
|
||||
relation connect_to_client: role#member
|
||||
relation publish: role#member | client
|
||||
relation subscribe: role#member | client
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
permission update_permission = update + parent_group->channel_update_permission + domain->channel_update_permission
|
||||
permission read_permission = read + parent_group->channel_read_permission + domain->channel_read_permission
|
||||
permission delete_permission = delete + parent_group->channel_delete_permission + domain->channel_delete_permission
|
||||
permission set_parent_group_permission = set_parent_group + parent_group->channel_set_parent_group_permission + domain->channel_set_parent_group_permission
|
||||
permission connect_to_client_permission = connect_to_client + parent_group->channel_connect_to_client_permission + domain->channel_connect_to_client_permission
|
||||
permission publish_permission = publish + parent_group->channel_publish_permission + domain->channel_publish_permission
|
||||
permission subscribe_permission = subscribe + parent_group->channel_subscribe_permission + domain->channel_subscribe_permission
|
||||
|
||||
permission manage_role_permission = manage_role + parent_group->channel_manage_role_permission + domain->channel_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + parent_group->channel_add_role_users_permission + domain->channel_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + parent_group->channel_remove_role_users_permission + domain->channel_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + parent_group->channel_view_role_users_permission + domain->channel_view_role_users_permission
|
||||
}
|
||||
|
||||
definition group {
|
||||
relation domain: domain // This can't be clubbed with parent_group, but if parent_group is unassigned then we could not track belongs to which domain, so it is safe to add domain
|
||||
relation parent_group: group
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation membership: role#member
|
||||
relation delete: role#member
|
||||
relation set_child: role#member
|
||||
relation set_parent: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
relation client_create: role#member
|
||||
relation channel_create: role#member
|
||||
// this allows to add parent for group during the new group creation
|
||||
relation subgroup_create: role#member
|
||||
relation subgroup_client_create: role#member
|
||||
relation subgroup_channel_create: role#member
|
||||
|
||||
relation client_update: role#member
|
||||
relation client_read: role#member
|
||||
relation client_delete: role#member
|
||||
relation client_set_parent_group: role#member
|
||||
relation client_connect_to_channel: role#member
|
||||
|
||||
relation client_manage_role: role#member
|
||||
relation client_add_role_users: role#member
|
||||
relation client_remove_role_users: role#member
|
||||
relation client_view_role_users: role#member
|
||||
|
||||
relation channel_update: role#member
|
||||
relation channel_read: role#member
|
||||
relation channel_delete: role#member
|
||||
relation channel_set_parent_group: role#member
|
||||
relation channel_connect_to_client: role#member
|
||||
relation channel_publish: role#member
|
||||
relation channel_subscribe: role#member
|
||||
|
||||
relation channel_manage_role: role#member
|
||||
relation channel_add_role_users: role#member
|
||||
relation channel_remove_role_users: role#member
|
||||
relation channel_view_role_users: role#member
|
||||
|
||||
relation subgroup_update: role#member
|
||||
relation subgroup_read: role#member
|
||||
relation subgroup_membership: role#member
|
||||
relation subgroup_delete: role#member
|
||||
relation subgroup_set_child: role#member
|
||||
relation subgroup_set_parent: role#member
|
||||
|
||||
relation subgroup_manage_role: role#member
|
||||
relation subgroup_add_role_users: role#member
|
||||
relation subgroup_remove_role_users: role#member
|
||||
relation subgroup_view_role_users: role#member
|
||||
|
||||
relation subgroup_client_update: role#member
|
||||
relation subgroup_client_read: role#member
|
||||
relation subgroup_client_delete: role#member
|
||||
relation subgroup_client_set_parent_group: role#member
|
||||
relation subgroup_client_connect_to_channel: role#member
|
||||
|
||||
relation subgroup_client_manage_role: role#member
|
||||
relation subgroup_client_add_role_users: role#member
|
||||
relation subgroup_client_remove_role_users: role#member
|
||||
relation subgroup_client_view_role_users: role#member
|
||||
|
||||
relation subgroup_channel_update: role#member
|
||||
relation subgroup_channel_read: role#member
|
||||
relation subgroup_channel_delete: role#member
|
||||
relation subgroup_channel_set_parent_group: role#member
|
||||
relation subgroup_channel_connect_to_client: role#member
|
||||
relation subgroup_channel_publish: role#member
|
||||
relation subgroup_channel_subscribe: role#member
|
||||
|
||||
relation subgroup_channel_manage_role: role#member
|
||||
relation subgroup_channel_add_role_users: role#member
|
||||
relation subgroup_channel_remove_role_users: role#member
|
||||
relation subgroup_channel_view_role_users: role#member
|
||||
|
||||
// Subgroup permission
|
||||
permission subgroup_create_permission = subgroup_create + parent_group->subgroup_create_permission
|
||||
permission subgroup_client_create_permission = subgroup_client_create + parent_group->subgroup_client_create_permission
|
||||
permission subgroup_channel_create_permission = subgroup_channel_create + parent_group->subgroup_channel_create_permission
|
||||
|
||||
permission subgroup_update_permission = subgroup_update + parent_group->subgroup_update_permission
|
||||
permission subgroup_membership_permission = subgroup_membership + parent_group->subgroup_membership_permission
|
||||
permission subgroup_read_permission = subgroup_read + parent_group->subgroup_read_permission
|
||||
permission subgroup_delete_permission = subgroup_delete + parent_group->subgroup_delete_permission
|
||||
permission subgroup_set_child_permission = subgroup_set_child + parent_group->subgroup_set_child_permission
|
||||
permission subgroup_set_parent_permission = subgroup_set_parent + parent_group->subgroup_set_parent_permission
|
||||
|
||||
permission subgroup_manage_role_permission = subgroup_manage_role + parent_group->subgroup_manage_role_permission
|
||||
permission subgroup_add_role_users_permission = subgroup_add_role_users + parent_group->subgroup_add_role_users_permission
|
||||
permission subgroup_remove_role_users_permission = subgroup_remove_role_users + parent_group->subgroup_remove_role_users_permission
|
||||
permission subgroup_view_role_users_permission = subgroup_view_role_users + parent_group->subgroup_view_role_users_permission
|
||||
|
||||
// Group permission
|
||||
permission update_permission = update + parent_group->subgroup_create_permission + domain->group_update_permission
|
||||
permission membership_permission = membership + parent_group->subgroup_membership_permission + domain->group_membership_permission
|
||||
permission read_permission = read + parent_group->subgroup_read_permission + domain->group_read_permission
|
||||
permission delete_permission = delete + parent_group->subgroup_delete_permission + domain->group_delete_permission
|
||||
permission set_child_permission = set_child + parent_group->subgroup_set_child_permission + domain->group_set_child_permission
|
||||
permission set_parent_permission = set_parent + parent_group->subgroup_set_parent_permission + domain->group_set_parent_permission
|
||||
|
||||
permission manage_role_permission = manage_role + parent_group->subgroup_manage_role_permission + domain->group_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + parent_group->subgroup_add_role_users_permission + domain->group_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + parent_group->subgroup_remove_role_users_permission + domain->group_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + parent_group->subgroup_view_role_users_permission + domain->group_view_role_users_permission
|
||||
|
||||
// Subgroup clients permission
|
||||
permission subgroup_client_update_permission = subgroup_client_update + parent_group->subgroup_client_update_permission
|
||||
permission subgroup_client_read_permission = subgroup_client_read + parent_group->subgroup_client_read_permission
|
||||
permission subgroup_client_delete_permission = subgroup_client_delete + parent_group->subgroup_client_delete_permission
|
||||
permission subgroup_client_set_parent_group_permission = subgroup_client_set_parent_group + parent_group->subgroup_client_set_parent_group_permission
|
||||
permission subgroup_client_connect_to_channel_permission = subgroup_client_connect_to_channel + parent_group->subgroup_client_connect_to_channel_permission
|
||||
|
||||
permission subgroup_client_manage_role_permission = subgroup_client_manage_role + parent_group->subgroup_client_manage_role_permission
|
||||
permission subgroup_client_add_role_users_permission = subgroup_client_add_role_users + parent_group->subgroup_client_add_role_users_permission
|
||||
permission subgroup_client_remove_role_users_permission = subgroup_client_remove_role_users + parent_group->subgroup_client_remove_role_users_permission
|
||||
permission subgroup_client_view_role_users_permission = subgroup_client_view_role_users + parent_group->subgroup_client_view_role_users_permission
|
||||
|
||||
// Group clients permission
|
||||
permission client_create_permission = client_create + parent_group->subgroup_client_create_permission + domain->client_create_permission
|
||||
permission client_update_permission = client_update + parent_group->subgroup_client_update_permission + domain->client_update_permission
|
||||
permission client_read_permission = client_read + parent_group->subgroup_client_read_permission + domain->client_read_permission
|
||||
permission client_delete_permission = client_delete + parent_group->subgroup_client_delete_permission + domain->client_delete_permission
|
||||
permission client_set_parent_group_permission = client_set_parent_group + parent_group->subgroup_client_set_parent_group_permission + domain->client_set_parent_group_permission
|
||||
permission client_connect_to_channel_permission = client_connect_to_channel + parent_group->subgroup_client_connect_to_channel_permission + domain->client_connect_to_channel_permission
|
||||
|
||||
permission client_manage_role_permission = client_manage_role + parent_group->subgroup_client_manage_role_permission + domain->client_manage_role_permission
|
||||
permission client_add_role_users_permission = client_add_role_users + parent_group->subgroup_client_add_role_users_permission + domain->client_add_role_users_permission
|
||||
permission client_remove_role_users_permission = client_remove_role_users + parent_group->subgroup_client_remove_role_users_permission + domain->client_remove_role_users_permission
|
||||
permission client_view_role_users_permission = client_view_role_users + parent_group->subgroup_client_view_role_users_permission + domain->client_view_role_users_permission
|
||||
|
||||
// Subgroup channels permission
|
||||
permission subgroup_channel_update_permission = subgroup_channel_update + parent_group->subgroup_channel_update_permission
|
||||
permission subgroup_channel_read_permission = subgroup_channel_read + parent_group->subgroup_channel_read_permission
|
||||
permission subgroup_channel_delete_permission = subgroup_channel_delete + parent_group->subgroup_channel_delete_permission
|
||||
permission subgroup_channel_set_parent_group_permission = subgroup_channel_set_parent_group + parent_group->subgroup_channel_set_parent_group_permission
|
||||
permission subgroup_channel_connect_to_client_permission = subgroup_channel_connect_to_client + parent_group->subgroup_channel_connect_to_client_permission
|
||||
permission subgroup_channel_publish_permission = subgroup_channel_publish + parent_group->subgroup_channel_publish_permission
|
||||
permission subgroup_channel_subscribe_permission = subgroup_channel_subscribe + parent_group->subgroup_channel_subscribe_permission
|
||||
|
||||
permission subgroup_channel_manage_role_permission = subgroup_channel_manage_role + parent_group->subgroup_channel_manage_role_permission
|
||||
permission subgroup_channel_add_role_users_permission = subgroup_channel_add_role_users + parent_group->subgroup_channel_add_role_users_permission
|
||||
permission subgroup_channel_remove_role_users_permission = subgroup_channel_remove_role_users + parent_group->subgroup_channel_remove_role_users_permission
|
||||
permission subgroup_channel_view_role_users_permission = subgroup_channel_view_role_users + parent_group->subgroup_channel_view_role_users_permission
|
||||
|
||||
// Group channels permission
|
||||
permission channel_create_permission = channel_create + parent_group->subgroup_channel_create_permission + domain->channel_create_permission
|
||||
permission channel_update_permission = channel_update + parent_group->subgroup_channel_update_permission + domain->channel_update_permission
|
||||
permission channel_read_permission = channel_read + parent_group->subgroup_channel_read_permission + domain->channel_read_permission
|
||||
permission channel_delete_permission = channel_delete + parent_group->subgroup_channel_delete_permission + domain->channel_delete_permission
|
||||
permission channel_set_parent_group_permission = channel_set_parent_group + parent_group->subgroup_channel_set_parent_group_permission + domain->channel_set_parent_group_permission
|
||||
permission channel_connect_to_client_permission = channel_connect_to_client + parent_group->subgroup_channel_connect_to_client_permission + domain->channel_connect_to_client_permission
|
||||
permission channel_publish_permission = channel_publish + parent_group->subgroup_channel_publish_permission + domain->channel_publish_permission
|
||||
permission channel_subscribe_permission = channel_subscribe + parent_group->subgroup_channel_subscribe_permission + domain->channel_subscribe_permission
|
||||
|
||||
permission channel_manage_role_permission = channel_manage_role + parent_group->channel_manage_role_permission + domain->channel_manage_role_permission
|
||||
permission channel_add_role_users_permission = channel_add_role_users + parent_group->channel_add_role_users_permission + domain->channel_add_role_users_permission
|
||||
permission channel_remove_role_users_permission = channel_remove_role_users + parent_group->channel_remove_role_users_permission + domain->channel_remove_role_users_permission
|
||||
permission channel_view_role_users_permission = channel_view_role_users + parent_group->channel_view_role_users_permission + domain->channel_view_role_users_permission
|
||||
|
||||
|
||||
}
|
||||
|
||||
definition domain {
|
||||
//Replace platform with organization in future
|
||||
relation organization: platform
|
||||
relation team: team
|
||||
|
||||
relation update: role#member | team#member
|
||||
relation enable: role#member | team#member
|
||||
relation disable: role#member | team#member
|
||||
relation read: role#member | team#member
|
||||
relation delete: role#member | team#member
|
||||
|
||||
relation manage_role: role#member | team#member
|
||||
relation add_role_users: role#member | team#member
|
||||
relation remove_role_users: role#member | team#member
|
||||
relation view_role_users: role#member | team#member
|
||||
|
||||
relation client_create: role#member | team#member
|
||||
relation channel_create: role#member | team#member
|
||||
relation group_create: role#member | team#member
|
||||
|
||||
relation client_update: role#member | team#member
|
||||
relation client_read: role#member | team#member
|
||||
relation client_delete: role#member | team#member
|
||||
relation client_set_parent_group: role#member | team#member
|
||||
relation client_connect_to_channel: role#member | team#member
|
||||
|
||||
relation client_manage_role: role#member | team#member
|
||||
relation client_add_role_users: role#member | team#member
|
||||
relation client_remove_role_users: role#member | team#member
|
||||
relation client_view_role_users: role#member | team#member
|
||||
|
||||
relation channel_update: role#member | team#member
|
||||
relation channel_read: role#member | team#member
|
||||
relation channel_delete: role#member | team#member
|
||||
relation channel_set_parent_group: role#member | team#member
|
||||
relation channel_connect_to_client: role#member | team#member
|
||||
relation channel_publish: role#member | team#member
|
||||
relation channel_subscribe: role#member | team#member
|
||||
|
||||
relation channel_manage_role: role#member | team#member
|
||||
relation channel_add_role_users: role#member | team#member
|
||||
relation channel_remove_role_users: role#member | team#member
|
||||
relation channel_view_role_users: role#member | team#member
|
||||
|
||||
relation group_update: role#member | team#member
|
||||
relation group_membership: role#member | team#member
|
||||
relation group_read: role#member | team#member
|
||||
relation group_delete: role#member | team#member
|
||||
relation group_set_child: role#member | team#member
|
||||
relation group_set_parent: role#member | team#member
|
||||
|
||||
relation group_manage_role: role#member | team#member
|
||||
relation group_add_role_users: role#member | team#member
|
||||
relation group_remove_role_users: role#member | team#member
|
||||
relation group_view_role_users: role#member | team#member
|
||||
|
||||
// Magistrala-specific relations
|
||||
relation alarm_create: role#member | team#member
|
||||
relation alarm_update: role#member | team#member
|
||||
relation alarm_read: role#member | team#member
|
||||
relation alarm_delete: role#member | team#member
|
||||
relation alarm_manage_role: role#member | team#member
|
||||
relation alarm_add_role_users: role#member | team#member
|
||||
relation alarm_remove_role_users: role#member | team#member
|
||||
relation alarm_view_role_users: role#member | team#member
|
||||
relation rule_create: role#member | team#member
|
||||
relation rule_update: role#member | team#member
|
||||
relation rule_read: role#member | team#member
|
||||
relation rule_delete: role#member | team#member
|
||||
relation rule_manage_role: role#member | team#member
|
||||
relation rule_add_role_users: role#member | team#member
|
||||
relation rule_remove_role_users: role#member | team#member
|
||||
relation rule_view_role_users: role#member | team#member
|
||||
relation report_create: role#member | team#member
|
||||
relation report_update: role#member | team#member
|
||||
relation report_read: role#member | team#member
|
||||
relation report_delete: role#member | team#member
|
||||
relation report_manage_role: role#member | team#member
|
||||
relation report_add_role_users: role#member | team#member
|
||||
relation report_remove_role_users: role#member | team#member
|
||||
relation report_view_role_users: role#member | team#member
|
||||
|
||||
permission update_permission = update + team->domain_update + organization->admin
|
||||
permission read_permission = read + team->domain_read + organization->admin
|
||||
permission enable_permission = enable + team->domain_update + organization->admin
|
||||
permission disable_permission = disable + team->domain_update + organization->admin
|
||||
permission delete_permission = delete + team->domain_delete + organization->admin
|
||||
|
||||
permission manage_role_permission = manage_role + team->domain_manage_role + organization->admin
|
||||
permission add_role_users_permission = add_role_users + team->domain_add_role_users + organization->admin
|
||||
permission remove_role_users_permission = remove_role_users + team->domain_remove_role_users + organization->admin
|
||||
permission view_role_users_permission = view_role_users + team->domain_view_role_users + organization->admin
|
||||
|
||||
permission membership = read + update + enable + disable + delete +
|
||||
manage_role + add_role_users + remove_role_users + view_role_users +
|
||||
client_create + channel_create + group_create +
|
||||
client_update + client_read + client_delete + client_set_parent_group + client_connect_to_channel +
|
||||
client_manage_role + client_add_role_users + client_remove_role_users + client_view_role_users +
|
||||
channel_update + channel_read + channel_delete + channel_set_parent_group + channel_connect_to_client + channel_publish + channel_subscribe +
|
||||
channel_manage_role + channel_add_role_users + channel_remove_role_users + channel_view_role_users +
|
||||
group_update + group_membership + group_read + group_delete + group_set_child + group_set_parent +
|
||||
group_manage_role + group_add_role_users + group_remove_role_users + group_view_role_users +
|
||||
alarm_create + alarm_update + alarm_read + alarm_delete + alarm_manage_role + alarm_add_role_users + alarm_remove_role_users + alarm_view_role_users + rule_create + rule_update + rule_read + rule_delete + rule_manage_role + rule_add_role_users + rule_remove_role_users + rule_view_role_users + report_create + report_update + report_read + report_delete + report_manage_role + report_add_role_users + report_remove_role_users + report_view_role_users +
|
||||
organization->admin
|
||||
|
||||
permission admin = (read & update & enable & disable & delete & manage_role & add_role_users & remove_role_users & view_role_users) + organization->admin
|
||||
|
||||
permission client_create_permission = client_create + team->client_create + organization->admin
|
||||
permission channel_create_permission = channel_create + team->channel_create + organization->admin
|
||||
permission group_create_permission = group_create + team->group_create + organization->admin
|
||||
|
||||
permission client_update_permission = client_update + team->client_update + organization->admin
|
||||
permission client_read_permission = client_read + team->client_read + organization->admin
|
||||
permission client_delete_permission = client_delete + team->client_delete + organization->admin
|
||||
permission client_set_parent_group_permission = client_set_parent_group + team->client_set_parent_group + organization->admin
|
||||
permission client_connect_to_channel_permission = client_connect_to_channel + team->client_connect_to_channel + organization->admin
|
||||
|
||||
permission client_manage_role_permission = client_manage_role + team->client_manage_role + organization->admin
|
||||
permission client_add_role_users_permission = client_add_role_users + team->client_add_role_users + organization->admin
|
||||
permission client_remove_role_users_permission = client_remove_role_users + team->client_remove_role_users + organization->admin
|
||||
permission client_view_role_users_permission = client_view_role_users + team->client_view_role_users + organization->admin
|
||||
|
||||
permission channel_update_permission = channel_update + team->channel_update + organization->admin
|
||||
permission channel_read_permission = channel_read + team->channel_read + organization->admin
|
||||
permission channel_delete_permission = channel_delete + team->channel_delete + organization->admin
|
||||
permission channel_set_parent_group_permission = channel_set_parent_group + team->channel_set_parent_group + organization->admin
|
||||
permission channel_connect_to_client_permission = channel_connect_to_client + team->channel_connect_to_client + organization->admin
|
||||
permission channel_publish_permission = channel_publish + team->channel_publish + organization->admin
|
||||
permission channel_subscribe_permission = channel_subscribe + team->channel_subscribe + organization->admin
|
||||
|
||||
permission channel_manage_role_permission = channel_manage_role + team->channel_manage_role + organization->admin
|
||||
permission channel_add_role_users_permission = channel_add_role_users + team->channel_add_role_users + organization->admin
|
||||
permission channel_remove_role_users_permission = channel_remove_role_users + team->channel_remove_role_users + organization->admin
|
||||
permission channel_view_role_users_permission = channel_view_role_users + team->channel_view_role_users + organization->admin
|
||||
|
||||
permission group_update_permission = group_update + team->group_update + organization->admin
|
||||
permission group_membership_permission = group_membership + team->group_membership + organization->admin
|
||||
permission group_read_permission = group_read + team->group_read + organization->admin
|
||||
permission group_delete_permission = group_delete + team->group_delete + organization->admin
|
||||
permission group_set_child_permission = group_set_child + team->group_set_child + organization->admin
|
||||
permission group_set_parent_permission = group_set_parent + team->group_set_parent + organization->admin
|
||||
|
||||
permission group_manage_role_permission = group_manage_role + team->group_manage_role + organization->admin
|
||||
permission group_add_role_users_permission = group_add_role_users + team->group_add_role_users + organization->admin
|
||||
permission group_remove_role_users_permission = group_remove_role_users + team->group_remove_role_users + organization->admin
|
||||
permission group_view_role_users_permission = group_view_role_users + team->group_view_role_users + organization->admin
|
||||
|
||||
// Magistrala-specific permissions
|
||||
permission alarm_create_permission = alarm_create + team->alarm_create + organization->admin
|
||||
permission alarm_update_permission = alarm_update + team->alarm_update + organization->admin
|
||||
permission alarm_read_permission = alarm_read + team->alarm_read + organization->admin
|
||||
permission alarm_delete_permission = alarm_delete + team->alarm_delete + organization->admin
|
||||
permission alarm_manage_role_permission = alarm_manage_role + team->alarm_manage_role + organization->admin
|
||||
permission alarm_add_role_users_permission = alarm_add_role_users + team->alarm_add_role_users + organization->admin
|
||||
permission alarm_remove_role_users_permission = alarm_remove_role_users + team->alarm_remove_role_users + organization->admin
|
||||
permission alarm_view_role_users_permission = alarm_view_role_users + team->alarm_view_role_users + organization->admin
|
||||
permission rule_create_permission = rule_create + team->rule_create + organization->admin
|
||||
permission rule_update_permission = rule_update + team->rule_update + organization->admin
|
||||
permission rule_read_permission = rule_read + team->rule_read + organization->admin
|
||||
permission rule_delete_permission = rule_delete + team->rule_delete + organization->admin
|
||||
permission rule_manage_role_permission = rule_manage_role + team->rule_manage_role + organization->admin
|
||||
permission rule_add_role_users_permission = rule_add_role_users + team->rule_add_role_users + organization->admin
|
||||
permission rule_remove_role_users_permission = rule_remove_role_users + team->rule_remove_role_users + organization->admin
|
||||
permission rule_view_role_users_permission = rule_view_role_users + team->rule_view_role_users + organization->admin
|
||||
permission report_create_permission = report_create + team->report_create + organization->admin
|
||||
permission report_update_permission = report_update + team->report_update + organization->admin
|
||||
permission report_read_permission = report_read + team->report_read + organization->admin
|
||||
permission report_delete_permission = report_delete + team->report_delete + organization->admin
|
||||
permission report_manage_role_permission = report_manage_role + team->report_manage_role + organization->admin
|
||||
permission report_add_role_users_permission = report_add_role_users + team->report_add_role_users + organization->admin
|
||||
permission report_remove_role_users_permission = report_remove_role_users + team->report_remove_role_users + organization->admin
|
||||
permission report_view_role_users_permission = report_view_role_users + team->report_view_role_users + organization->admin
|
||||
|
||||
}
|
||||
|
||||
// Add this relation and permission in future while adding organization
|
||||
definition team {
|
||||
relation organization: organization
|
||||
relation parent_team: team
|
||||
|
||||
relation delete: role#member
|
||||
relation enable: role#member | team#member
|
||||
relation disable: role#member | team#member
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
|
||||
relation set_parent: role#member
|
||||
relation set_child: role#member
|
||||
|
||||
relation member: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
relation subteam_delete: role#member
|
||||
relation subteam_update: role#member
|
||||
relation subteam_read: role#member
|
||||
|
||||
relation subteam_member: role#member
|
||||
|
||||
relation subteam_set_child: role#member
|
||||
relation subteam_set_parent: role#member
|
||||
|
||||
relation subteam_manage_role: role#member
|
||||
relation subteam_add_role_users: role#member
|
||||
relation subteam_remove_role_users: role#member
|
||||
relation subteam_view_role_users: role#member
|
||||
|
||||
// Domain related permission
|
||||
|
||||
relation domain_update: role#member | team#member
|
||||
relation domain_read: role#member | team#member
|
||||
relation domain_membership: role#member | team#member
|
||||
relation domain_delete: role#member | team#member
|
||||
|
||||
relation domain_manage_role: role#member | team#member
|
||||
relation domain_add_role_users: role#member | team#member
|
||||
relation domain_remove_role_users: role#member | team#member
|
||||
relation domain_view_role_users: role#member | team#member
|
||||
|
||||
relation client_create: role#member | team#member
|
||||
relation channel_create: role#member | team#member
|
||||
relation group_create: role#member | team#member
|
||||
|
||||
relation client_update: role#member | team#member
|
||||
relation client_read: role#member | team#member
|
||||
relation client_delete: role#member | team#member
|
||||
relation client_set_parent_group: role#member | team#member
|
||||
relation client_connect_to_channel: role#member | team#member
|
||||
|
||||
relation client_manage_role: role#member | team#member
|
||||
relation client_add_role_users: role#member | team#member
|
||||
relation client_remove_role_users: role#member | team#member
|
||||
relation client_view_role_users: role#member | team#member
|
||||
|
||||
relation channel_update: role#member | team#member
|
||||
relation channel_read: role#member | team#member
|
||||
relation channel_delete: role#member | team#member
|
||||
relation channel_set_parent_group: role#member | team#member
|
||||
relation channel_connect_to_client: role#member | team#member
|
||||
relation channel_publish: role#member | team#member
|
||||
relation channel_subscribe: role#member | team#member
|
||||
|
||||
relation channel_manage_role: role#member | team#member
|
||||
relation channel_add_role_users: role#member | team#member
|
||||
relation channel_remove_role_users: role#member | team#member
|
||||
relation channel_view_role_users: role#member | team#member
|
||||
|
||||
relation group_update: role#member | team#member
|
||||
relation group_membership: role#member | team#member
|
||||
relation group_read: role#member | team#member
|
||||
relation group_delete: role#member | team#member
|
||||
relation group_set_child: role#member | team#member
|
||||
relation group_set_parent: role#member | team#member
|
||||
|
||||
relation group_manage_role: role#member | team#member
|
||||
relation group_add_role_users: role#member | team#member
|
||||
relation group_remove_role_users: role#member | team#member
|
||||
relation group_view_role_users: role#member | team#member
|
||||
|
||||
// Magistrala-specific relations
|
||||
relation alarm_create: role#member | team#member
|
||||
relation alarm_update: role#member | team#member
|
||||
relation alarm_read: role#member | team#member
|
||||
relation alarm_delete: role#member | team#member
|
||||
relation alarm_manage_role: role#member | team#member
|
||||
relation alarm_add_role_users: role#member | team#member
|
||||
relation alarm_remove_role_users: role#member | team#member
|
||||
relation alarm_view_role_users: role#member | team#member
|
||||
relation rule_create: role#member | team#member
|
||||
relation rule_update: role#member | team#member
|
||||
relation rule_read: role#member | team#member
|
||||
relation rule_delete: role#member | team#member
|
||||
relation rule_manage_role: role#member | team#member
|
||||
relation rule_add_role_users: role#member | team#member
|
||||
relation rule_remove_role_users: role#member | team#member
|
||||
relation rule_view_role_users: role#member | team#member
|
||||
relation report_create: role#member | team#member
|
||||
relation report_update: role#member | team#member
|
||||
relation report_read: role#member | team#member
|
||||
relation report_delete: role#member | team#member
|
||||
relation report_manage_role: role#member | team#member
|
||||
relation report_add_role_users: role#member | team#member
|
||||
relation report_remove_role_users: role#member | team#member
|
||||
relation report_view_role_users: role#member | team#member
|
||||
|
||||
permission delete_permission = delete + organization->team_delete + parent_team->subteam_delete + organization->admin
|
||||
permission update_permission = update + organization->team_update + parent_team->subteam_update + organization->admin
|
||||
permission read_permission = read + organization->team_read + parent_team->subteam_read + organization->admin
|
||||
|
||||
permission set_parent_permission = set_parent + organization->team_set_parent + parent_team->subteam_set_parent + organization->admin
|
||||
permission set_child_permisssion = set_child + organization->team_set_child + parent_team->subteam_set_child + organization->admin
|
||||
|
||||
permission membership = member + organization->team_member + parent_team->subteam_member + organization->admin
|
||||
|
||||
permission manage_role_permission = manage_role + organization->team_manage_role + parent_team->subteam_manage_role + organization->admin
|
||||
permission add_role_users_permission = add_role_users + organization->team_add_role_users + parent_team->subteam_add_role_users + organization->admin
|
||||
permission remove_role_users_permission = remove_role_users + organization->team_remove_role_users + parent_team->subteam_remove_role_users + organization->admin
|
||||
permission view_role_users_permission = view_role_users + organization->team_view_role_users + parent_team->subteam_view_role_users + organization->admin
|
||||
}
|
||||
|
||||
|
||||
definition organization {
|
||||
relation platform: platform
|
||||
relation administrator: user
|
||||
|
||||
relation delete: role#member
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
|
||||
relation member: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
relation team_create: role#member
|
||||
|
||||
relation team_delete: role#member
|
||||
relation team_update: role#member
|
||||
relation team_read: role#member
|
||||
|
||||
relation team_member: role#member // Will be member of all the teams in the organization
|
||||
|
||||
relation team_set_child: role#member
|
||||
relation team_set_parent: role#member
|
||||
|
||||
relation team_manage_role: role#member
|
||||
relation team_add_role_users: role#member
|
||||
relation team_remove_role_users: role#member
|
||||
relation team_view_role_users: role#member
|
||||
|
||||
permission admin = administrator + platform->administrator
|
||||
permission delete_permission = admin + delete->member
|
||||
permission update_permission = admin + update->member
|
||||
permission read_permission = admin + read->member
|
||||
|
||||
permission membership = admin + member->member
|
||||
|
||||
permission team_create_permission = admin + team_create->member
|
||||
|
||||
permission manage_role_permission = admin + manage_role
|
||||
permission add_role_users_permisson = admin + add_role_users
|
||||
permission remove_role_users_permission = admin + remove_role_users
|
||||
permission view_role_users_permission = admin + view_role_users
|
||||
}
|
||||
|
||||
|
||||
definition platform {
|
||||
relation administrator: user
|
||||
relation member: user
|
||||
|
||||
permission admin = administrator
|
||||
permission membership = administrator + member
|
||||
}
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Merge documentation
|
||||
// - Source A (base): docker/supermq-docker/spicedb/schema.zed (SuperMQ upstream schema)
|
||||
// - Source B (overlay): docker/spicedb/override-schema.zed (Magistrala schema extensions)
|
||||
// - Merge script: scripts/combined-schema.sh
|
||||
// - Output: docker/spicedb/combined-schema.zed
|
||||
//
|
||||
// How merge works:
|
||||
// 1. The first `definition domain { ... }` block is treated as explicit domain overlay.
|
||||
// 2. The first `definition team { ... }` block is treated as explicit team overlay.
|
||||
// 3. Domain overlay relations/permissions are injected into SuperMQ `definition domain`.
|
||||
// 4. Team overlay relations are injected into SuperMQ `definition team`.
|
||||
// 5. `permission membership_extension = ...` from the domain overlay is injected into
|
||||
// SuperMQ `domain.permission membership` before `organization->admin`.
|
||||
// 6. Overlay `definition domain` and `definition team` blocks are removed before append,
|
||||
// so only merged SuperMQ domain/team definitions remain.
|
||||
// 7. Remaining definitions in this file (for example `alarm`, `rule`, `report`) are appended.
|
||||
//
|
||||
// Maintenance notes:
|
||||
// - Keep all custom domain/team merge lines inside the two overlay blocks below.
|
||||
// - Update `permission membership_extension` whenever domain membership additions change.
|
||||
// - Regenerate combined schema with: `sh scripts/combine-schema.sh`
|
||||
// - `scripts/supermq.sh` also regenerates combined schema after refreshing SuperMQ docker files.
|
||||
|
||||
// Overlay domain block consumed by scripts/combine-schema.sh during merge.
|
||||
|
||||
// Overlay team block consumed by scripts/combine-schema.sh during merge.
|
||||
|
||||
definition alarm {
|
||||
relation domain: domain
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation delete: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
permission update_permission = update + domain->alarm_update_permission
|
||||
permission read_permission = read + domain->alarm_read_permission
|
||||
permission delete_permission = delete + domain->alarm_delete_permission
|
||||
|
||||
permission manage_role_permission = manage_role + domain->alarm_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + domain->alarm_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + domain->alarm_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + domain->alarm_view_role_users_permission
|
||||
}
|
||||
|
||||
definition rule {
|
||||
relation domain: domain
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation delete: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
permission update_permission = update + domain->rule_update_permission
|
||||
permission read_permission = read + domain->rule_read_permission
|
||||
permission delete_permission = delete + domain->rule_delete_permission
|
||||
|
||||
permission manage_role_permission = manage_role + domain->rule_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + domain->rule_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + domain->rule_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + domain->rule_view_role_users_permission
|
||||
}
|
||||
|
||||
definition report {
|
||||
relation domain: domain
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation delete: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
permission update_permission = update + domain->report_update_permission
|
||||
permission read_permission = read + domain->report_read_permission
|
||||
permission delete_permission = delete + domain->report_delete_permission
|
||||
|
||||
permission manage_role_permission = manage_role + domain->report_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + domain->report_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + domain->report_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + domain->report_view_role_users_permission
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Merge documentation
|
||||
// - Source A (base): docker/supermq-docker/spicedb/schema.zed (SuperMQ upstream schema)
|
||||
// - Source B (overlay): docker/spicedb/override-schema.zed (Magistrala schema extensions)
|
||||
// - Merge script: scripts/combined-schema.sh
|
||||
// - Output: docker/spicedb/combined-schema.zed
|
||||
//
|
||||
// How merge works:
|
||||
// 1. The first `definition domain { ... }` block is treated as explicit domain overlay.
|
||||
// 2. The first `definition team { ... }` block is treated as explicit team overlay.
|
||||
// 3. Domain overlay relations/permissions are injected into SuperMQ `definition domain`.
|
||||
// 4. Team overlay relations are injected into SuperMQ `definition team`.
|
||||
// 5. `permission membership_extension = ...` from the domain overlay is injected into
|
||||
// SuperMQ `domain.permission membership` before `organization->admin`.
|
||||
// 6. Overlay `definition domain` and `definition team` blocks are removed before append,
|
||||
// so only merged SuperMQ domain/team definitions remain.
|
||||
// 7. Remaining definitions in this file (for example `alarm`, `rule`, `report`) are appended.
|
||||
//
|
||||
// Maintenance notes:
|
||||
// - Keep all custom domain/team merge lines inside the two overlay blocks below.
|
||||
// - Update `permission membership_extension` whenever domain membership additions change.
|
||||
// - Regenerate combined schema with: `sh scripts/combine-schema.sh`
|
||||
// - `scripts/supermq.sh` also regenerates combined schema after refreshing SuperMQ docker files.
|
||||
|
||||
// Overlay domain block consumed by scripts/combine-schema.sh during merge.
|
||||
definition domain {
|
||||
|
||||
// Magistrala-specific relations
|
||||
relation alarm_create: role#member | team#member
|
||||
relation alarm_update: role#member | team#member
|
||||
relation alarm_read: role#member | team#member
|
||||
relation alarm_delete: role#member | team#member
|
||||
relation alarm_manage_role: role#member | team#member
|
||||
relation alarm_add_role_users: role#member | team#member
|
||||
relation alarm_remove_role_users: role#member | team#member
|
||||
relation alarm_view_role_users: role#member | team#member
|
||||
|
||||
relation rule_create: role#member | team#member
|
||||
relation rule_update: role#member | team#member
|
||||
relation rule_read: role#member | team#member
|
||||
relation rule_delete: role#member | team#member
|
||||
relation rule_manage_role: role#member | team#member
|
||||
relation rule_add_role_users: role#member | team#member
|
||||
relation rule_remove_role_users: role#member | team#member
|
||||
relation rule_view_role_users: role#member | team#member
|
||||
|
||||
relation report_create: role#member | team#member
|
||||
relation report_update: role#member | team#member
|
||||
relation report_read: role#member | team#member
|
||||
relation report_delete: role#member | team#member
|
||||
relation report_manage_role: role#member | team#member
|
||||
relation report_add_role_users: role#member | team#member
|
||||
relation report_remove_role_users: role#member | team#member
|
||||
relation report_view_role_users: role#member | team#member
|
||||
|
||||
// Magistrala-specific permissions
|
||||
permission alarm_create_permission = alarm_create + team->alarm_create + organization->admin
|
||||
permission alarm_update_permission = alarm_update + team->alarm_update + organization->admin
|
||||
permission alarm_read_permission = alarm_read + team->alarm_read + organization->admin
|
||||
permission alarm_delete_permission = alarm_delete + team->alarm_delete + organization->admin
|
||||
permission alarm_manage_role_permission = alarm_manage_role + team->alarm_manage_role + organization->admin
|
||||
permission alarm_add_role_users_permission = alarm_add_role_users + team->alarm_add_role_users + organization->admin
|
||||
permission alarm_remove_role_users_permission = alarm_remove_role_users + team->alarm_remove_role_users + organization->admin
|
||||
permission alarm_view_role_users_permission = alarm_view_role_users + team->alarm_view_role_users + organization->admin
|
||||
|
||||
permission rule_create_permission = rule_create + team->rule_create + organization->admin
|
||||
permission rule_update_permission = rule_update + team->rule_update + organization->admin
|
||||
permission rule_read_permission = rule_read + team->rule_read + organization->admin
|
||||
permission rule_delete_permission = rule_delete + team->rule_delete + organization->admin
|
||||
permission rule_manage_role_permission = rule_manage_role + team->rule_manage_role + organization->admin
|
||||
permission rule_add_role_users_permission = rule_add_role_users + team->rule_add_role_users + organization->admin
|
||||
permission rule_remove_role_users_permission = rule_remove_role_users + team->rule_remove_role_users + organization->admin
|
||||
permission rule_view_role_users_permission = rule_view_role_users + team->rule_view_role_users + organization->admin
|
||||
|
||||
permission report_create_permission = report_create + team->report_create + organization->admin
|
||||
permission report_update_permission = report_update + team->report_update + organization->admin
|
||||
permission report_read_permission = report_read + team->report_read + organization->admin
|
||||
permission report_delete_permission = report_delete + team->report_delete + organization->admin
|
||||
permission report_manage_role_permission = report_manage_role + team->report_manage_role + organization->admin
|
||||
permission report_add_role_users_permission = report_add_role_users + team->report_add_role_users + organization->admin
|
||||
permission report_remove_role_users_permission = report_remove_role_users + team->report_remove_role_users + organization->admin
|
||||
permission report_view_role_users_permission = report_view_role_users + team->report_view_role_users + organization->admin
|
||||
|
||||
// Explicit extension injected into SuperMQ domain `permission membership`.
|
||||
permission membership_extension = alarm_create + alarm_update + alarm_read + alarm_delete + alarm_manage_role + alarm_add_role_users + alarm_remove_role_users + alarm_view_role_users + rule_create + rule_update + rule_read + rule_delete + rule_manage_role + rule_add_role_users + rule_remove_role_users + rule_view_role_users + report_create + report_update + report_read + report_delete + report_manage_role + report_add_role_users + report_remove_role_users + report_view_role_users
|
||||
|
||||
}
|
||||
|
||||
// Overlay team block consumed by scripts/combine-schema.sh during merge.
|
||||
definition team {
|
||||
|
||||
relation alarm_create: role#member | team#member
|
||||
relation alarm_update: role#member | team#member
|
||||
relation alarm_read: role#member | team#member
|
||||
relation alarm_delete: role#member | team#member
|
||||
relation alarm_manage_role: role#member | team#member
|
||||
relation alarm_add_role_users: role#member | team#member
|
||||
relation alarm_remove_role_users: role#member | team#member
|
||||
relation alarm_view_role_users: role#member | team#member
|
||||
|
||||
relation rule_create: role#member | team#member
|
||||
relation rule_update: role#member | team#member
|
||||
relation rule_read: role#member | team#member
|
||||
relation rule_delete: role#member | team#member
|
||||
relation rule_manage_role: role#member | team#member
|
||||
relation rule_add_role_users: role#member | team#member
|
||||
relation rule_remove_role_users: role#member | team#member
|
||||
relation rule_view_role_users: role#member | team#member
|
||||
|
||||
relation report_create: role#member | team#member
|
||||
relation report_update: role#member | team#member
|
||||
relation report_read: role#member | team#member
|
||||
relation report_delete: role#member | team#member
|
||||
relation report_manage_role: role#member | team#member
|
||||
relation report_add_role_users: role#member | team#member
|
||||
relation report_remove_role_users: role#member | team#member
|
||||
relation report_view_role_users: role#member | team#member
|
||||
|
||||
}
|
||||
|
||||
definition alarm {
|
||||
relation domain: domain
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation delete: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
permission update_permission = update + domain->alarm_update_permission
|
||||
permission read_permission = read + domain->alarm_read_permission
|
||||
permission delete_permission = delete + domain->alarm_delete_permission
|
||||
|
||||
permission manage_role_permission = manage_role + domain->alarm_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + domain->alarm_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + domain->alarm_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + domain->alarm_view_role_users_permission
|
||||
}
|
||||
|
||||
definition rule {
|
||||
relation domain: domain
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation delete: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
permission update_permission = update + domain->rule_update_permission
|
||||
permission read_permission = read + domain->rule_read_permission
|
||||
permission delete_permission = delete + domain->rule_delete_permission
|
||||
|
||||
permission manage_role_permission = manage_role + domain->rule_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + domain->rule_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + domain->rule_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + domain->rule_view_role_users_permission
|
||||
}
|
||||
|
||||
definition report {
|
||||
relation domain: domain
|
||||
|
||||
relation update: role#member
|
||||
relation read: role#member
|
||||
relation delete: role#member
|
||||
|
||||
relation manage_role: role#member
|
||||
relation add_role_users: role#member
|
||||
relation remove_role_users: role#member
|
||||
relation view_role_users: role#member
|
||||
|
||||
permission update_permission = update + domain->report_update_permission
|
||||
permission read_permission = read + domain->report_read_permission
|
||||
permission delete_permission = delete + domain->report_delete_permission
|
||||
|
||||
permission manage_role_permission = manage_role + domain->report_manage_role_permission
|
||||
permission add_role_users_permission = add_role_users + domain->report_add_role_users_permission
|
||||
permission remove_role_users_permission = remove_role_users + domain->report_remove_role_users_permission
|
||||
permission view_role_users_permission = view_role_users + domain->report_view_role_users_permission
|
||||
}
|
||||
@@ -2,9 +2,12 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
services:
|
||||
|
||||
spicedb:
|
||||
networks: !override
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ../spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
|
||||
spicedb-migrate:
|
||||
networks: !override
|
||||
@@ -17,7 +20,8 @@ services:
|
||||
auth-db:
|
||||
networks: !override
|
||||
- magistrala-base-net
|
||||
|
||||
volumes:
|
||||
- ../spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
auth-redis:
|
||||
networks: !override
|
||||
- magistrala-base-net
|
||||
@@ -25,6 +29,8 @@ services:
|
||||
auth:
|
||||
networks: !override
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ../spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
|
||||
domains-db:
|
||||
networks: !override
|
||||
@@ -37,6 +43,8 @@ services:
|
||||
domains:
|
||||
networks: !override
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ../spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
|
||||
clients-db:
|
||||
networks: !override
|
||||
@@ -49,6 +57,8 @@ services:
|
||||
clients:
|
||||
networks: !override
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ../spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
|
||||
channels-redis:
|
||||
networks: !override
|
||||
@@ -61,6 +71,8 @@ services:
|
||||
channels:
|
||||
networks: !override
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ../spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
|
||||
users-db:
|
||||
networks: !override
|
||||
@@ -77,6 +89,8 @@ services:
|
||||
groups:
|
||||
networks: !override
|
||||
- magistrala-base-net
|
||||
volumes:
|
||||
- ../spicedb/combined-schema.zed:${SMQ_SPICEDB_SCHEMA_FILE}
|
||||
|
||||
jaeger:
|
||||
networks: !override
|
||||
@@ -170,10 +184,10 @@ services:
|
||||
AM_CERTS_OPENBAO_UNSEAL_KEY_2: ${AM_CERTS_OPENBAO_UNSEAL_KEY_2}
|
||||
AM_CERTS_OPENBAO_UNSEAL_KEY_3: ${AM_CERTS_OPENBAO_UNSEAL_KEY_3}
|
||||
AM_CERTS_OPENBAO_ROOT_TOKEN: ${AM_CERTS_OPENBAO_ROOT_TOKEN}
|
||||
|
||||
|
||||
AM_JAEGER_URL: ${AM_JAEGER_URL}
|
||||
AM_JAEGER_TRACE_RATIO: ${AM_JAEGER_TRACE_RATIO}
|
||||
|
||||
|
||||
AM_AUTH_GRPC_URL: ${AM_AUTH_GRPC_URL}
|
||||
AM_AUTH_GRPC_TIMEOUT: ${AM_AUTH_GRPC_TIMEOUT}
|
||||
AM_AUTH_GRPC_CLIENT_CERT: ${AM_AUTH_GRPC_CLIENT_CERT}
|
||||
@@ -209,3 +223,5 @@ services:
|
||||
env_file: !override
|
||||
- ./.env
|
||||
- ../../docker/.env
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
module github.com/absmach/magistrala
|
||||
|
||||
go 1.25.7
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
github.com/0x6flab/namegenerator v1.4.0
|
||||
github.com/absmach/callhome v0.18.2
|
||||
github.com/absmach/certs v0.18.5
|
||||
github.com/absmach/supermq v0.18.6-0.20260226153547-15a6c026e943
|
||||
github.com/absmach/supermq v0.19.0
|
||||
github.com/authzed/authzed-go v1.8.0
|
||||
github.com/authzed/grpcutil v0.0.0-20250221190651-1985b19b35b8
|
||||
github.com/caarlos0/env/v11 v11.4.0
|
||||
@@ -36,9 +36,9 @@ require (
|
||||
github.com/traefik/yaegi v0.16.1
|
||||
github.com/vadv/gopher-lua-libs v0.8.0
|
||||
github.com/yuin/gopher-lua v1.1.1
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0
|
||||
go.opentelemetry.io/otel v1.40.0
|
||||
go.opentelemetry.io/otel/trace v1.40.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0
|
||||
go.opentelemetry.io/otel v1.41.0
|
||||
go.opentelemetry.io/otel/trace v1.41.0
|
||||
golang.org/x/sync v0.19.0
|
||||
gonum.org/v1/gonum v0.17.0
|
||||
google.golang.org/grpc v1.79.1
|
||||
@@ -47,13 +47,25 @@ require (
|
||||
moul.io/http2curl v1.0.0
|
||||
)
|
||||
|
||||
require go.uber.org/atomic v1.11.0 // indirect
|
||||
require (
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/authzed/cel-go v0.20.2 // indirect
|
||||
github.com/authzed/spicedb v1.49.2 // indirect
|
||||
github.com/ccoveille/go-safecast/v2 v2.0.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-logr/zerologr v1.2.3 // indirect
|
||||
github.com/rs/zerolog v1.34.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.1 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20251017212417-90e834f514db // indirect
|
||||
sigs.k8s.io/controller-runtime v0.22.4 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||
@@ -115,7 +127,7 @@ require (
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240917153116-6f2963f01587 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.4 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/rabbitmq/amqp091-go v1.10.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||
@@ -132,10 +144,10 @@ require (
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.41.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.41.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.41.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
|
||||
@@ -3,18 +3,23 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-202512091757
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1/go.mod h1:tvtbpgaVXZX4g6Pn+AnzFycuRK3MOz5HJfEGeEllXYM=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.122.0 h1:0JTLGrcSIs3HIGsgVPvTx3cfyFSP/k9CI8vLPHTd6Wc=
|
||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
|
||||
filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/0x6flab/namegenerator v1.4.0 h1:QnkI813SZsI/hYnKD9pg3mkIlcYzCx0N4hnzb0YYME4=
|
||||
github.com/0x6flab/namegenerator v1.4.0/go.mod h1:2sQzXuS6dX/KEwWtB6GJU729O3m4gBdD5oAU8hd0SyY=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
@@ -30,17 +35,23 @@ github.com/absmach/mgate v0.5.0 h1:RV2Aalra3xIm+XTs13TM7iE7v4WTL2SKhKcPbKr22Ac=
|
||||
github.com/absmach/mgate v0.5.0/go.mod h1:0KVq7mxM0wayosmyXPPxp1EL0c2d9kRp5V8NZCKdetA=
|
||||
github.com/absmach/senml v1.0.8 h1:+opem/r4g6c6eA/JLyCIuksyEhj7eBdysY3pEmy1mqo=
|
||||
github.com/absmach/senml v1.0.8/go.mod h1:DRhzHLgvQoIUHroBgpFrSWso+bJZO9E96RlHAHy+VRI=
|
||||
github.com/absmach/supermq v0.18.6-0.20260226153547-15a6c026e943 h1:DbQ0t46WNqMVHcks8D4XcMIYU3m5lZ6hmbhr2Wcln+Y=
|
||||
github.com/absmach/supermq v0.18.6-0.20260226153547-15a6c026e943/go.mod h1:VLInclhsnLm/mo1qng3ac7T0bJnteqH/y2mPxML6H+4=
|
||||
github.com/absmach/supermq v0.19.0 h1:sbqfzmSiMp9GEaCWgpREiLC0tFsSntgLIyAaZs7SnRY=
|
||||
github.com/absmach/supermq v0.19.0/go.mod h1:SG2yIzlJmc26ZjDVSkoapc6HZ6W13SUsaN3sAErfgC4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
|
||||
github.com/authzed/authzed-go v1.8.0 h1:cRka8J8QXGl+nyNrhsiPSFJUluIG1tuTXnG8ad2LZ1Y=
|
||||
github.com/authzed/authzed-go v1.8.0/go.mod h1:WC3x/SuVvclBlDYMg9V7e5c/J/KGGwG+cSw2WQBbodk=
|
||||
github.com/authzed/cel-go v0.20.2 h1:GlmLecGry7Z8HU0k+hmaHHUV05ZHrsFxduXHtIePvck=
|
||||
github.com/authzed/cel-go v0.20.2/go.mod h1:pJHVFWbqUHV1J+klQoZubdKswlbxcsbojda3mye9kiU=
|
||||
github.com/authzed/grpcutil v0.0.0-20250221190651-1985b19b35b8 h1:y17oq4U8n+k1OcIGGDsjYdIdp4QywGcE7ZphIvtfEbo=
|
||||
github.com/authzed/grpcutil v0.0.0-20250221190651-1985b19b35b8/go.mod h1:Pf1ZSi41EePvx1GC1DeEJw5dn35iUcxZHqpHuG1Rpic=
|
||||
github.com/authzed/spicedb v1.49.2 h1:6LKOxiNN7K18x4xs2NB0dhnDNDypbpuOP7s06AwjCH8=
|
||||
github.com/authzed/spicedb v1.49.2/go.mod h1:I9t8PtFBxUHsSZKfrkK6bxbMy8La7LYjkpgw6UpNHQs=
|
||||
github.com/aws/aws-sdk-go v1.34.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xUI=
|
||||
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
@@ -57,6 +68,8 @@ github.com/caarlos0/env/v11 v11.4.0 h1:Kcb6t5kIIr4XkoQC9AF2j+8E1Jsrl3Wz/hhm1LtoG
|
||||
github.com/caarlos0/env/v11 v11.4.0/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=
|
||||
github.com/cbroglie/mustache v1.0.1 h1:ivMg8MguXq/rrz2eu3tw6g3b16+PQhoTn6EZAhst2mw=
|
||||
github.com/cbroglie/mustache v1.0.1/go.mod h1:R/RUa+SobQ14qkP4jtx5Vke5sDytONDQXNLPY/PO69g=
|
||||
github.com/ccoveille/go-safecast/v2 v2.0.0 h1:+5eyITXAUj3wMjad6cRVJKGnC7vDS55zk0INzJagub0=
|
||||
github.com/ccoveille/go-safecast/v2 v2.0.0/go.mod h1:JIYA4CAR33blIDuE6fSwCp2sz1oOBahXnvmdBhOAABs=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
@@ -78,6 +91,7 @@ github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un
|
||||
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
@@ -109,6 +123,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/eclipse/paho.mqtt.golang v1.5.1 h1:/VSOv3oDLlpqR2Epjn1Q7b2bSTplJIeV2ISgCl2W7nE=
|
||||
github.com/eclipse/paho.mqtt.golang v1.5.1/go.mod h1:1/yJCneuyOoCOzKSsOTUc0AJfpsItBGWvYpBLimhArU=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@@ -131,6 +147,8 @@ github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sa
|
||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=
|
||||
github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
@@ -150,17 +168,22 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-logr/zerologr v1.2.3 h1:up5N9vcH9Xck3jJkXzgyOxozT14R47IyDODz8LM1KSs=
|
||||
github.com/go-logr/zerologr v1.2.3/go.mod h1:BxwGo7y5zgSHYR1BjbnHPyF/5ZjVKfKxAZANVu6E8Ho=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid/v5 v5.4.0 h1:EfbpCTjqMuGyq5ZJwxqzn3Cbr2d0rUZU7v5ycAk/e/0=
|
||||
github.com/gofrs/uuid/v5 v5.4.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
@@ -191,6 +214,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY=
|
||||
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
@@ -291,8 +316,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -330,6 +355,7 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
@@ -337,6 +363,8 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
@@ -371,6 +399,10 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
|
||||
github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
|
||||
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
|
||||
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
@@ -417,8 +449,8 @@ github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvM
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc=
|
||||
github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
@@ -433,8 +465,11 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||
github.com/rubenv/sql-migrate v1.8.1 h1:EPNwCvjAowHI3TnZ+4fQu3a915OpnQoPAjTXCGOy2U0=
|
||||
github.com/rubenv/sql-migrate v1.8.1/go.mod h1:BTIKBORjzyxZDS6dzoiw6eAFYJ1iNlGAtjn4LGeVjS8=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@@ -474,6 +509,8 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
github.com/sqids/sqids-go v0.4.1 h1:eQKYzmAZbLlRwHeHYPF35QhgxwZHLnlmVj9AkIj/rrw=
|
||||
github.com/sqids/sqids-go v0.4.1/go.mod h1:EMwHuPQgSNFS0A49jESTfIQS+066XQTVhukrzEPScl8=
|
||||
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
|
||||
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
@@ -526,22 +563,22 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 h1:XmiuHzgJt067+a6kwyAzkhXooYVv3/TOw9cM2VfJgUM=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0/go.mod h1:KDgtbWKTQs4bM+VPUr6WlL9m/WXcmkCcBlIzqxPGzmI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
|
||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0 h1:PnV4kVnw0zOmwwFkAzCN5O07fw1YOIQor120zrh0AVo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0/go.mod h1:ofAwF4uinaf8SXdVzzbL4OsxJ3VfeEg3f/F6CeF49/Y=
|
||||
go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c=
|
||||
go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.41.0 h1:ao6Oe+wSebTlQ1OEht7jlYTzQKE+pnx/iNywFvTbuuI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.41.0/go.mod h1:u3T6vz0gh/NVzgDgiwkgLxpsSF6PaPmo2il0apGJbls=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0 h1:wVZXIWjQSeSmMoxF74LzAnpVQOAFDo3pPji9Y4SOFKc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0/go.mod h1:khvBS2IggMFNwZK/6lEeHg/W57h/IX6J4URh57fuI40=
|
||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
||||
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
||||
go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ=
|
||||
go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps=
|
||||
go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8=
|
||||
go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.41.0 h1:siZQIYBAUd1rlIWQT2uCxWJxcCO7q3TriaMlf08rXw8=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.41.0/go.mod h1:HNBuSvT7ROaGtGI50ArdRLUnvRTRGniSUZbxiWxSO8Y=
|
||||
go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0=
|
||||
go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
@@ -595,6 +632,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -660,9 +699,11 @@ golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
@@ -703,6 +744,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -769,3 +812,5 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8=
|
||||
moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE=
|
||||
sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A=
|
||||
sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package policies
|
||||
|
||||
const RulesType = "rules"
|
||||
+1
-1
@@ -44,7 +44,7 @@ func viewRuleEndpoint(s re.Service) endpoint.Endpoint {
|
||||
if err := req.validate(); err != nil {
|
||||
return viewRuleRes{}, err
|
||||
}
|
||||
rule, err := s.ViewRule(ctx, session, req.id)
|
||||
rule, err := s.ViewRule(ctx, session, req.id, req.withRoles)
|
||||
if err != nil {
|
||||
return viewRuleRes{}, err
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ func TestViewRuleEndpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("ViewRule", mock.Anything, tc.authnRes, tc.id).Return(tc.svcRes, tc.svcErr)
|
||||
svcCall := svc.On("ViewRule", mock.Anything, tc.authnRes, tc.id, false).Return(tc.svcRes, tc.svcErr)
|
||||
res, err := req.make()
|
||||
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
|
||||
+2
-1
@@ -33,7 +33,8 @@ func (req addRuleReq) validate() error {
|
||||
}
|
||||
|
||||
type viewRuleReq struct {
|
||||
id string
|
||||
id string
|
||||
withRoles bool
|
||||
}
|
||||
|
||||
func (req viewRuleReq) validate() error {
|
||||
|
||||
+12
-1
@@ -16,6 +16,7 @@ import (
|
||||
apiutil "github.com/absmach/supermq/api/http/util"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
roleManagerHttp "github.com/absmach/supermq/pkg/roles/rolemanager/api"
|
||||
"github.com/go-chi/chi/v5"
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
@@ -36,6 +37,8 @@ func MakeHandler(svc re.Service, authn smqauthn.AuthNMiddleware, mux *chi.Mux, l
|
||||
r.Use(authn.WithOptions(smqauthn.WithDomainCheck(true)).Middleware())
|
||||
r.Route("/{domainID}", func(r chi.Router) {
|
||||
r.Route("/rules", func(r chi.Router) {
|
||||
d := roleManagerHttp.NewDecoder("ruleID")
|
||||
|
||||
r.Post("/", otelhttp.NewHandler(kithttp.NewServer(
|
||||
addRuleEndpoint(svc),
|
||||
decodeAddRuleRequest,
|
||||
@@ -50,6 +53,8 @@ func MakeHandler(svc re.Service, authn smqauthn.AuthNMiddleware, mux *chi.Mux, l
|
||||
opts...,
|
||||
), "list_rules").ServeHTTP)
|
||||
|
||||
r = roleManagerHttp.EntityAvailableActionsRouter(svc, d, r, opts)
|
||||
|
||||
r.Route("/{ruleID}", func(r chi.Router) {
|
||||
r.Get("/", otelhttp.NewHandler(kithttp.NewServer(
|
||||
viewRuleEndpoint(svc),
|
||||
@@ -99,6 +104,8 @@ func MakeHandler(svc re.Service, authn smqauthn.AuthNMiddleware, mux *chi.Mux, l
|
||||
api.EncodeResponse,
|
||||
opts...,
|
||||
), "disable_rule").ServeHTTP)
|
||||
|
||||
roleManagerHttp.EntityRoleMangerRouter(svc, d, r, opts)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -123,7 +130,11 @@ func decodeAddRuleRequest(_ context.Context, r *http.Request) (any, error) {
|
||||
|
||||
func decodeViewRuleRequest(_ context.Context, r *http.Request) (any, error) {
|
||||
id := chi.URLParam(r, ruleIdKey)
|
||||
return viewRuleReq{id: id}, nil
|
||||
withRoles, err := apiutil.ReadBoolQuery(r, api.RolesKey, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
return viewRuleReq{id: id, withRoles: withRoles}, nil
|
||||
}
|
||||
|
||||
func decodeUpdateRuleRequest(_ context.Context, r *http.Request) (any, error) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package re
|
||||
|
||||
import "github.com/absmach/supermq/pkg/roles"
|
||||
|
||||
const BuiltInRoleAdmin roles.BuiltInRoleName = "admin"
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/absmach/supermq/pkg/events"
|
||||
"github.com/absmach/supermq/pkg/events/store"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
rmEvents "github.com/absmach/supermq/pkg/roles/rolemanager/events"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
)
|
||||
|
||||
@@ -32,6 +33,7 @@ var _ re.Service = (*eventStore)(nil)
|
||||
type eventStore struct {
|
||||
events.Publisher
|
||||
svc re.Service
|
||||
rmEvents.RoleManagerEventStore
|
||||
}
|
||||
|
||||
// NewEventStoreMiddleware returns wrapper around rules service that sends
|
||||
@@ -42,9 +44,12 @@ func NewEventStoreMiddleware(ctx context.Context, svc re.Service, url string) (r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := rmEvents.NewRoleManagerEventStore("alarms", supermqPrefix, svc, publisher)
|
||||
|
||||
return &eventStore{
|
||||
svc: svc,
|
||||
Publisher: publisher,
|
||||
svc: svc,
|
||||
Publisher: publisher,
|
||||
RoleManagerEventStore: res,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -78,8 +83,8 @@ func (es *eventStore) ListRules(ctx context.Context, session authn.Session, pm r
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) ViewRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
rule, err := es.svc.ViewRule(ctx, session, id)
|
||||
func (es *eventStore) ViewRule(ctx context.Context, session authn.Session, id string, withRoles bool) (re.Rule, error) {
|
||||
rule, err := es.svc.ViewRule(ctx, session, id, withRoles)
|
||||
if err != nil {
|
||||
return rule, err
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/re"
|
||||
"github.com/absmach/magistrala/re/operations"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
smqauthz "github.com/absmach/supermq/pkg/authz"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
"github.com/absmach/supermq/pkg/permissions"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
rolemgr "github.com/absmach/supermq/pkg/roles/rolemanager/middleware"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -23,36 +25,47 @@ var (
|
||||
)
|
||||
|
||||
type authorizationMiddleware struct {
|
||||
svc re.Service
|
||||
authz smqauthz.Authorization
|
||||
svc re.Service
|
||||
authz smqauthz.Authorization
|
||||
entitiesOps permissions.EntitiesOperations[permissions.Operation]
|
||||
rolemgr.RoleManagerAuthorizationMiddleware
|
||||
}
|
||||
|
||||
// AuthorizationMiddleware adds authorization to the re service.
|
||||
func AuthorizationMiddleware(svc re.Service, authz smqauthz.Authorization) (re.Service, error) {
|
||||
func AuthorizationMiddleware(svc re.Service, authz smqauthz.Authorization, entitiesOps permissions.EntitiesOperations[permissions.Operation], roleOps permissions.Operations[permissions.RoleOperation]) (re.Service, error) {
|
||||
if err := entitiesOps.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ram, err := rolemgr.NewAuthorization(operations.EntityType, svc, authz, roleOps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &authorizationMiddleware{
|
||||
svc: svc,
|
||||
authz: authz,
|
||||
svc: svc,
|
||||
authz: authz,
|
||||
entitiesOps: entitiesOps,
|
||||
RoleManagerAuthorizationMiddleware: ram,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) AddRule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
if err := am.authorize(ctx, re.OpAddRule, session); err != nil {
|
||||
if err := am.authorize(ctx, operations.OpAddRule, session, policies.DomainType, session.DomainID); err != nil {
|
||||
return re.Rule{}, errors.Wrap(errDomainCreateRules, err)
|
||||
}
|
||||
|
||||
return am.svc.AddRule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ViewRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
if err := am.authorize(ctx, re.OpViewRule, session); err != nil {
|
||||
func (am *authorizationMiddleware) ViewRule(ctx context.Context, session authn.Session, id string, withRoles bool) (re.Rule, error) {
|
||||
if err := am.authorize(ctx, operations.OpViewRule, session, operations.EntityType, id); err != nil {
|
||||
return re.Rule{}, errors.Wrap(errDomainViewRules, err)
|
||||
}
|
||||
|
||||
return am.svc.ViewRule(ctx, session, id)
|
||||
return am.svc.ViewRule(ctx, session, id, withRoles)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateRule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
if err := am.authorize(ctx, re.OpUpdateRule, session); err != nil {
|
||||
if err := am.authorize(ctx, operations.OpUpdateRule, session, operations.EntityType, r.ID); err != nil {
|
||||
return re.Rule{}, errors.Wrap(errDomainUpdateRules, err)
|
||||
}
|
||||
|
||||
@@ -60,7 +73,7 @@ func (am *authorizationMiddleware) UpdateRule(ctx context.Context, session authn
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateRuleTags(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
if err := am.authorize(ctx, re.OpUpdateRuleTags, session); err != nil {
|
||||
if err := am.authorize(ctx, operations.OpUpdateRuleTags, session, operations.EntityType, r.ID); err != nil {
|
||||
return re.Rule{}, errors.Wrap(errDomainUpdateRules, err)
|
||||
}
|
||||
|
||||
@@ -68,7 +81,7 @@ func (am *authorizationMiddleware) UpdateRuleTags(ctx context.Context, session a
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateRuleSchedule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
if err := am.authorize(ctx, re.OpUpdateRuleSchedule, session); err != nil {
|
||||
if err := am.authorize(ctx, operations.OpUpdateRuleSchedule, session, operations.EntityType, r.ID); err != nil {
|
||||
return re.Rule{}, errors.Wrap(errDomainUpdateRules, err)
|
||||
}
|
||||
|
||||
@@ -76,7 +89,7 @@ func (am *authorizationMiddleware) UpdateRuleSchedule(ctx context.Context, sessi
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ListRules(ctx context.Context, session authn.Session, pm re.PageMeta) (re.Page, error) {
|
||||
if err := am.authorize(ctx, re.OpListRules, session); err != nil {
|
||||
if err := am.authorize(ctx, operations.OpListRules, session, policies.DomainType, session.DomainID); err != nil {
|
||||
return re.Page{}, errors.Wrap(errDomainViewRules, err)
|
||||
}
|
||||
|
||||
@@ -84,7 +97,7 @@ func (am *authorizationMiddleware) ListRules(ctx context.Context, session authn.
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) RemoveRule(ctx context.Context, session authn.Session, id string) error {
|
||||
if err := am.authorize(ctx, re.OpRemoveRule, session); err != nil {
|
||||
if err := am.authorize(ctx, operations.OpRemoveRule, session, operations.EntityType, id); err != nil {
|
||||
return errors.Wrap(errDomainDeleteRules, err)
|
||||
}
|
||||
|
||||
@@ -92,7 +105,7 @@ func (am *authorizationMiddleware) RemoveRule(ctx context.Context, session authn
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) EnableRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
if err := am.authorize(ctx, re.OpEnableRule, session); err != nil {
|
||||
if err := am.authorize(ctx, operations.OpEnableRule, session, operations.EntityType, id); err != nil {
|
||||
return re.Rule{}, errors.Wrap(errDomainUpdateRules, err)
|
||||
}
|
||||
|
||||
@@ -100,7 +113,7 @@ func (am *authorizationMiddleware) EnableRule(ctx context.Context, session authn
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) DisableRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
if err := am.authorize(ctx, re.OpDisableRule, session); err != nil {
|
||||
if err := am.authorize(ctx, operations.OpDisableRule, session, operations.EntityType, id); err != nil {
|
||||
return re.Rule{}, errors.Wrap(errDomainUpdateRules, err)
|
||||
}
|
||||
|
||||
@@ -119,8 +132,8 @@ func (am *authorizationMiddleware) Cancel() error {
|
||||
return am.svc.Cancel()
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) authorize(ctx context.Context, op permissions.Operation, session authn.Session) error {
|
||||
perm, err := re.GetPermission(op)
|
||||
func (am *authorizationMiddleware) authorize(ctx context.Context, op permissions.Operation, session authn.Session, objType, obj string) error {
|
||||
perm, err := am.entitiesOps.GetPermission(operations.EntityType, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -130,19 +143,19 @@ func (am *authorizationMiddleware) authorize(ctx context.Context, op permissions
|
||||
SubjectType: policies.UserType,
|
||||
SubjectKind: policies.UsersKind,
|
||||
Subject: session.DomainUserID,
|
||||
Object: session.DomainID,
|
||||
ObjectType: policies.DomainType,
|
||||
Permission: perm,
|
||||
Object: obj,
|
||||
ObjectType: objType,
|
||||
Permission: perm.String(),
|
||||
}
|
||||
|
||||
var pat *smqauthz.PATReq
|
||||
if session.PatID != "" {
|
||||
opName := re.OperationName(op)
|
||||
opName := am.entitiesOps.OperationName(operations.EntityType, op)
|
||||
pat = &smqauthz.PATReq{
|
||||
UserID: session.UserID,
|
||||
PatID: session.PatID,
|
||||
EntityID: session.DomainID,
|
||||
EntityType: re.EntityType,
|
||||
EntityType: operations.EntityType,
|
||||
Operation: opName,
|
||||
Domain: session.DomainID,
|
||||
}
|
||||
|
||||
+35
-18
@@ -7,26 +7,43 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
mgPolicies "github.com/absmach/magistrala/pkg/policies"
|
||||
"github.com/absmach/magistrala/re"
|
||||
"github.com/absmach/magistrala/re/operations"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/callout"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
"github.com/absmach/supermq/pkg/permissions"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
rolemw "github.com/absmach/supermq/pkg/roles/rolemanager/middleware"
|
||||
)
|
||||
|
||||
var _ re.Service = (*calloutMiddleware)(nil)
|
||||
|
||||
type calloutMiddleware struct {
|
||||
svc re.Service
|
||||
callout callout.Callout
|
||||
svc re.Service
|
||||
callout callout.Callout
|
||||
entitiesOps permissions.EntitiesOperations[permissions.Operation]
|
||||
rolemw.RoleManagerCalloutMiddleware
|
||||
}
|
||||
|
||||
const entityType = "rule"
|
||||
|
||||
func NewCallout(svc re.Service, callout callout.Callout) (re.Service, error) {
|
||||
func NewCallout(svc re.Service, callout callout.Callout, entitiesOps permissions.EntitiesOperations[permissions.Operation], roleOps permissions.Operations[permissions.RoleOperation]) (re.Service, error) {
|
||||
call, err := rolemw.NewCallout(mgPolicies.RulesType, svc, callout, roleOps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := entitiesOps.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &calloutMiddleware{
|
||||
svc: svc,
|
||||
callout: callout,
|
||||
svc: svc,
|
||||
callout: callout,
|
||||
entitiesOps: entitiesOps,
|
||||
RoleManagerCalloutMiddleware: call,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -36,23 +53,23 @@ func (cm *calloutMiddleware) AddRule(ctx context.Context, session authn.Session,
|
||||
"count": 1,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpAddRuleStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpAddRule, params); err != nil {
|
||||
return re.Rule{}, err
|
||||
}
|
||||
|
||||
return cm.svc.AddRule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (cm *calloutMiddleware) ViewRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
func (cm *calloutMiddleware) ViewRule(ctx context.Context, session authn.Session, id string, withRoles bool) (re.Rule, error) {
|
||||
params := map[string]any{
|
||||
"entity_id": id,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpViewRuleStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpViewRule, params); err != nil {
|
||||
return re.Rule{}, err
|
||||
}
|
||||
|
||||
return cm.svc.ViewRule(ctx, session, id)
|
||||
return cm.svc.ViewRule(ctx, session, id, withRoles)
|
||||
}
|
||||
|
||||
func (cm *calloutMiddleware) UpdateRule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
@@ -60,7 +77,7 @@ func (cm *calloutMiddleware) UpdateRule(ctx context.Context, session authn.Sessi
|
||||
"entity_id": r.ID,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpUpdateRuleStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpUpdateRule, params); err != nil {
|
||||
return re.Rule{}, err
|
||||
}
|
||||
|
||||
@@ -72,7 +89,7 @@ func (cm *calloutMiddleware) UpdateRuleTags(ctx context.Context, session authn.S
|
||||
"entity_id": r.ID,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpUpdateRuleTagsStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpUpdateRuleTags, params); err != nil {
|
||||
return re.Rule{}, err
|
||||
}
|
||||
|
||||
@@ -84,7 +101,7 @@ func (cm *calloutMiddleware) UpdateRuleSchedule(ctx context.Context, session aut
|
||||
"entity_id": r.ID,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpUpdateRuleScheduleStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpUpdateRuleSchedule, params); err != nil {
|
||||
return re.Rule{}, err
|
||||
}
|
||||
|
||||
@@ -96,7 +113,7 @@ func (cm *calloutMiddleware) ListRules(ctx context.Context, session authn.Sessio
|
||||
"pagemeta": pm,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpListRulesStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpListRules, params); err != nil {
|
||||
return re.Page{}, err
|
||||
}
|
||||
|
||||
@@ -108,7 +125,7 @@ func (cm *calloutMiddleware) RemoveRule(ctx context.Context, session authn.Sessi
|
||||
"entity_id": id,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpRemoveRuleStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpRemoveRule, params); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -120,7 +137,7 @@ func (cm *calloutMiddleware) EnableRule(ctx context.Context, session authn.Sessi
|
||||
"entity_id": id,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpEnableRuleStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpEnableRule, params); err != nil {
|
||||
return re.Rule{}, err
|
||||
}
|
||||
|
||||
@@ -132,7 +149,7 @@ func (cm *calloutMiddleware) DisableRule(ctx context.Context, session authn.Sess
|
||||
"entity_id": id,
|
||||
}
|
||||
|
||||
if err := cm.callOut(ctx, session, re.OpDisableRuleStr, params); err != nil {
|
||||
if err := cm.callOut(ctx, session, operations.OpDisableRule, params); err != nil {
|
||||
return re.Rule{}, err
|
||||
}
|
||||
|
||||
@@ -151,7 +168,7 @@ func (cm *calloutMiddleware) Cancel() error {
|
||||
return cm.svc.Cancel()
|
||||
}
|
||||
|
||||
func (cm *calloutMiddleware) callOut(ctx context.Context, session authn.Session, op string, pld map[string]any) error {
|
||||
func (cm *calloutMiddleware) callOut(ctx context.Context, session authn.Session, op permissions.Operation, pld map[string]any) error {
|
||||
var entityID string
|
||||
if id, ok := pld["entity_id"].(string); ok {
|
||||
entityID = id
|
||||
@@ -159,7 +176,7 @@ func (cm *calloutMiddleware) callOut(ctx context.Context, session authn.Session,
|
||||
|
||||
req := callout.Request{
|
||||
BaseRequest: callout.BaseRequest{
|
||||
Operation: op,
|
||||
Operation: cm.entitiesOps.OperationName(entityType, op),
|
||||
EntityType: entityType,
|
||||
EntityID: entityID,
|
||||
CallerID: session.UserID,
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/absmach/magistrala/re"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
rolemw "github.com/absmach/supermq/pkg/roles/rolemanager/middleware"
|
||||
)
|
||||
|
||||
var _ re.Service = (*loggingMiddleware)(nil)
|
||||
@@ -19,10 +20,15 @@ var _ re.Service = (*loggingMiddleware)(nil)
|
||||
type loggingMiddleware struct {
|
||||
logger *slog.Logger
|
||||
svc re.Service
|
||||
rolemw.RoleManagerLoggingMiddleware
|
||||
}
|
||||
|
||||
func LoggingMiddleware(svc re.Service, logger *slog.Logger) re.Service {
|
||||
return &loggingMiddleware{logger, svc}
|
||||
return &loggingMiddleware{
|
||||
logger: logger,
|
||||
svc: svc,
|
||||
RoleManagerLoggingMiddleware: rolemw.NewLogging("re", svc, logger),
|
||||
}
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) AddRule(ctx context.Context, session authn.Session, r re.Rule) (res re.Rule, err error) {
|
||||
@@ -42,7 +48,7 @@ func (lm *loggingMiddleware) AddRule(ctx context.Context, session authn.Session,
|
||||
return lm.svc.AddRule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) ViewRule(ctx context.Context, session authn.Session, id string) (res re.Rule, err error) {
|
||||
func (lm *loggingMiddleware) ViewRule(ctx context.Context, session authn.Session, id string, withRoles bool) (res re.Rule, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -59,7 +65,7 @@ func (lm *loggingMiddleware) ViewRule(ctx context.Context, session authn.Session
|
||||
}
|
||||
lm.logger.Info("View rule completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.ViewRule(ctx, session, id)
|
||||
return lm.svc.ViewRule(ctx, session, id, withRoles)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) UpdateRule(ctx context.Context, session authn.Session, r re.Rule) (res re.Rule, err error) {
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/re"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
rolemw "github.com/absmach/supermq/pkg/roles/rolemanager/middleware"
|
||||
"github.com/go-kit/kit/metrics"
|
||||
)
|
||||
|
||||
type metricsMiddleware struct {
|
||||
counter metrics.Counter
|
||||
latency metrics.Histogram
|
||||
service re.Service
|
||||
rolemw.RoleManagerMetricsMiddleware
|
||||
}
|
||||
|
||||
var _ re.Service = (*metricsMiddleware)(nil)
|
||||
|
||||
func NewMetricsMiddleware(counter metrics.Counter, latency metrics.Histogram, service re.Service) re.Service {
|
||||
return &metricsMiddleware{
|
||||
counter: counter,
|
||||
latency: latency,
|
||||
service: service,
|
||||
RoleManagerMetricsMiddleware: rolemw.NewMetrics("re", service, counter, latency),
|
||||
}
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) AddRule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "add_rule").Add(1)
|
||||
mm.latency.With("method", "add_rule").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.AddRule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) ViewRule(ctx context.Context, session authn.Session, id string, withRoles bool) (re.Rule, error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "view_rule").Add(1)
|
||||
mm.latency.With("method", "view_rule").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.ViewRule(ctx, session, id, withRoles)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) UpdateRule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "update_rule").Add(1)
|
||||
mm.latency.With("method", "update_rule").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.UpdateRule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) UpdateRuleTags(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "update_rule_tags").Add(1)
|
||||
mm.latency.With("method", "update_rule_tags").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.UpdateRuleTags(ctx, session, r)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) UpdateRuleSchedule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "update_rule_schedule").Add(1)
|
||||
mm.latency.With("method", "update_rule_schedule").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.UpdateRuleSchedule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) ListRules(ctx context.Context, session authn.Session, pm re.PageMeta) (re.Page, error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "list_rules").Add(1)
|
||||
mm.latency.With("method", "list_rules").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.ListRules(ctx, session, pm)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) RemoveRule(ctx context.Context, session authn.Session, id string) error {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "remove_rule").Add(1)
|
||||
mm.latency.With("method", "remove_rule").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.RemoveRule(ctx, session, id)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) EnableRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "enable_rule").Add(1)
|
||||
mm.latency.With("method", "enable_rule").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.EnableRule(ctx, session, id)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) DisableRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "disable_rule").Add(1)
|
||||
mm.latency.With("method", "disable_rule").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.DisableRule(ctx, session, id)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) Handle(msg *messaging.Message) error {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "handle").Add(1)
|
||||
mm.latency.With("method", "handle").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.Handle(msg)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) StartScheduler(ctx context.Context) error {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "start_scheduler").Add(1)
|
||||
mm.latency.With("method", "start_scheduler").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.service.StartScheduler(ctx)
|
||||
}
|
||||
|
||||
func (mm *metricsMiddleware) Cancel() error {
|
||||
return mm.service.Cancel()
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/re"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
rolemw "github.com/absmach/supermq/pkg/roles/rolemanager/middleware"
|
||||
smqTracing "github.com/absmach/supermq/pkg/tracing"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
type tracingMiddleware struct {
|
||||
tracer trace.Tracer
|
||||
svc re.Service
|
||||
rolemw.RoleManagerTracing
|
||||
}
|
||||
|
||||
var _ re.Service = (*tracingMiddleware)(nil)
|
||||
|
||||
func NewTracingMiddleware(tracer trace.Tracer, svc re.Service) re.Service {
|
||||
return &tracingMiddleware{
|
||||
tracer: tracer,
|
||||
svc: svc,
|
||||
RoleManagerTracing: rolemw.NewTracing("re", svc, tracer),
|
||||
}
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) AddRule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "add_rule", trace.WithAttributes(
|
||||
attribute.String("name", r.Name),
|
||||
attribute.String("domain_id", r.DomainID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.AddRule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) ViewRule(ctx context.Context, session authn.Session, id string, withRoles bool) (re.Rule, error) {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "view_rule", trace.WithAttributes(
|
||||
attribute.String("id", id),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.ViewRule(ctx, session, id, withRoles)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) UpdateRule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "update_rule", trace.WithAttributes(
|
||||
attribute.String("id", r.ID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.UpdateRule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) UpdateRuleTags(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "update_rule_tags", trace.WithAttributes(
|
||||
attribute.String("id", r.ID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.UpdateRuleTags(ctx, session, r)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) UpdateRuleSchedule(ctx context.Context, session authn.Session, r re.Rule) (re.Rule, error) {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "update_rule_schedule", trace.WithAttributes(
|
||||
attribute.String("id", r.ID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.UpdateRuleSchedule(ctx, session, r)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) ListRules(ctx context.Context, session authn.Session, pm re.PageMeta) (re.Page, error) {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "list_rules", trace.WithAttributes(
|
||||
attribute.Int("offset", int(pm.Offset)),
|
||||
attribute.Int("limit", int(pm.Limit)),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.ListRules(ctx, session, pm)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) RemoveRule(ctx context.Context, session authn.Session, id string) error {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "remove_rule", trace.WithAttributes(
|
||||
attribute.String("id", id),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.RemoveRule(ctx, session, id)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) EnableRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "enable_rule", trace.WithAttributes(
|
||||
attribute.String("id", id),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.EnableRule(ctx, session, id)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) DisableRule(ctx context.Context, session authn.Session, id string) (re.Rule, error) {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "disable_rule", trace.WithAttributes(
|
||||
attribute.String("id", id),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.DisableRule(ctx, session, id)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) Handle(msg *messaging.Message) error {
|
||||
_, span := smqTracing.StartSpan(context.Background(), tm.tracer, "handle", trace.WithAttributes(
|
||||
attribute.String("channel", msg.Channel),
|
||||
attribute.String("subtopic", msg.Subtopic),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.Handle(msg)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) StartScheduler(ctx context.Context) error {
|
||||
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "start_scheduler")
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.StartScheduler(ctx)
|
||||
}
|
||||
|
||||
func (tm *tracingMiddleware) Cancel() error {
|
||||
return tm.svc.Cancel()
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+1500
-12
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package re
|
||||
|
||||
import (
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
"github.com/absmach/supermq/pkg/permissions"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
)
|
||||
|
||||
const EntityType = "rules"
|
||||
|
||||
const (
|
||||
OpAddRule permissions.Operation = iota
|
||||
OpViewRule
|
||||
OpUpdateRule
|
||||
OpUpdateRuleTags
|
||||
OpUpdateRuleSchedule
|
||||
OpListRules
|
||||
OpRemoveRule
|
||||
OpEnableRule
|
||||
OpDisableRule
|
||||
)
|
||||
|
||||
const (
|
||||
OpAddRuleStr = "OpAddRule"
|
||||
OpViewRuleStr = "OpViewRule"
|
||||
OpUpdateRuleStr = "OpUpdateRule"
|
||||
OpUpdateRuleTagsStr = "OpUpdateRuleTags"
|
||||
OpUpdateRuleScheduleStr = "OpUpdateRuleSchedule"
|
||||
OpListRulesStr = "OpListRules"
|
||||
OpRemoveRuleStr = "OpRemoveRule"
|
||||
OpEnableRuleStr = "OpEnableRule"
|
||||
OpDisableRuleStr = "OpDisableRule"
|
||||
)
|
||||
|
||||
func GetPermission(op permissions.Operation) (string, error) {
|
||||
if op < OpAddRule || op > OpDisableRule {
|
||||
return "", errors.New("invalid operation")
|
||||
}
|
||||
return policies.MembershipPermission, nil
|
||||
}
|
||||
|
||||
func OperationName(op permissions.Operation) string {
|
||||
switch op {
|
||||
case OpAddRule:
|
||||
return OpAddRuleStr
|
||||
case OpViewRule:
|
||||
return OpViewRuleStr
|
||||
case OpUpdateRule:
|
||||
return OpUpdateRuleStr
|
||||
case OpUpdateRuleTags:
|
||||
return OpUpdateRuleTagsStr
|
||||
case OpUpdateRuleSchedule:
|
||||
return OpUpdateRuleScheduleStr
|
||||
case OpListRules:
|
||||
return OpListRulesStr
|
||||
case OpRemoveRule:
|
||||
return OpRemoveRuleStr
|
||||
case OpEnableRule:
|
||||
return OpEnableRuleStr
|
||||
case OpDisableRule:
|
||||
return OpDisableRuleStr
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package operations
|
||||
|
||||
import (
|
||||
"github.com/absmach/supermq/pkg/permissions"
|
||||
)
|
||||
|
||||
const EntityType = "rule"
|
||||
|
||||
// Rule Operations.
|
||||
const (
|
||||
OpAddRule permissions.Operation = iota
|
||||
OpViewRule
|
||||
OpUpdateRule
|
||||
OpUpdateRuleTags
|
||||
OpUpdateRuleSchedule
|
||||
OpRemoveRule
|
||||
OpListRules
|
||||
OpEnableRule
|
||||
OpDisableRule
|
||||
)
|
||||
|
||||
func OperationDetails() map[permissions.Operation]permissions.OperationDetails {
|
||||
return map[permissions.Operation]permissions.OperationDetails{
|
||||
OpAddRule: {
|
||||
Name: "add",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
OpViewRule: {
|
||||
Name: "view",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
OpUpdateRule: {
|
||||
Name: "update",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
OpUpdateRuleTags: {
|
||||
Name: "update_tags",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
OpUpdateRuleSchedule: {
|
||||
Name: "update_schedule",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
OpRemoveRule: {
|
||||
Name: "delete",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
OpListRules: {
|
||||
Name: "list",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
OpEnableRule: {
|
||||
Name: "enable",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
OpDisableRule: {
|
||||
Name: "disable",
|
||||
PermissionRequired: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
+20
-2
@@ -4,12 +4,20 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
dpostgres "github.com/absmach/supermq/domains/postgres"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
rolesPostgres "github.com/absmach/supermq/pkg/roles/repo/postgres"
|
||||
_ "github.com/jackc/pgx/v5/stdlib" // required for SQL access
|
||||
migrate "github.com/rubenv/sql-migrate"
|
||||
)
|
||||
|
||||
func Migration() *migrate.MemoryMigrationSource {
|
||||
return &migrate.MemoryMigrationSource{
|
||||
func Migration() (*migrate.MemoryMigrationSource, error) {
|
||||
rolesMigration, err := rolesPostgres.Migration(rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
if err != nil {
|
||||
return &migrate.MemoryMigrationSource{}, errors.Wrap(repoerr.ErrRoleMigration, err)
|
||||
}
|
||||
rulesMigration := &migrate.MemoryMigrationSource{
|
||||
Migrations: []*migrate.Migration{
|
||||
{
|
||||
Id: "rules_01",
|
||||
@@ -65,4 +73,14 @@ func Migration() *migrate.MemoryMigrationSource {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
rulesMigration.Migrations = append(rulesMigration.Migrations, rolesMigration.Migrations...)
|
||||
|
||||
domainsMigration, err := dpostgres.Migration()
|
||||
if err != nil {
|
||||
return &migrate.MemoryMigrationSource{}, errors.Wrap(repoerr.ErrRoleMigration, err)
|
||||
}
|
||||
rulesMigration.Migrations = append(rulesMigration.Migrations, domainsMigration.Migrations...)
|
||||
|
||||
return rulesMigration, nil
|
||||
}
|
||||
|
||||
+165
-1
@@ -10,19 +10,32 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
mgPolicies "github.com/absmach/magistrala/pkg/policies"
|
||||
"github.com/absmach/magistrala/re"
|
||||
api "github.com/absmach/supermq/api/http"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/pkg/postgres"
|
||||
rolesPostgres "github.com/absmach/supermq/pkg/roles/repo/postgres"
|
||||
)
|
||||
|
||||
const (
|
||||
rolesTableNamePrefix = "rules"
|
||||
entityTableName = "rules"
|
||||
entityIDColumnName = "id"
|
||||
)
|
||||
|
||||
type PostgresRepository struct {
|
||||
DB postgres.Database
|
||||
rolesPostgres.Repository
|
||||
}
|
||||
|
||||
func NewRepository(db postgres.Database) re.Repository {
|
||||
return &PostgresRepository{DB: db}
|
||||
rolesRepo := rolesPostgres.NewRepository(db, mgPolicies.RulesType, rolesTableNamePrefix, entityTableName, entityIDColumnName)
|
||||
return &PostgresRepository{
|
||||
DB: db,
|
||||
Repository: rolesRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (repo *PostgresRepository) AddRule(ctx context.Context, r re.Rule) (re.Rule, error) {
|
||||
@@ -82,6 +95,157 @@ func (repo *PostgresRepository) ViewRule(ctx context.Context, id string) (re.Rul
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (repo *PostgresRepository) RetrieveByIDWithRoles(ctx context.Context, id, memberID string) (re.Rule, error) {
|
||||
query := `
|
||||
WITH selected_rule AS (
|
||||
SELECT
|
||||
r.id,
|
||||
r.domain_id
|
||||
FROM
|
||||
rules r
|
||||
WHERE
|
||||
r.id = :id
|
||||
LIMIT 1
|
||||
),
|
||||
selected_rule_roles AS (
|
||||
SELECT
|
||||
rr.entity_id AS rule_id,
|
||||
rrm.member_id AS member_id,
|
||||
rr.id AS role_id,
|
||||
rr."name" AS role_name,
|
||||
jsonb_agg(DISTINCT rra."action") AS actions,
|
||||
'direct' AS access_type,
|
||||
'' AS access_provider_id
|
||||
FROM
|
||||
rules_roles rr
|
||||
JOIN
|
||||
rules_role_members rrm ON rr.id = rrm.role_id
|
||||
JOIN
|
||||
rules_role_actions rra ON rr.id = rra.role_id
|
||||
JOIN
|
||||
selected_rule sr ON sr.id = rr.entity_id
|
||||
AND rrm.member_id = :member_id
|
||||
GROUP BY
|
||||
rr.entity_id, rr.id, rr.name, rrm.member_id
|
||||
),
|
||||
selected_domain_roles AS (
|
||||
SELECT
|
||||
sr.id AS rule_id,
|
||||
drm.member_id AS member_id,
|
||||
dr.id AS role_id,
|
||||
dr."name" AS role_name,
|
||||
jsonb_agg(DISTINCT all_actions."action") AS actions,
|
||||
'domain' AS access_type,
|
||||
dr.entity_id AS access_provider_id
|
||||
FROM
|
||||
domains d
|
||||
JOIN
|
||||
selected_rule sr ON sr.domain_id = d.id
|
||||
JOIN
|
||||
domains_roles dr ON dr.entity_id = d.id
|
||||
JOIN
|
||||
domains_role_members drm ON dr.id = drm.role_id
|
||||
JOIN
|
||||
domains_role_actions dra ON dr.id = dra.role_id
|
||||
JOIN
|
||||
domains_role_actions all_actions ON dr.id = all_actions.role_id
|
||||
WHERE
|
||||
drm.member_id = :member_id
|
||||
AND dra."action" LIKE 'rule%'
|
||||
GROUP BY
|
||||
sr.id, dr.entity_id, dr.id, dr."name", drm.member_id
|
||||
),
|
||||
all_roles AS (
|
||||
SELECT
|
||||
srr.rule_id,
|
||||
srr.member_id,
|
||||
srr.role_id,
|
||||
srr.role_name,
|
||||
srr.actions,
|
||||
srr.access_type,
|
||||
srr.access_provider_id
|
||||
FROM
|
||||
selected_rule_roles srr
|
||||
UNION
|
||||
SELECT
|
||||
sdr.rule_id,
|
||||
sdr.member_id,
|
||||
sdr.role_id,
|
||||
sdr.role_name,
|
||||
sdr.actions,
|
||||
sdr.access_type,
|
||||
sdr.access_provider_id
|
||||
FROM
|
||||
selected_domain_roles sdr
|
||||
),
|
||||
final_roles AS (
|
||||
SELECT
|
||||
ar.rule_id,
|
||||
ar.member_id,
|
||||
jsonb_agg(
|
||||
jsonb_build_object(
|
||||
'role_id', ar.role_id,
|
||||
'role_name', ar.role_name,
|
||||
'actions', ar.actions,
|
||||
'access_type', ar.access_type,
|
||||
'access_provider_id', ar.access_provider_id
|
||||
)
|
||||
) AS roles
|
||||
FROM all_roles ar
|
||||
GROUP BY
|
||||
ar.rule_id, ar.member_id
|
||||
)
|
||||
SELECT
|
||||
r2.id,
|
||||
r2."name",
|
||||
r2.domain_id,
|
||||
r2.tags,
|
||||
r2.metadata,
|
||||
r2.input_channel,
|
||||
r2.input_topic,
|
||||
r2.outputs,
|
||||
r2.status,
|
||||
r2.logic_type,
|
||||
r2.logic_value,
|
||||
r2.time,
|
||||
r2.recurring,
|
||||
r2.recurring_period,
|
||||
r2.start_datetime,
|
||||
r2.created_at,
|
||||
r2.created_by,
|
||||
r2.updated_at,
|
||||
r2.updated_by,
|
||||
fr.member_id,
|
||||
fr.roles
|
||||
FROM rules r2
|
||||
JOIN final_roles fr ON fr.rule_id = r2.id
|
||||
`
|
||||
parameters := map[string]any{
|
||||
"id": id,
|
||||
"member_id": memberID,
|
||||
}
|
||||
row, err := repo.DB.NamedQueryContext(ctx, query, parameters)
|
||||
if err != nil {
|
||||
return re.Rule{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
dbrule := dbRule{}
|
||||
if !row.Next() {
|
||||
return re.Rule{}, repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
if err := row.StructScan(&dbrule); err != nil {
|
||||
return re.Rule{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
r, err := dbToRule(dbrule)
|
||||
if err != nil {
|
||||
return re.Rule{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (repo *PostgresRepository) UpdateRuleStatus(ctx context.Context, r re.Rule) (re.Rule, error) {
|
||||
q := `UPDATE rules
|
||||
SET status = :status, updated_at = :updated_at, updated_by = :updated_by
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/absmach/magistrala/pkg/schedule"
|
||||
"github.com/absmach/magistrala/re"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
"github.com/absmach/supermq/pkg/roles"
|
||||
"github.com/jackc/pgtype"
|
||||
)
|
||||
|
||||
@@ -35,6 +36,8 @@ type dbRule struct {
|
||||
CreatedBy string `db:"created_by"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
UpdatedBy string `db:"updated_by"`
|
||||
MemberID string `db:"member_id,omitempty"`
|
||||
Roles json.RawMessage `db:"roles,omitempty"`
|
||||
}
|
||||
|
||||
func ruleToDb(r re.Rule) (dbRule, error) {
|
||||
@@ -108,6 +111,13 @@ func dbToRule(dto dbRule) (re.Rule, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var roles []roles.MemberRoleActions
|
||||
if dto.Roles != nil {
|
||||
if err := json.Unmarshal(dto.Roles, &roles); err != nil {
|
||||
return re.Rule{}, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
}
|
||||
|
||||
return re.Rule{
|
||||
ID: dto.ID,
|
||||
Name: dto.Name,
|
||||
@@ -132,6 +142,7 @@ func dbToRule(dto dbRule) (re.Rule, error) {
|
||||
CreatedBy: dto.CreatedBy,
|
||||
UpdatedAt: dto.UpdatedAt,
|
||||
UpdatedBy: dto.UpdatedBy,
|
||||
Roles: roles,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,11 @@ func TestMain(m *testing.M) {
|
||||
SSLRootCert: "",
|
||||
}
|
||||
|
||||
if db, err = postgres.Setup(dbConfig, *repostgres.Migration()); err != nil {
|
||||
migration, err := repostgres.Migration()
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get migration: %s", err)
|
||||
}
|
||||
if db, err = postgres.Setup(dbConfig, *migration); err != nil {
|
||||
log.Fatalf("Could not setup test DB connection: %s", err)
|
||||
}
|
||||
|
||||
|
||||
+21
-16
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
"github.com/absmach/supermq/pkg/roles"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -42,21 +43,22 @@ var outputRegistry = map[outputs.OutputType]func() Runnable{
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
DomainID string `json:"domain"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
InputChannel string `json:"input_channel"`
|
||||
InputTopic string `json:"input_topic"`
|
||||
Logic Script `json:"logic"`
|
||||
Outputs Outputs `json:"outputs,omitempty"`
|
||||
Schedule schedule.Schedule `json:"schedule,omitempty"`
|
||||
Status Status `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedBy string `json:"created_by"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
UpdatedBy string `json:"updated_by"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
DomainID string `json:"domain"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
InputChannel string `json:"input_channel"`
|
||||
InputTopic string `json:"input_topic"`
|
||||
Logic Script `json:"logic"`
|
||||
Outputs Outputs `json:"outputs,omitempty"`
|
||||
Schedule schedule.Schedule `json:"schedule,omitempty"`
|
||||
Status Status `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedBy string `json:"created_by"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
UpdatedBy string `json:"updated_by"`
|
||||
Roles []roles.MemberRoleActions `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
// EventEncode converts a Rule struct to map[string]any at event producer.
|
||||
@@ -224,7 +226,7 @@ type Page struct {
|
||||
type Service interface {
|
||||
messaging.MessageHandler
|
||||
AddRule(ctx context.Context, session authn.Session, r Rule) (Rule, error)
|
||||
ViewRule(ctx context.Context, session authn.Session, id string) (Rule, error)
|
||||
ViewRule(ctx context.Context, session authn.Session, id string, withRoles bool) (Rule, error)
|
||||
UpdateRule(ctx context.Context, session authn.Session, r Rule) (Rule, error)
|
||||
UpdateRuleTags(ctx context.Context, session authn.Session, r Rule) (Rule, error)
|
||||
UpdateRuleSchedule(ctx context.Context, session authn.Session, r Rule) (Rule, error)
|
||||
@@ -234,11 +236,13 @@ type Service interface {
|
||||
DisableRule(ctx context.Context, session authn.Session, id string) (Rule, error)
|
||||
|
||||
StartScheduler(ctx context.Context) error
|
||||
roles.RoleManager
|
||||
}
|
||||
|
||||
type Repository interface {
|
||||
AddRule(ctx context.Context, r Rule) (Rule, error)
|
||||
ViewRule(ctx context.Context, id string) (Rule, error)
|
||||
RetrieveByIDWithRoles(ctx context.Context, id, memberID string) (Rule, error)
|
||||
UpdateRule(ctx context.Context, r Rule) (Rule, error)
|
||||
UpdateRuleTags(ctx context.Context, r Rule) (Rule, error)
|
||||
UpdateRuleSchedule(ctx context.Context, r Rule) (Rule, error)
|
||||
@@ -246,4 +250,5 @@ type Repository interface {
|
||||
UpdateRuleStatus(ctx context.Context, r Rule) (Rule, error)
|
||||
ListRules(ctx context.Context, pm PageMeta) (Page, error)
|
||||
UpdateRuleDue(ctx context.Context, id string, due time.Time) (Rule, error)
|
||||
roles.Repository
|
||||
}
|
||||
|
||||
+57
-14
@@ -11,11 +11,14 @@ import (
|
||||
"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")
|
||||
@@ -30,23 +33,29 @@ type re struct {
|
||||
ticker ticker.Ticker
|
||||
email emailer.Emailer
|
||||
readers grpcReadersV1.ReadersServiceClient
|
||||
roles.ProvisionManageService
|
||||
}
|
||||
|
||||
func NewService(repo Repository, runInfo chan pkglog.RunInfo, idp supermq.IDProvider, rePubSub messaging.PubSub, writersPub, alarmsPub messaging.Publisher, tck ticker.Ticker, emailer emailer.Emailer, readers grpcReadersV1.ReadersServiceClient) Service {
|
||||
return &re{
|
||||
repo: repo,
|
||||
idp: idp,
|
||||
runInfo: runInfo,
|
||||
rePubSub: rePubSub,
|
||||
writersPub: writersPub,
|
||||
alarmsPub: alarmsPub,
|
||||
ticker: tck,
|
||||
email: emailer,
|
||||
readers: readers,
|
||||
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) (Rule, error) {
|
||||
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)
|
||||
}
|
||||
@@ -72,11 +81,45 @@ func (re *re) AddRule(ctx context.Context, session authn.Session, r Rule) (Rule,
|
||||
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) (Rule, error) {
|
||||
rule, err := re.repo.ViewRule(ctx, id)
|
||||
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)
|
||||
}
|
||||
|
||||
+197
-32
@@ -26,6 +26,8 @@ import (
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
pubsubmocks "github.com/absmach/supermq/pkg/messaging/mocks"
|
||||
policymocks "github.com/absmach/supermq/pkg/policies/mocks"
|
||||
"github.com/absmach/supermq/pkg/roles"
|
||||
"github.com/absmach/supermq/pkg/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -59,27 +61,40 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func newService(t *testing.T, runInfo chan pkglog.RunInfo) (re.Service, *mocks.Repository, *pubsubmocks.PubSub, *tmocks.Ticker, *emocks.Emailer) {
|
||||
func newService(t *testing.T, runInfo chan pkglog.RunInfo) (re.Service, *mocks.Repository, *pubsubmocks.PubSub, *tmocks.Ticker, *emocks.Emailer, *policymocks.Service) {
|
||||
repo := new(mocks.Repository)
|
||||
mockTicker := new(tmocks.Ticker)
|
||||
idProvider := uuid.NewMock()
|
||||
pubsub := pubsubmocks.NewPubSub(t)
|
||||
readersSvc := new(readmocks.ReadersServiceClient)
|
||||
e := new(emocks.Emailer)
|
||||
return re.NewService(repo, runInfo, idProvider, pubsub, pubsub, pubsub, mockTicker, e, readersSvc), repo, pubsub, mockTicker, e
|
||||
policy := new(policymocks.Service)
|
||||
availableActions := []roles.Action{}
|
||||
builtInRoles := map[roles.BuiltInRoleName][]roles.Action{
|
||||
"admin": availableActions,
|
||||
}
|
||||
svc, err := re.NewService(repo, runInfo, policy, idProvider, pubsub, pubsub, pubsub, mockTicker, e, readersSvc, availableActions, builtInRoles)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create service: %v", err)
|
||||
}
|
||||
return svc, repo, pubsub, mockTicker, e, policy
|
||||
}
|
||||
|
||||
func TestAddRule(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, policies := newService(t, make(chan pkglog.RunInfo))
|
||||
ruleName := namegen.Generate()
|
||||
now := time.Now().Add(time.Hour)
|
||||
cases := []struct {
|
||||
desc string
|
||||
session authn.Session
|
||||
rule re.Rule
|
||||
res re.Rule
|
||||
err error
|
||||
desc string
|
||||
session authn.Session
|
||||
rule re.Rule
|
||||
res re.Rule
|
||||
err error
|
||||
addPoliciesErr error
|
||||
deletePolicies error
|
||||
addRoleErr error
|
||||
deleteErr error
|
||||
}{
|
||||
{
|
||||
desc: "Add rule successfully",
|
||||
@@ -109,7 +124,10 @@ func TestAddRule(t *testing.T) {
|
||||
CreatedBy: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
err: nil,
|
||||
err: nil,
|
||||
addPoliciesErr: nil,
|
||||
addRoleErr: nil,
|
||||
deleteErr: nil,
|
||||
},
|
||||
{
|
||||
desc: "Add rule with failed repo",
|
||||
@@ -126,7 +144,11 @@ func TestAddRule(t *testing.T) {
|
||||
Time: now,
|
||||
},
|
||||
},
|
||||
err: repoerr.ErrCreateEntity,
|
||||
err: repoerr.ErrCreateEntity,
|
||||
addPoliciesErr: nil,
|
||||
deletePolicies: nil,
|
||||
addRoleErr: nil,
|
||||
deleteErr: nil,
|
||||
},
|
||||
{
|
||||
desc: "Add rule with non-zero StartDateTime",
|
||||
@@ -158,7 +180,136 @@ func TestAddRule(t *testing.T) {
|
||||
CreatedBy: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
err: nil,
|
||||
err: nil,
|
||||
addPoliciesErr: nil,
|
||||
addRoleErr: nil,
|
||||
deleteErr: nil,
|
||||
},
|
||||
{
|
||||
desc: "Add rule with failed to add roles and failed to delete policies",
|
||||
session: authn.Session{
|
||||
UserID: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
rule: re.Rule{
|
||||
Name: ruleName,
|
||||
InputChannel: inputChannel,
|
||||
Schedule: pkgSch.Schedule{
|
||||
Recurring: pkgSch.Daily,
|
||||
RecurringPeriod: 1,
|
||||
Time: now,
|
||||
},
|
||||
},
|
||||
res: re.Rule{
|
||||
Name: ruleName,
|
||||
ID: ruleID,
|
||||
InputChannel: inputChannel,
|
||||
Schedule: pkgSch.Schedule{
|
||||
Recurring: pkgSch.Daily,
|
||||
RecurringPeriod: 1,
|
||||
Time: now,
|
||||
},
|
||||
Status: re.EnabledStatus,
|
||||
CreatedBy: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
addRoleErr: svcerr.ErrCreateEntity,
|
||||
deletePolicies: svcerr.ErrRemoveEntity,
|
||||
err: svcerr.ErrRemoveEntity,
|
||||
},
|
||||
{
|
||||
desc: "Add rule with failed to add policies",
|
||||
session: authn.Session{
|
||||
UserID: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
rule: re.Rule{
|
||||
Name: ruleName,
|
||||
InputChannel: inputChannel,
|
||||
Schedule: pkgSch.Schedule{
|
||||
Recurring: pkgSch.Daily,
|
||||
RecurringPeriod: 1,
|
||||
Time: now,
|
||||
},
|
||||
},
|
||||
res: re.Rule{
|
||||
Name: ruleName,
|
||||
ID: ruleID,
|
||||
InputChannel: inputChannel,
|
||||
Schedule: pkgSch.Schedule{
|
||||
Recurring: pkgSch.Daily,
|
||||
RecurringPeriod: 1,
|
||||
Time: now,
|
||||
},
|
||||
Status: re.EnabledStatus,
|
||||
CreatedBy: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
addPoliciesErr: svcerr.ErrAuthorization,
|
||||
err: svcerr.ErrAddPolicies,
|
||||
},
|
||||
{
|
||||
desc: "Add rule with failed to add policies and failed rollback",
|
||||
session: authn.Session{
|
||||
UserID: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
rule: re.Rule{
|
||||
Name: ruleName,
|
||||
InputChannel: inputChannel,
|
||||
Schedule: pkgSch.Schedule{
|
||||
Recurring: pkgSch.Daily,
|
||||
RecurringPeriod: 1,
|
||||
Time: now,
|
||||
},
|
||||
},
|
||||
res: re.Rule{
|
||||
Name: ruleName,
|
||||
ID: ruleID,
|
||||
InputChannel: inputChannel,
|
||||
Schedule: pkgSch.Schedule{
|
||||
Recurring: pkgSch.Daily,
|
||||
RecurringPeriod: 1,
|
||||
Time: now,
|
||||
},
|
||||
Status: re.EnabledStatus,
|
||||
CreatedBy: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
addPoliciesErr: svcerr.ErrAuthorization,
|
||||
deleteErr: svcerr.ErrRemoveEntity,
|
||||
err: svcerr.ErrRollbackRepo,
|
||||
},
|
||||
{
|
||||
desc: "Add rule with failed to add roles",
|
||||
session: authn.Session{
|
||||
UserID: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
rule: re.Rule{
|
||||
Name: ruleName,
|
||||
InputChannel: inputChannel,
|
||||
Schedule: pkgSch.Schedule{
|
||||
Recurring: pkgSch.Daily,
|
||||
RecurringPeriod: 1,
|
||||
Time: now,
|
||||
},
|
||||
},
|
||||
res: re.Rule{
|
||||
Name: ruleName,
|
||||
ID: ruleID,
|
||||
InputChannel: inputChannel,
|
||||
Schedule: pkgSch.Schedule{
|
||||
Recurring: pkgSch.Daily,
|
||||
RecurringPeriod: 1,
|
||||
Time: now,
|
||||
},
|
||||
Status: re.EnabledStatus,
|
||||
CreatedBy: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
addRoleErr: svcerr.ErrCreateEntity,
|
||||
err: svcerr.ErrAddPolicies,
|
||||
},
|
||||
{
|
||||
desc: "Add rule with Go script containing goroutines",
|
||||
@@ -186,6 +337,10 @@ func TestAddRule(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
repoCall := repo.On("AddRule", mock.Anything, mock.Anything).Return(tc.res, tc.err)
|
||||
policyCall := policies.On("AddPolicies", context.Background(), mock.Anything).Return(tc.addPoliciesErr)
|
||||
policyCall2 := policies.On("DeletePolicies", context.Background(), mock.Anything).Return(tc.deletePolicies).Maybe()
|
||||
repoCall1 := repo.On("AddRoles", context.Background(), mock.Anything).Return([]roles.RoleProvision{}, tc.addRoleErr)
|
||||
repoCall2 := repo.On("Remove", context.Background(), mock.Anything).Return(tc.deleteErr).Maybe()
|
||||
res, err := svc.AddRule(context.Background(), tc.session, tc.rule)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
if err == nil {
|
||||
@@ -193,14 +348,18 @@ func TestAddRule(t *testing.T) {
|
||||
assert.Equal(t, tc.rule.Name, res.Name)
|
||||
assert.Equal(t, tc.rule.Schedule, res.Schedule)
|
||||
}
|
||||
defer repoCall.Unset()
|
||||
policyCall.Unset()
|
||||
policyCall2.Unset()
|
||||
repoCall.Unset()
|
||||
repoCall1.Unset()
|
||||
repoCall2.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestViewRule(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
|
||||
now := time.Now().Add(time.Hour)
|
||||
cases := []struct {
|
||||
@@ -246,7 +405,7 @@ func TestViewRule(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
repoCall := repo.On("ViewRule", mock.Anything, mock.Anything).Return(tc.res, tc.err)
|
||||
res, err := svc.ViewRule(context.Background(), tc.session, tc.id)
|
||||
res, err := svc.ViewRule(context.Background(), tc.session, tc.id, false)
|
||||
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
if err == nil {
|
||||
@@ -259,7 +418,7 @@ func TestViewRule(t *testing.T) {
|
||||
|
||||
func TestUpdateRule(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
|
||||
newName := namegen.Generate()
|
||||
now := time.Now().Add(time.Hour)
|
||||
@@ -370,7 +529,7 @@ func TestUpdateRule(t *testing.T) {
|
||||
|
||||
func TestUpdateRuleTags(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -427,7 +586,7 @@ func TestUpdateRuleTags(t *testing.T) {
|
||||
|
||||
func TestUpdateRuleSchedule(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
|
||||
now := time.Now().UTC()
|
||||
future := now.Add(2 * time.Hour)
|
||||
@@ -495,7 +654,7 @@ func TestUpdateRuleSchedule(t *testing.T) {
|
||||
|
||||
func TestListRules(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
numRules := 50
|
||||
now := time.Now().Add(time.Hour)
|
||||
var rules []re.Rule
|
||||
@@ -629,13 +788,14 @@ func TestListRules(t *testing.T) {
|
||||
|
||||
func TestRemoveRule(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, policies := newService(t, make(chan pkglog.RunInfo))
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
session authn.Session
|
||||
id string
|
||||
err error
|
||||
desc string
|
||||
session authn.Session
|
||||
id string
|
||||
err error
|
||||
deletePoliciesErr error
|
||||
}{
|
||||
{
|
||||
desc: "remove rule successfully",
|
||||
@@ -643,8 +803,9 @@ func TestRemoveRule(t *testing.T) {
|
||||
UserID: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
id: ruleID,
|
||||
err: nil,
|
||||
id: ruleID,
|
||||
err: nil,
|
||||
deletePoliciesErr: nil,
|
||||
},
|
||||
{
|
||||
desc: "remove rule with failed repo",
|
||||
@@ -652,25 +813,28 @@ func TestRemoveRule(t *testing.T) {
|
||||
UserID: userID,
|
||||
DomainID: domainID,
|
||||
},
|
||||
id: ruleID,
|
||||
err: svcerr.ErrRemoveEntity,
|
||||
id: ruleID,
|
||||
err: svcerr.ErrRemoveEntity,
|
||||
deletePoliciesErr: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
repoCall := repo.On("RemoveRule", mock.Anything, mock.Anything).Return(tc.err)
|
||||
policyCall := policies.On("DeletePolicies", context.Background(), mock.Anything).Return(tc.deletePoliciesErr)
|
||||
err := svc.RemoveRule(context.Background(), tc.session, tc.id)
|
||||
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
defer repoCall.Unset()
|
||||
policyCall.Unset()
|
||||
repoCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnableRule(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
|
||||
now := time.Now()
|
||||
|
||||
@@ -730,7 +894,7 @@ func TestEnableRule(t *testing.T) {
|
||||
|
||||
func TestDisableRule(t *testing.T) {
|
||||
// nolint:dogsled
|
||||
svc, repo, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, _, _, _, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
|
||||
now := time.Now()
|
||||
|
||||
@@ -789,7 +953,7 @@ func TestDisableRule(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHandle(t *testing.T) {
|
||||
svc, repo, pubmocks, _, emailer := newService(t, make(chan pkglog.RunInfo))
|
||||
svc, repo, pubmocks, _, emailer, _ := newService(t, make(chan pkglog.RunInfo))
|
||||
now := time.Now()
|
||||
scheduled := false
|
||||
|
||||
@@ -1461,7 +1625,8 @@ func TestHandle(t *testing.T) {
|
||||
func TestStartScheduler(t *testing.T) {
|
||||
now := time.Now().Truncate(time.Minute)
|
||||
ri := make(chan pkglog.RunInfo)
|
||||
svc, repo, _, ticker, _ := newService(t, ri)
|
||||
// nolint:dogsled
|
||||
svc, repo, _, ticker, _, _ := newService(t, ri)
|
||||
|
||||
ctxCases := []struct {
|
||||
desc string
|
||||
|
||||
Executable
+350
@@ -0,0 +1,350 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
REPO_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
|
||||
SUPERMQ_SCHEMA="$REPO_ROOT/docker/supermq-docker/spicedb/schema.zed"
|
||||
OVERRIDE_SCHEMA="$REPO_ROOT/docker/spicedb/override-schema.zed"
|
||||
OUTPUT_SCHEMA="$REPO_ROOT/docker/spicedb/combined-schema.zed"
|
||||
|
||||
if [ ! -f "$SUPERMQ_SCHEMA" ]; then
|
||||
echo "ERROR: $SUPERMQ_SCHEMA not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$OVERRIDE_SCHEMA" ]; then
|
||||
echo "ERROR: $OVERRIDE_SCHEMA not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$OUTPUT_SCHEMA")"
|
||||
|
||||
tmp_supermq_schema=$(mktemp)
|
||||
tmp_supermq_merged=$(mktemp)
|
||||
tmp_override_remaining=$(mktemp)
|
||||
tmp_overlay_domain=$(mktemp)
|
||||
tmp_overlay_team=$(mktemp)
|
||||
tmp_overlay_domain_relations=$(mktemp)
|
||||
tmp_overlay_team_relations=$(mktemp)
|
||||
tmp_overlay_domain_permissions=$(mktemp)
|
||||
tmp_overlay_membership_extension=$(mktemp)
|
||||
|
||||
cleanup() {
|
||||
rm -f "$tmp_supermq_schema"
|
||||
rm -f "$tmp_supermq_merged"
|
||||
rm -f "$tmp_override_remaining"
|
||||
rm -f "$tmp_overlay_domain"
|
||||
rm -f "$tmp_overlay_team"
|
||||
rm -f "$tmp_overlay_domain_relations"
|
||||
rm -f "$tmp_overlay_team_relations"
|
||||
rm -f "$tmp_overlay_domain_permissions"
|
||||
rm -f "$tmp_overlay_membership_extension"
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
cp "$SUPERMQ_SCHEMA" "$tmp_supermq_schema"
|
||||
|
||||
# Extract the first domain overlay block from override schema.
|
||||
if ! awk '
|
||||
BEGIN {
|
||||
in_domain = 0
|
||||
found = 0
|
||||
}
|
||||
!found && /^definition domain[[:space:]]*{/ {
|
||||
in_domain = 1
|
||||
found = 1
|
||||
next
|
||||
}
|
||||
in_domain {
|
||||
if ($0 ~ /^}/) {
|
||||
in_domain = 0
|
||||
next
|
||||
}
|
||||
print
|
||||
}
|
||||
END {
|
||||
if (!found) {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
' "$OVERRIDE_SCHEMA" > "$tmp_overlay_domain"; then
|
||||
echo "ERROR: definition domain block not found in $OVERRIDE_SCHEMA" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract the first team overlay block from override schema.
|
||||
if ! awk '
|
||||
BEGIN {
|
||||
in_team = 0
|
||||
found = 0
|
||||
}
|
||||
!found && /^definition team[[:space:]]*{/ {
|
||||
in_team = 1
|
||||
found = 1
|
||||
next
|
||||
}
|
||||
in_team {
|
||||
if ($0 ~ /^}/) {
|
||||
in_team = 0
|
||||
next
|
||||
}
|
||||
print
|
||||
}
|
||||
END {
|
||||
if (!found) {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
' "$OVERRIDE_SCHEMA" > "$tmp_overlay_team"; then
|
||||
echo "ERROR: definition team block not found in $OVERRIDE_SCHEMA" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read explicit domain overlay relations from override domain block.
|
||||
awk '
|
||||
/^[[:space:]]*relation[[:space:]]+[A-Za-z0-9_]+:[[:space:]]*role#member[[:space:]]*\|[[:space:]]*team#member[[:space:]]*$/ {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "\t", line)
|
||||
print line
|
||||
}
|
||||
' "$tmp_overlay_domain" > "$tmp_overlay_domain_relations"
|
||||
|
||||
# Read explicit team overlay relations from override team block.
|
||||
awk '
|
||||
/^[[:space:]]*relation[[:space:]]+[A-Za-z0-9_]+:[[:space:]]*role#member[[:space:]]*\|[[:space:]]*team#member[[:space:]]*$/ {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "\t", line)
|
||||
print line
|
||||
}
|
||||
' "$tmp_overlay_team" > "$tmp_overlay_team_relations"
|
||||
|
||||
# Read explicit domain overlay permissions from override domain block.
|
||||
awk '
|
||||
/^[[:space:]]*permission[[:space:]]+[A-Za-z0-9_]+_permission[[:space:]]*=/ {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "\t", line)
|
||||
print line
|
||||
}
|
||||
' "$tmp_overlay_domain" > "$tmp_overlay_domain_permissions"
|
||||
|
||||
# Read explicit domain membership extension expression from override domain block.
|
||||
awk '
|
||||
/^[[:space:]]*permission[[:space:]]+membership_extension[[:space:]]*=/ {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*permission[[:space:]]+membership_extension[[:space:]]*=[[:space:]]*/, "", line)
|
||||
print line
|
||||
exit
|
||||
}
|
||||
' "$tmp_overlay_domain" > "$tmp_overlay_membership_extension"
|
||||
|
||||
if [ ! -s "$tmp_overlay_domain_relations" ]; then
|
||||
echo "ERROR: no domain relation overlay lines found in definition domain block of $OVERRIDE_SCHEMA" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -s "$tmp_overlay_team_relations" ]; then
|
||||
echo "ERROR: no team relation overlay lines found in definition team block of $OVERRIDE_SCHEMA" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -s "$tmp_overlay_domain_permissions" ]; then
|
||||
echo "ERROR: no domain permission overlay lines found in definition domain block of $OVERRIDE_SCHEMA" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -s "$tmp_overlay_membership_extension" ]; then
|
||||
echo "ERROR: permission membership_extension not found in definition domain block of $OVERRIDE_SCHEMA" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove the first domain and first team overlay blocks from override schema before appending.
|
||||
if ! awk '
|
||||
BEGIN {
|
||||
skip_domain = 0
|
||||
skip_team = 0
|
||||
removed_domain = 0
|
||||
removed_team = 0
|
||||
}
|
||||
!removed_domain && /^definition domain[[:space:]]*{/ {
|
||||
skip_domain = 1
|
||||
removed_domain = 1
|
||||
next
|
||||
}
|
||||
skip_domain {
|
||||
if ($0 ~ /^}/) {
|
||||
skip_domain = 0
|
||||
}
|
||||
next
|
||||
}
|
||||
!removed_team && /^definition team[[:space:]]*{/ {
|
||||
skip_team = 1
|
||||
removed_team = 1
|
||||
next
|
||||
}
|
||||
skip_team {
|
||||
if ($0 ~ /^}/) {
|
||||
skip_team = 0
|
||||
}
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
END {
|
||||
if (!removed_domain || !removed_team) {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
' "$OVERRIDE_SCHEMA" > "$tmp_override_remaining"; then
|
||||
echo "ERROR: failed to strip definition domain/team blocks from $OVERRIDE_SCHEMA" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Inject explicit override lines into SuperMQ domain and team definitions.
|
||||
awk \
|
||||
-v domain_relations_file="$tmp_overlay_domain_relations" \
|
||||
-v team_relations_file="$tmp_overlay_team_relations" \
|
||||
-v domain_permissions_file="$tmp_overlay_domain_permissions" \
|
||||
-v membership_extension_file="$tmp_overlay_membership_extension" '
|
||||
BEGIN {
|
||||
while ((getline line < domain_relations_file) > 0) {
|
||||
domain_relations = domain_relations line ORS
|
||||
}
|
||||
close(domain_relations_file)
|
||||
|
||||
while ((getline line < team_relations_file) > 0) {
|
||||
team_relations = team_relations line ORS
|
||||
}
|
||||
close(team_relations_file)
|
||||
|
||||
while ((getline line < domain_permissions_file) > 0) {
|
||||
domain_permissions = domain_permissions line ORS
|
||||
}
|
||||
close(domain_permissions_file)
|
||||
|
||||
membership_extension = ""
|
||||
if ((getline line < membership_extension_file) > 0) {
|
||||
membership_extension = line
|
||||
}
|
||||
close(membership_extension_file)
|
||||
|
||||
in_domain = 0
|
||||
in_team = 0
|
||||
in_domain_membership = 0
|
||||
inserted_domain_relations = 0
|
||||
inserted_team_relations = 0
|
||||
inserted_domain_permissions = 0
|
||||
inserted_domain_membership = 0
|
||||
}
|
||||
{
|
||||
if ($0 ~ /^definition domain[[:space:]]*{/) {
|
||||
in_domain = 1
|
||||
} else if ($0 ~ /^definition team[[:space:]]*{/) {
|
||||
in_team = 1
|
||||
}
|
||||
|
||||
if (in_domain && $0 ~ /^[[:space:]]*permission membership[[:space:]]*=/) {
|
||||
in_domain_membership = 1
|
||||
}
|
||||
|
||||
if (in_domain && in_domain_membership && $0 ~ /organization->admin[[:space:]]*$/) {
|
||||
membership_tail = $0
|
||||
sub(/[[:space:]]*\+[[:space:]]*organization->admin[[:space:]]*$/, " +", membership_tail)
|
||||
print membership_tail
|
||||
print "\t" membership_extension " +"
|
||||
print "\torganization->admin"
|
||||
in_domain_membership = 0
|
||||
inserted_domain_membership = 1
|
||||
next
|
||||
}
|
||||
|
||||
print $0
|
||||
|
||||
if (in_domain && $0 ~ /^[[:space:]]*relation group_view_role_users: role#member \| team#member[[:space:]]*$/) {
|
||||
print ""
|
||||
print "\t// Magistrala-specific relations"
|
||||
printf "%s", domain_relations
|
||||
inserted_domain_relations = 1
|
||||
}
|
||||
|
||||
if (in_team && $0 ~ /^[[:space:]]*relation group_view_role_users: role#member \| team#member[[:space:]]*$/) {
|
||||
print ""
|
||||
print "\t// Magistrala-specific relations"
|
||||
printf "%s", team_relations
|
||||
inserted_team_relations = 1
|
||||
}
|
||||
|
||||
if (in_domain && $0 ~ /^[[:space:]]*permission group_view_role_users_permission = group_view_role_users \+ team->group_view_role_users \+ organization->admin[[:space:]]*$/) {
|
||||
print ""
|
||||
print "\t// Magistrala-specific permissions"
|
||||
printf "%s", domain_permissions
|
||||
inserted_domain_permissions = 1
|
||||
}
|
||||
|
||||
if (in_domain && $0 ~ /^}/) {
|
||||
in_domain = 0
|
||||
in_domain_membership = 0
|
||||
} else if (in_team && $0 ~ /^}/) {
|
||||
in_team = 0
|
||||
}
|
||||
}
|
||||
END {
|
||||
if (!inserted_domain_relations || !inserted_team_relations || !inserted_domain_permissions || !inserted_domain_membership) {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
' "$tmp_supermq_schema" > "$tmp_supermq_merged" || {
|
||||
echo "ERROR: failed to merge override schema into SuperMQ schema" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
first_domain_relation=$(awk 'NR == 1 {print $2}' "$tmp_overlay_domain_relations")
|
||||
first_team_relation=$(awk 'NR == 1 {print $2}' "$tmp_overlay_team_relations")
|
||||
first_domain_permission=$(awk 'NR == 1 {print $2}' "$tmp_overlay_domain_permissions")
|
||||
|
||||
if [ -z "$first_domain_relation" ] || [ -z "$first_team_relation" ] || [ -z "$first_domain_permission" ]; then
|
||||
echo "ERROR: failed to verify merged overlay lines" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sub_first_domain_relation=${first_domain_relation%%:*}
|
||||
sub_first_team_relation=${first_team_relation%%:*}
|
||||
|
||||
if ! grep -Fq "relation $sub_first_domain_relation: role#member | team#member" "$tmp_supermq_merged"; then
|
||||
echo "ERROR: merged schema is missing domain relation $sub_first_domain_relation" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -Fq "relation $sub_first_team_relation: role#member | team#member" "$tmp_supermq_merged"; then
|
||||
echo "ERROR: merged schema is missing team relation $sub_first_team_relation" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -Fq "permission $first_domain_permission" "$tmp_supermq_merged"; then
|
||||
echo "ERROR: merged schema is missing domain permission $first_domain_permission" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
membership_extension_value=$(cat "$tmp_overlay_membership_extension")
|
||||
if ! grep -Fq "$membership_extension_value +" "$tmp_supermq_merged"; then
|
||||
echo "ERROR: merged schema is missing domain membership_extension values" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
{
|
||||
cat <<'EOF'
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Code generated by scripts/combine-schema.sh. DO NOT EDIT.
|
||||
//
|
||||
// Combined from:
|
||||
// - docker/supermq-docker/spicedb/schema.zed
|
||||
// - docker/spicedb/override-schema.zed
|
||||
|
||||
EOF
|
||||
cat "$tmp_supermq_merged" "$tmp_override_remaining"
|
||||
} > "$OUTPUT_SCHEMA"
|
||||
|
||||
echo "Combined schema generated at: $OUTPUT_SCHEMA"
|
||||
+4
-1
@@ -13,7 +13,8 @@ REPO_URL=https://github.com/absmach/supermq
|
||||
TEMP_DIR="supermq"
|
||||
DOCKER_DIR="docker"
|
||||
DOCKER_DST_DIR="../docker"
|
||||
DEST_DIR="../../docker/supermq-docker"
|
||||
DEST_DIR="../docker/supermq-docker"
|
||||
COMBINE_SCHEMA_SCRIPT="./combine-schema.sh"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR" || exit 1
|
||||
@@ -40,3 +41,5 @@ mkdir -p "$DEST_DIR"
|
||||
mv -f "$DOCKER_DIR"/.??* "$DOCKER_DIR"/* "$DEST_DIR"/
|
||||
cd ..
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
sh "$COMBINE_SCHEMA_SCRIPT"
|
||||
|
||||
Reference in New Issue
Block a user