mirror of
https://github.com/paralus/paralus.git
synced 2026-08-24 15:47:19 +00:00
@@ -0,0 +1,46 @@
|
||||
# Filebeat
|
||||
|
||||
We use filebeat inorder to push logs from application to elasticsearch
|
||||
server.
|
||||
|
||||
In actual deployment, the idea is that we will have a sidecar
|
||||
container that will be responsible for tailing the log files so that
|
||||
we can read it using a filebeat instance running in a daemonset.
|
||||
|
||||
## Development
|
||||
|
||||
For local testing, you can run filebeat as as a binary and push the
|
||||
logs generated into ES. You can use the following config to do so.
|
||||
|
||||
``` yaml
|
||||
filebeat.inputs:
|
||||
- type: log
|
||||
fields:
|
||||
type: "auditlogs"
|
||||
paths:
|
||||
- audit.log # audit file path
|
||||
json.keys_under_root: true
|
||||
json.overwrite_keys: true
|
||||
json.add_error_key: true
|
||||
json.expand_keys: true
|
||||
|
||||
output.elasticsearch:
|
||||
hosts: ["http://127.0.0.1:9200"]
|
||||
index: "index-%{[fields.type]:other}-%{+yyyy.MM.dd}"
|
||||
ssl:
|
||||
verification_mode: "none"
|
||||
enabled: false
|
||||
ca_trusted_fingerprint: "ignore-this"
|
||||
|
||||
setup.template.name: "index"
|
||||
setup.template.pattern: "index-*"
|
||||
setup.template.overwrite: true
|
||||
setup.template.append_fields:
|
||||
- name: timestamp
|
||||
type: date
|
||||
```
|
||||
|
||||
This will push the audit logs generated in `audit.log` file into
|
||||
elasticsearch index with the name `index-auditlogs-<date>` which you
|
||||
should be able to see in ES. Now if you were to use this as the audit
|
||||
index key, you should be able to use this in the application.
|
||||
@@ -203,6 +203,15 @@
|
||||
"clientType": {
|
||||
"$ref": "#/definitions/v3ClientType"
|
||||
},
|
||||
"clientHost": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientIp": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientUa": {
|
||||
"type": "string"
|
||||
},
|
||||
"isAllNsAccess": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
|
||||
@@ -54,22 +54,43 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/DataDog/datadog-go v4.8.2+incompatible // indirect
|
||||
github.com/DataDog/sketches-go v1.2.1 // indirect
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
|
||||
github.com/Microsoft/go-winio v0.5.1 // indirect
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
|
||||
github.com/beevik/etree v1.1.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 // indirect
|
||||
github.com/containerd/continuity v0.2.1 // indirect
|
||||
github.com/crewjam/httperr v0.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.11.0 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||
github.com/docker/cli v20.10.11+incompatible // indirect
|
||||
github.com/docker/docker v20.10.9+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/duo-labs/webauthn v0.0.0-20210727191636-9f1b88ef44cc // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/eapache/go-resiliency v1.2.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/elastic/go-licenser v0.3.1 // indirect
|
||||
github.com/elastic/go-sysinfo v1.7.1 // indirect
|
||||
github.com/elastic/go-windows v1.0.1 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.2.0 // indirect
|
||||
github.com/go-logr/logr v1.2.0 // indirect
|
||||
github.com/go-openapi/analysis v0.21.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
@@ -78,21 +99,31 @@ require (
|
||||
github.com/go-openapi/spec v0.20.4 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
github.com/gobuffalo/pop/v5 v5.3.4 // indirect
|
||||
github.com/gofrs/uuid v4.1.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2 // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/certificate-transparency-go v1.0.21 // indirect
|
||||
github.com/google/go-cmp v0.5.7 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||
github.com/gorilla/sessions v1.2.1 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743 // indirect
|
||||
github.com/instana/go-sensor v1.34.0 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.10.1-0.20211002123621-290ee79d1e8d // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
@@ -101,6 +132,8 @@ require (
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
||||
github.com/jackc/pgtype v1.8.1 // indirect
|
||||
github.com/jackc/pgx/v4 v4.13.0 // indirect
|
||||
github.com/jandelgado/gcov2lcov v1.0.5 // indirect
|
||||
github.com/jcchavezs/porto v0.3.0 // indirect
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/gofork v1.0.0 // indirect
|
||||
@@ -108,59 +141,116 @@ require (
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.4 // indirect
|
||||
github.com/jmoiron/sqlx v1.3.4 // indirect
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect
|
||||
github.com/jonboulle/clockwork v0.2.2 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
||||
github.com/klauspost/compress v1.14.4 // indirect
|
||||
github.com/knadh/koanf v1.3.0 // indirect
|
||||
github.com/lib/pq v1.10.3 // indirect
|
||||
github.com/looplab/fsm v0.3.0 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/runc v1.0.2 // indirect
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 // indirect
|
||||
github.com/openzipkin/zipkin-go v0.2.5 // indirect
|
||||
github.com/ory/dockertest/v3 v3.8.1 // indirect
|
||||
github.com/ory/go-acc v0.2.6 // indirect
|
||||
github.com/ory/herodot v0.9.12 // indirect
|
||||
github.com/ory/jsonschema/v3 v3.0.4 // indirect
|
||||
github.com/ory/kratos v0.8.2-alpha.1 // indirect
|
||||
github.com/ory/nosurf v1.2.6 // indirect
|
||||
github.com/ory/viper v1.7.5 // indirect
|
||||
github.com/ory/x v0.0.310 // indirect
|
||||
github.com/pborman/uuid v1.2.1 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/philhofer/fwd v1.1.1 // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rs/cors v1.8.0 // indirect
|
||||
github.com/russellhaering/goxmldsig v1.1.1 // indirect
|
||||
github.com/santhosh-tekuri/jsonschema v1.2.4 // indirect
|
||||
github.com/satori/go.uuid v1.2.0 // indirect
|
||||
github.com/seatgeek/logrus-gelf-formatter v0.0.0-20210414080842-5b05eb8ff761 // indirect
|
||||
github.com/segmentio/asm v1.1.3 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/spf13/afero v1.6.0 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/cobra v1.2.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/tidwall/gjson v1.9.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tinylib/msgp v1.1.6 // indirect
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
||||
github.com/uber/jaeger-client-go v2.29.1+incompatible // indirect
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
go.elastic.co/apm v1.14.0 // indirect
|
||||
go.elastic.co/apm/module/apmhttp v1.14.0 // indirect
|
||||
go.elastic.co/apm/module/apmot v1.14.0 // indirect
|
||||
go.elastic.co/fastjson v1.1.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.8.3 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.25.0 // indirect
|
||||
go.opentelemetry.io/otel v1.0.1 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.0.1 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
golang.org/x/tools v0.1.7 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.33.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gorm.io/driver/mysql v1.1.2 // indirect
|
||||
gorm.io/driver/sqlserver v1.2.1 // indirect
|
||||
gorm.io/plugin/dbresolver v1.1.0 // indirect
|
||||
howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect
|
||||
k8s.io/component-base v0.23.4 // indirect
|
||||
k8s.io/klog v1.0.0 // indirect
|
||||
k8s.io/klog/v2 v2.30.0 // indirect
|
||||
|
||||
@@ -128,6 +128,22 @@ func GetNameById(ctx context.Context, db bun.IDB, id uuid.UUID, entity interface
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
func GetNamesByIds(ctx context.Context, db bun.IDB, id []uuid.UUID, entity interface{}) ([]string, error) {
|
||||
names := []string{}
|
||||
if len(id) == 0 {
|
||||
return names, nil
|
||||
}
|
||||
err := db.NewSelect().Column("name").Model(entity).
|
||||
Where("id = (?)", bun.In(id)).
|
||||
Where("trash = ?", false).
|
||||
Scan(ctx, &names)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func Update(ctx context.Context, db bun.IDB, id uuid.UUID, entity interface{}) (interface{}, error) {
|
||||
if _, err := db.NewUpdate().Model(entity).Where("id = ?", id).Exec(ctx); err != nil {
|
||||
return nil, err
|
||||
@@ -147,6 +163,7 @@ func Delete(ctx context.Context, db bun.IDB, id uuid.UUID, entity interface{}) e
|
||||
Model(entity).
|
||||
Column("trash").
|
||||
Where("id = ?", id).
|
||||
Where("trash = false").
|
||||
Set("trash = ?", true).
|
||||
Exec(ctx)
|
||||
return err
|
||||
@@ -157,11 +174,38 @@ func DeleteX(ctx context.Context, db bun.IDB, field string, value interface{}, e
|
||||
Model(entity).
|
||||
Column("trash").
|
||||
Where("? = ?", bun.Ident(field), value).
|
||||
Where("trash = false").
|
||||
Set("trash = ?", true).
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteR delete and returns the changed items
|
||||
func DeleteR(ctx context.Context, db bun.IDB, id uuid.UUID, entity interface{}) error {
|
||||
_, err := db.NewUpdate().
|
||||
Model(entity).
|
||||
Column("trash").
|
||||
Where("id = ?", id).
|
||||
Where("trash = false").
|
||||
Set("trash = ?", true).
|
||||
Returning("*").
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteXR delete with selector and returns the changed items
|
||||
func DeleteXR(ctx context.Context, db bun.IDB, field string, value interface{}, entity interface{}) error {
|
||||
_, err := db.NewUpdate().
|
||||
Model(entity).
|
||||
Column("trash").
|
||||
Where("? = ?", bun.Ident(field), value).
|
||||
Where("trash = false").
|
||||
Set("trash = ?", true).
|
||||
Returning("*").
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// HardDeleteAll deletes all records in a table (primarily for use in scripts)
|
||||
func HardDeleteAll(ctx context.Context, db bun.IDB, entity interface{}) error {
|
||||
_, err := db.NewDelete().
|
||||
|
||||
@@ -129,3 +129,17 @@ func ListFilteredUsers(ctx context.Context, db bun.IDB, users *[]models.KratosId
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func GetUserNamesByIds(ctx context.Context, db bun.IDB, id []uuid.UUID, entity interface{}) ([]string, error) {
|
||||
names := []string{}
|
||||
if len(id) == 0 {
|
||||
return names, nil
|
||||
}
|
||||
err := db.NewSelect().ColumnExpr("traits ->> 'email' as name").Model(entity).
|
||||
Where("id = (?)", bun.In(id)).
|
||||
Scan(ctx, &names)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/RafayLabs/rcloud-base/internal/fixtures"
|
||||
providers "github.com/RafayLabs/rcloud-base/internal/provider/kratos"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/audit"
|
||||
authv3 "github.com/RafayLabs/rcloud-base/pkg/auth/v3"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/common"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/enforcer"
|
||||
@@ -70,6 +71,7 @@ const (
|
||||
relayImageEnv = "RELAY_IMAGE"
|
||||
|
||||
// audit
|
||||
auditFileEnv = "AUDIT_LOG_FILE"
|
||||
esEndPointEnv = "ES_END_POINT"
|
||||
esIndexPrefixEnv = "ES_INDEX_PREFIX"
|
||||
relayAuditESIndexPrefixEnv = "RELAY_AUDITS_ES_INDEX_PREFIX"
|
||||
@@ -110,6 +112,7 @@ var (
|
||||
relayImage string
|
||||
|
||||
// audit
|
||||
auditFile string
|
||||
elasticSearchUrl string
|
||||
esIndexPrefix string
|
||||
relayAuditsESIndexPrefix string
|
||||
@@ -186,6 +189,7 @@ func setup() {
|
||||
viper.SetDefault(esIndexPrefixEnv, "events-core")
|
||||
viper.SetDefault(relayAuditESIndexPrefixEnv, "relay-audits")
|
||||
viper.SetDefault(relayCommandESIndexPrefix, "relay-commands")
|
||||
viper.SetDefault(auditFileEnv, "audit.log")
|
||||
|
||||
// cd relay
|
||||
viper.SetDefault(coreCDRelayUserHostEnv, "*.user.cdrelay.rafay.local:10012")
|
||||
@@ -217,6 +221,7 @@ func setup() {
|
||||
viper.BindEnv(relayImageEnv)
|
||||
viper.BindEnv(schedulerNamespaceEnv)
|
||||
|
||||
viper.BindEnv(auditFileEnv)
|
||||
viper.BindEnv(esEndPointEnv)
|
||||
viper.BindEnv(esIndexPrefixEnv)
|
||||
viper.BindEnv(relayAuditESIndexPrefixEnv)
|
||||
@@ -244,6 +249,7 @@ func setup() {
|
||||
relayImage = viper.GetString(relayImageEnv)
|
||||
schedulerNamespace = viper.GetString(schedulerNamespaceEnv)
|
||||
|
||||
auditFile = viper.GetString(auditFileEnv)
|
||||
elasticSearchUrl = viper.GetString(esEndPointEnv)
|
||||
esIndexPrefix = viper.GetString(esIndexPrefixEnv)
|
||||
relayAuditsESIndexPrefix = viper.GetString(relayAuditESIndexPrefixEnv)
|
||||
@@ -274,6 +280,14 @@ func setup() {
|
||||
|
||||
_log.Infow("printing db", "db", db)
|
||||
|
||||
ao := audit.AuditOptions{
|
||||
LogPath: auditFile,
|
||||
MaxSizeMB: 1,
|
||||
MaxBackups: 10, // Should we let sidecar do rotation?
|
||||
MaxAgeDays: 10, // Make these configurable via env
|
||||
}
|
||||
auditLogger := audit.GetAuditLogger(&ao)
|
||||
|
||||
// authz services
|
||||
gormDb, err := gorm.Open(postgres.New(postgres.Config{
|
||||
Conn: sqldb,
|
||||
@@ -289,9 +303,9 @@ func setup() {
|
||||
|
||||
schedulerPool = schedulerrpc.NewSchedulerPool(schedulerAddr, 5*goruntime.NumCPU())
|
||||
|
||||
ps = service.NewPartnerService(db)
|
||||
os = service.NewOrganizationService(db)
|
||||
pps = service.NewProjectService(db, as)
|
||||
ps = service.NewPartnerService(db, auditLogger)
|
||||
os = service.NewOrganizationService(db, auditLogger)
|
||||
pps = service.NewProjectService(db, as, auditLogger)
|
||||
|
||||
// users and role management services
|
||||
cc := common.CliConfigDownloadData{
|
||||
@@ -303,13 +317,13 @@ func setup() {
|
||||
} else {
|
||||
cc.Profile = "production"
|
||||
}
|
||||
ks = service.NewApiKeyService(db)
|
||||
us = service.NewUserService(providers.NewKratosAuthProvider(kc), db, as, ks, cc)
|
||||
gs = service.NewGroupService(db, as)
|
||||
rs = service.NewRoleService(db, as)
|
||||
ks = service.NewApiKeyService(db, auditLogger)
|
||||
us = service.NewUserService(providers.NewKratosAuthProvider(kc), db, as, ks, cc, auditLogger)
|
||||
gs = service.NewGroupService(db, as, auditLogger)
|
||||
rs = service.NewRoleService(db, as, auditLogger)
|
||||
rrs = service.NewRolepermissionService(db)
|
||||
is = service.NewIdpService(db, apiAddr)
|
||||
oidcs = service.NewOIDCProviderService(db, kratosAddr)
|
||||
is = service.NewIdpService(db, apiAddr, auditLogger)
|
||||
oidcs = service.NewOIDCProviderService(db, kratosAddr, auditLogger)
|
||||
|
||||
//sentry related services
|
||||
bs = service.NewBootstrapService(db)
|
||||
@@ -355,7 +369,7 @@ func setup() {
|
||||
RelayAgentImage: relayImage,
|
||||
}
|
||||
|
||||
cs = service.NewClusterService(db, downloadData, bs)
|
||||
cs = service.NewClusterService(db, downloadData, bs, auditLogger)
|
||||
ms = service.NewMetroService(db)
|
||||
|
||||
notify.Init(cs)
|
||||
|
||||
+28
@@ -315,11 +315,20 @@ GET :host/auth/v3/users
|
||||
Content-Type: application/yaml
|
||||
X-Session-Token: :token
|
||||
|
||||
# Get all users with query options
|
||||
GET :host/auth/v3/users?partner=:partner&organization=:org&q=user&name=john&order_by=email&project=ALL,:project
|
||||
Content-Type: application/yaml
|
||||
X-Session-Token: :token
|
||||
|
||||
# Get single user
|
||||
GET :host/auth/v3/user/:user
|
||||
Content-Type: application/yaml
|
||||
X-Session-Token: :token
|
||||
|
||||
# Get currently logged in user info
|
||||
GET :host/auth/v3/userinfo
|
||||
Content-Type: application/yaml
|
||||
X-Session-Token: :token
|
||||
|
||||
# Delete single user
|
||||
DELETE :host/auth/v3/user/:user
|
||||
@@ -477,6 +486,7 @@ X-Session-Token: :token
|
||||
|
||||
# Audit by project
|
||||
GET :host/event/v1/auditlog?filter.timefrom=now-1h
|
||||
X-Session-Token: :token
|
||||
|
||||
## Partner
|
||||
|
||||
@@ -510,6 +520,24 @@ metadata:
|
||||
spec:
|
||||
active: true
|
||||
|
||||
# Update organization
|
||||
PUT :host/auth/v3/partner/:partner/organization/:org
|
||||
Content-Type: application/yaml
|
||||
X-Session-Token: :token
|
||||
|
||||
metadata:
|
||||
partner: :partner
|
||||
name: :org
|
||||
description: "Very first organizataion"
|
||||
spec:
|
||||
active: true
|
||||
settings:
|
||||
idleLogoutMin: 30
|
||||
lockout:
|
||||
enabled: true
|
||||
period_min: 10
|
||||
attempts: 6
|
||||
|
||||
# List organizations
|
||||
GET :host/auth/v3/partner/:partner/organizations
|
||||
Content-Type: application/yaml
|
||||
|
||||
@@ -32,10 +32,6 @@ CREATE INDEX authsrv_projectaccountresourcerole_project_id_f8a43852 ON authsrv_p
|
||||
|
||||
CREATE INDEX authsrv_projectaccountresourcerole_role_id_a345b16f ON authsrv_projectaccountresourcerole USING btree (role_id);
|
||||
|
||||
ALTER TABLE ONLY authsrv_projectaccountresourcerole
|
||||
ADD CONSTRAINT authsrv_projectaccou_account_id_532ce8df_fk_authsrv_a FOREIGN KEY (account_id)
|
||||
REFERENCES identities(id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
ALTER TABLE ONLY authsrv_projectaccountresourcerole
|
||||
ADD CONSTRAINT authsrv_projectaccou_organization_id_91c5602d_fk_authsrv_o FOREIGN KEY (organization_id)
|
||||
REFERENCES authsrv_organization(id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
@@ -32,10 +32,6 @@ CREATE INDEX authsrv_projectaccountnamespacerole_project_id_66e567ed ON authsrv_
|
||||
|
||||
CREATE INDEX authsrv_projectaccountnamespacerole_role_id_8a5411cc ON authsrv_projectaccountnamespacerole USING btree (role_id);
|
||||
|
||||
ALTER TABLE ONLY authsrv_projectaccountnamespacerole
|
||||
ADD CONSTRAINT authsrv_projectaccou_account_id_4fac0ac2_fk_authsrv_a FOREIGN KEY (account_id)
|
||||
REFERENCES identities(id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
ALTER TABLE ONLY authsrv_projectaccountnamespacerole
|
||||
ADD CONSTRAINT authsrv_projectaccou_organization_id_96c921c9_fk_authsrv_o FOREIGN KEY (organization_id)
|
||||
REFERENCES authsrv_organization(id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
@@ -22,10 +22,6 @@ CREATE INDEX authsrv_groupaccount_name_d17de056 ON authsrv_groupaccount USING bt
|
||||
|
||||
CREATE INDEX authsrv_groupaccount_name_d17de056_like ON authsrv_groupaccount USING btree (name varchar_pattern_ops);
|
||||
|
||||
ALTER TABLE ONLY authsrv_groupaccount
|
||||
ADD CONSTRAINT authsrv_groupaccount_account_id_041e4e98_fk_authsrv_account_id FOREIGN KEY (account_id)
|
||||
REFERENCES identities(id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
ALTER TABLE ONLY authsrv_groupaccount
|
||||
ADD CONSTRAINT authsrv_groupaccount_group_id_c67750ef_fk_authsrv_group_id FOREIGN KEY (group_id)
|
||||
REFERENCES authsrv_group(id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
@@ -29,10 +29,6 @@ CREATE INDEX authsrv_accountresourcerole_partner_id_8e96aff4 ON authsrv_accountr
|
||||
|
||||
CREATE INDEX authsrv_accountresourcerole_role_id_769ec143 ON authsrv_accountresourcerole USING btree (role_id);
|
||||
|
||||
ALTER TABLE ONLY authsrv_accountresourcerole
|
||||
ADD CONSTRAINT authsrv_accountresou_account_id_229069ae_fk_authsrv_a FOREIGN KEY (account_id)
|
||||
REFERENCES identities(id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
ALTER TABLE ONLY authsrv_accountresourcerole
|
||||
ADD CONSTRAINT authsrv_accountresou_organization_id_22bb772c_fk_authsrv_o FOREIGN KEY (organization_id)
|
||||
REFERENCES authsrv_organization(id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
+74
-63
@@ -2,7 +2,6 @@ package audit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -10,7 +9,7 @@ import (
|
||||
|
||||
logv2 "github.com/RafayLabs/rcloud-base/pkg/log"
|
||||
commonv3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
|
||||
"github.com/Shopify/sarama"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
@@ -46,11 +45,12 @@ type EventActorAccount struct {
|
||||
|
||||
// EventActor Event's initiator
|
||||
type EventActor struct {
|
||||
Type string `json:"type"`
|
||||
PartnerID string `json:"partner_id"`
|
||||
OrganizationID string `json:"organization_id"`
|
||||
Account EventActorAccount `json:"account"`
|
||||
Groups []string `json:"groups"`
|
||||
Type string `json:"type"`
|
||||
// Add org and partner id once we have multi-org support
|
||||
// PartnerID string `json:"partner_id"`
|
||||
// OrganizationID string `json:"organization_id"`
|
||||
Account EventActorAccount `json:"account"`
|
||||
Groups []string `json:"groups"`
|
||||
}
|
||||
|
||||
// EventClient Event's client
|
||||
@@ -69,22 +69,19 @@ type EventDetail struct {
|
||||
|
||||
// Event is struct to hold event data
|
||||
type Event struct {
|
||||
Version EventVersion `json:"version"`
|
||||
Category EventCategory `json:"category"`
|
||||
Origin EventOrigin `json:"origin"`
|
||||
Portal string `json:"portal"`
|
||||
Type string `json:"type"`
|
||||
PartnerID string `json:"partner_id"`
|
||||
OrganizationID string `json:"organization_id"`
|
||||
ProjectID string `json:"project_id"`
|
||||
Actor *EventActor `json:"actor"`
|
||||
Client *EventClient `json:"client"`
|
||||
Detail *EventDetail `json:"detail"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Version EventVersion `json:"version"`
|
||||
Category EventCategory `json:"category"`
|
||||
Origin EventOrigin `json:"origin"`
|
||||
Portal string `json:"portal"`
|
||||
Type string `json:"type"`
|
||||
ProjectID string `json:"project_id"`
|
||||
Actor *EventActor `json:"actor"`
|
||||
Client *EventClient `json:"client"`
|
||||
Detail *EventDetail `json:"detail"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
type createEventOptions struct {
|
||||
producer sarama.AsyncProducer
|
||||
version EventVersion
|
||||
origin EventOrigin
|
||||
category EventCategory
|
||||
@@ -98,13 +95,6 @@ type createEventOptions struct {
|
||||
groups []string
|
||||
}
|
||||
|
||||
// WithProducer sets producer for audit event
|
||||
func WithProducer(producer sarama.AsyncProducer) CreateEventOption {
|
||||
return func(opts *createEventOptions) {
|
||||
opts.producer = producer
|
||||
}
|
||||
}
|
||||
|
||||
// WithVersion sets version for audit event
|
||||
func WithVersion(version EventVersion) CreateEventOption {
|
||||
return func(opts *createEventOptions) {
|
||||
@@ -186,18 +176,13 @@ func WithGroups(groups []string) CreateEventOption {
|
||||
type CreateEventOption func(opts *createEventOptions)
|
||||
|
||||
// CreateEvent creates an event
|
||||
func CreateEvent(event *Event, opts ...CreateEventOption) error {
|
||||
func CreateEvent(al *zap.Logger, event *Event, opts ...CreateEventOption) error {
|
||||
|
||||
cOpts := createEventOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(&cOpts)
|
||||
}
|
||||
|
||||
if cOpts.producer == nil {
|
||||
_log.Infow("audit event producer is nil")
|
||||
return fmt.Errorf("audit even producer is nil")
|
||||
}
|
||||
|
||||
t := time.Now()
|
||||
dateArray := strings.Fields(t.String())
|
||||
timestamp := fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d.%06d%s",
|
||||
@@ -209,8 +194,6 @@ func CreateEvent(event *Event, opts ...CreateEventOption) error {
|
||||
event.Category = cOpts.category
|
||||
event.Origin = cOpts.origin
|
||||
|
||||
event.PartnerID = cOpts.partnerID
|
||||
event.OrganizationID = cOpts.organizationID
|
||||
event.ProjectID = cOpts.projectID
|
||||
|
||||
if event.Client == nil {
|
||||
@@ -221,16 +204,7 @@ func CreateEvent(event *Event, opts ...CreateEventOption) error {
|
||||
event.Actor = getActor(cOpts)
|
||||
}
|
||||
|
||||
payload, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
_log.Infow("unable to marshal audit event", "error", err)
|
||||
return err
|
||||
}
|
||||
rawMessage := &sarama.ProducerMessage{
|
||||
Topic: string(cOpts.topic),
|
||||
Value: sarama.ByteEncoder(payload),
|
||||
}
|
||||
cOpts.producer.Input() <- rawMessage
|
||||
go WriteEvent(event, al)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -279,36 +253,25 @@ func getActor(cOpts createEventOptions) *EventActor {
|
||||
Username: cOpts.username,
|
||||
}
|
||||
return &EventActor{
|
||||
Type: "USER",
|
||||
PartnerID: cOpts.partnerID,
|
||||
OrganizationID: cOpts.organizationID,
|
||||
Account: account,
|
||||
Groups: cOpts.groups,
|
||||
Type: "USER",
|
||||
Account: account,
|
||||
Groups: cOpts.groups,
|
||||
}
|
||||
}
|
||||
|
||||
func GetActorFromSessionData(sd *commonv3.SessionData) *EventActor {
|
||||
pid := sd.GetPartner()
|
||||
oid := sd.GetOrganization()
|
||||
accountID := sd.GetAccount()
|
||||
username := sd.GetUsername()
|
||||
account := EventActorAccount{
|
||||
ID: accountID,
|
||||
Username: username,
|
||||
}
|
||||
groups := sd.Groups
|
||||
|
||||
// Set org id to string "null" for users with PARTNER_ADMIN role
|
||||
if oid == "" {
|
||||
oid = "null"
|
||||
}
|
||||
groups := sd.Groups // TODO: get groups (in interceptor?)
|
||||
|
||||
return &EventActor{
|
||||
Type: "USER",
|
||||
PartnerID: pid,
|
||||
OrganizationID: oid,
|
||||
Account: account,
|
||||
Groups: groups,
|
||||
Type: "USER",
|
||||
Account: account,
|
||||
Groups: groups,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,6 +284,15 @@ func GetClientFromRequest(r *http.Request) *EventClient {
|
||||
}
|
||||
}
|
||||
|
||||
func GetClientFromSessionData(sd *commonv3.SessionData) *EventClient {
|
||||
return &EventClient{
|
||||
Type: "BROWSER",
|
||||
IP: sd.GetClientIp(),
|
||||
UserAgent: sd.GetClientUa(),
|
||||
Host: sd.GetClientHost(),
|
||||
}
|
||||
}
|
||||
|
||||
func GetEvent(r *http.Request, sd *commonv3.SessionData, detail *EventDetail, eventType string, projectID string) *Event {
|
||||
event := &Event{
|
||||
Actor: GetActorFromSessionData(sd),
|
||||
@@ -333,3 +305,42 @@ func GetEvent(r *http.Request, sd *commonv3.SessionData, detail *EventDetail, ev
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
func CreateV1Event(al *zap.Logger, sd *commonv3.SessionData, detail *EventDetail, eventType string, projectID string) error {
|
||||
actor := GetActorFromSessionData(sd)
|
||||
client := GetClientFromSessionData(sd)
|
||||
|
||||
if projectID == "" {
|
||||
projectID = "null"
|
||||
}
|
||||
|
||||
event := &Event{
|
||||
Version: VersionV1,
|
||||
Category: AuditCategory,
|
||||
Origin: OriginCore,
|
||||
Actor: actor,
|
||||
Client: client,
|
||||
Detail: detail,
|
||||
Type: eventType,
|
||||
Portal: "OPS", // TODO: What is the portal?
|
||||
ProjectID: projectID,
|
||||
}
|
||||
|
||||
go WriteEvent(event, al)
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteEvent(event *Event, al *zap.Logger) {
|
||||
al.Info(
|
||||
"audit",
|
||||
zap.String("version", string(event.Version)),
|
||||
zap.String("category", string(event.Category)),
|
||||
zap.String("origin", string(event.Origin)),
|
||||
zap.Reflect("actor", event.Actor),
|
||||
zap.Reflect("client", event.Client),
|
||||
zap.Reflect("detail", event.Detail),
|
||||
zap.String("type", event.Type),
|
||||
zap.String("portal", event.Portal),
|
||||
zap.String("project_id", event.ProjectID),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package audit
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
// options holds audit options
|
||||
type AuditOptions struct {
|
||||
LogPath string
|
||||
MaxSizeMB int
|
||||
MaxBackups int
|
||||
MaxAgeDays int
|
||||
}
|
||||
|
||||
func GetAuditLogger(opts *AuditOptions) *zap.Logger {
|
||||
encoder := zapcore.EncoderConfig{
|
||||
TimeKey: "timestamp",
|
||||
EncodeTime: zapcore.RFC3339NanoTimeEncoder,
|
||||
}
|
||||
logger := zap.New(zapcore.NewCore(
|
||||
zapcore.NewJSONEncoder(encoder),
|
||||
zapcore.AddSync(&lumberjack.Logger{
|
||||
Filename: opts.LogPath,
|
||||
MaxSize: opts.MaxSizeMB, // megabytes
|
||||
MaxBackups: opts.MaxBackups,
|
||||
MaxAge: opts.MaxAgeDays, // days
|
||||
}),
|
||||
zap.InfoLevel,
|
||||
))
|
||||
|
||||
return logger
|
||||
}
|
||||
+3
-2
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/RafayLabs/rcloud-base/pkg/service"
|
||||
kclient "github.com/ory/kratos-client-go"
|
||||
"github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/uptrace/bun/dialect/pgdialect"
|
||||
"github.com/uptrace/bun/driver/pgdriver"
|
||||
@@ -40,7 +41,7 @@ type authContext struct {
|
||||
// SetupAuthContext sets up new authContext along with its
|
||||
// dependencies. If the caller already has instances of authContext
|
||||
// fields created then use NewAuthContext instead.
|
||||
func SetupAuthContext() authContext {
|
||||
func SetupAuthContext(auditLogger *zap.Logger) authContext {
|
||||
var (
|
||||
kc *kclient.APIClient
|
||||
kratosScheme string
|
||||
@@ -85,7 +86,7 @@ func SetupAuthContext() authContext {
|
||||
}
|
||||
as := service.NewAuthzService(db, enforcer)
|
||||
|
||||
return authContext{kc: kc, as: as, ks: service.NewApiKeyService(db)}
|
||||
return authContext{kc: kc, as: as, ks: service.NewApiKeyService(db, auditLogger)}
|
||||
}
|
||||
|
||||
func getEnvWithDefault(env, def string) string {
|
||||
|
||||
@@ -59,6 +59,9 @@ func (ac authContext) NewAuthUnaryInterceptor(opt Option) grpc.UnaryServerInterc
|
||||
method string
|
||||
token string
|
||||
cookie string
|
||||
host string
|
||||
ua string
|
||||
ip string
|
||||
)
|
||||
if len(md.Get(gateway.GatewayURL)) != 0 {
|
||||
url = md.Get(gateway.GatewayURL)[0]
|
||||
@@ -72,6 +75,16 @@ func (ac authContext) NewAuthUnaryInterceptor(opt Option) grpc.UnaryServerInterc
|
||||
if len(md.Get("grpcgateway-cookie")) != 0 {
|
||||
cookie = md.Get("grpcgateway-cookie")[0]
|
||||
}
|
||||
if len(md.Get("x-gateway-host")) != 0 {
|
||||
host = md.Get("x-gateway-host")[0]
|
||||
}
|
||||
if len(md.Get("x-gateway-user-agent")) != 0 {
|
||||
ua = md.Get("x-gateway-user-agent")[0]
|
||||
}
|
||||
if len(md.Get("x-gateway-remote-addr")) != 0 {
|
||||
ip = md.Get("x-gateway-remote-addr")[0]
|
||||
}
|
||||
|
||||
acReq := &commonv3.IsRequestAllowedRequest{
|
||||
Url: url,
|
||||
Method: method,
|
||||
@@ -89,7 +102,11 @@ func (ac authContext) NewAuthUnaryInterceptor(opt Option) grpc.UnaryServerInterc
|
||||
s := res.GetStatus()
|
||||
switch s {
|
||||
case commonv3.RequestStatus_RequestAllowed:
|
||||
ctx := context.WithValue(ctx, common.SessionDataKey, res.SessionData)
|
||||
sd := res.SessionData
|
||||
sd.ClientIp = ip
|
||||
sd.ClientHost = host
|
||||
sd.ClientUa = ua
|
||||
ctx := context.WithValue(ctx, common.SessionDataKey, sd)
|
||||
return handler(ctx, req)
|
||||
case commonv3.RequestStatus_RequestMethodOrURLNotAllowed:
|
||||
return nil, status.Error(codes.PermissionDenied, res.GetReason())
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/urfave/negroni"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type authMiddleware struct {
|
||||
@@ -20,9 +21,9 @@ type authMiddleware struct {
|
||||
opt Option
|
||||
}
|
||||
|
||||
func NewAuthMiddleware(opt Option) negroni.Handler {
|
||||
func NewAuthMiddleware(al *zap.Logger, opt Option) negroni.Handler {
|
||||
return &authMiddleware{
|
||||
ac: SetupAuthContext(),
|
||||
ac: SetupAuthContext(al),
|
||||
opt: opt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ var (
|
||||
// ErrInvalidAPIKey is returned when api key is invalid
|
||||
ErrInvalidAPIKey = errors.New("invalid api key")
|
||||
// ErrInvalidSignature is returns when signature is invalid
|
||||
ErrInvalidSignature = errors.New("invaid signature")
|
||||
ErrInvalidSignature = errors.New("invalid signature")
|
||||
)
|
||||
|
||||
func (ac *authContext) IsRequestAllowed(ctx context.Context, httpreq *http.Request, req *commonv3.IsRequestAllowedRequest) (*commonv3.IsRequestAllowedResponse, error) {
|
||||
|
||||
@@ -33,8 +33,8 @@ var rafayGatewayAnnotator = func(ctx context.Context, r *http.Request) metadata.
|
||||
// }(),
|
||||
GatewayAPIKey: r.Header.Get(GatewayAPIKey),
|
||||
GatewayMethod: r.Method,
|
||||
// UserAgent: r.UserAgent(),
|
||||
// Host: r.Host,
|
||||
// RemoteAddr: r.RemoteAddr,
|
||||
UserAgent: r.UserAgent(),
|
||||
Host: r.Host,
|
||||
RemoteAddr: r.RemoteAddr,
|
||||
})
|
||||
}
|
||||
|
||||
+14
-3
@@ -11,6 +11,7 @@ import (
|
||||
rpcv3 "github.com/RafayLabs/rcloud-base/proto/rpc/user"
|
||||
"github.com/google/uuid"
|
||||
"github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -31,11 +32,12 @@ type ApiKeyService interface {
|
||||
// apiKeyService implements ApiKeyService
|
||||
type apiKeyService struct {
|
||||
db *bun.DB
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
// NewApiKeyService return new api key service
|
||||
func NewApiKeyService(db *bun.DB) ApiKeyService {
|
||||
return &apiKeyService{db}
|
||||
func NewApiKeyService(db *bun.DB, al *zap.Logger) ApiKeyService {
|
||||
return &apiKeyService{db, al}
|
||||
}
|
||||
|
||||
func (s *apiKeyService) Create(ctx context.Context, req *rpcv3.ApiKeyRequest) (*models.ApiKey, error) {
|
||||
@@ -49,10 +51,14 @@ func (s *apiKeyService) Create(ctx context.Context, req *rpcv3.ApiKeyRequest) (*
|
||||
Secret: crypto.GenerateSha256Secret(),
|
||||
}
|
||||
|
||||
_, err := dao.Create(ctx, s.db, apikey)
|
||||
entity, err := dao.Create(ctx, s.db, apikey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ak, ok := entity.(*models.Group); ok {
|
||||
CreateApiKeyAuditEvent(ctx, s.al, AuditActionCreate, ak.ID.String())
|
||||
}
|
||||
return apikey, nil
|
||||
}
|
||||
|
||||
@@ -61,6 +67,11 @@ func (s *apiKeyService) Delete(ctx context.Context, req *rpcv3.ApiKeyRequest) (*
|
||||
Set("trash = ?", true).
|
||||
Where("account_id = ?", req.Username).
|
||||
Where("key = ?", req.Id).Exec(ctx)
|
||||
if err != nil {
|
||||
return &rpcv3.DeleteUserResponse{}, err
|
||||
}
|
||||
|
||||
CreateApiKeyAuditEvent(ctx, s.al, AuditActionDelete, req.Id)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,6 @@ func getPrjectIdFromUrlScope(urlScope string) (string, error) {
|
||||
|
||||
func (a *AuditLogService) GetAuditLogByProjects(req *v1.AuditLogSearchRequest) (res *v1.AuditLogSearchResponse, err error) {
|
||||
// No embedding in golang/protoc (https://github.com/golang/protobuf/issues/192)
|
||||
oid := req.GetMetadata().GetOrganization() // TODO: these are to be filled in by authinterceptor
|
||||
pid := req.GetMetadata().GetPartner()
|
||||
err = validateQueryString(req.GetFilter().QueryString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -72,16 +70,7 @@ func (a *AuditLogService) GetAuditLogByProjects(req *v1.AuditLogSearchRequest) (
|
||||
"query": map[string]interface{}{
|
||||
"bool": map[string]interface{}{
|
||||
"must": []map[string]interface{}{
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"organization_id": oid,
|
||||
},
|
||||
},
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"partner_id": pid,
|
||||
},
|
||||
},
|
||||
// Add org and partner filter once we have to support multi-org
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"category": "AUDIT",
|
||||
|
||||
@@ -0,0 +1,426 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/RafayLabs/rcloud-base/internal/dao"
|
||||
"github.com/RafayLabs/rcloud-base/internal/models"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/audit"
|
||||
systemv3 "github.com/RafayLabs/rcloud-base/proto/types/systempb/v3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
AuditActionCreate = "create"
|
||||
AuditActionDelete = "delete"
|
||||
AuditActionUpdate = "update"
|
||||
)
|
||||
|
||||
func CreateUserAuditEvent(ctx context.Context, al *zap.Logger, db bun.IDB, action string, name string, id uuid.UUID, rolesBefore, rolesAfter, groupsBefore, groupsAfter []uuid.UUID) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("User %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"username": name,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("user.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
|
||||
cr, _, dr := diffu(rolesBefore, rolesAfter)
|
||||
ncr, err := dao.GetNamesByIds(ctx, db, cr, &models.Role{})
|
||||
if err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
ndr, err := dao.GetNamesByIds(ctx, db, dr, &models.Role{})
|
||||
if err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
for _, r := range ncr {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Role %s added to user %s", r, name),
|
||||
Meta: map[string]string{
|
||||
"username": name,
|
||||
"roles_name": r, // TODO: add info like namespace and project
|
||||
},
|
||||
}
|
||||
// user.role.created is user.project.created in rcloud
|
||||
if err := audit.CreateV1Event(al, sd, detail, "user.role.created", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range ndr {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Role %s deleted from user %s", r, name),
|
||||
Meta: map[string]string{
|
||||
"username": name,
|
||||
"role_name": r,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, "user.role.deleted", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
cg, _, dg := diffu(groupsBefore, rolesAfter)
|
||||
ncg, err := dao.GetNamesByIds(ctx, db, cg, &models.Group{})
|
||||
if err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
ndg, err := dao.GetNamesByIds(ctx, db, dg, &models.Group{})
|
||||
if err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
for _, g := range ncg {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("User %s added to group %s", name, g),
|
||||
Meta: map[string]string{
|
||||
"username": name,
|
||||
"group_name": g,
|
||||
},
|
||||
}
|
||||
// user.role.created is user.project.created in rcloud
|
||||
if err := audit.CreateV1Event(al, sd, detail, "user.group.created", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, g := range ndg {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("User %s added to group %s", name, g),
|
||||
Meta: map[string]string{
|
||||
"username": name,
|
||||
"group_name": g,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, "user.group.deleted", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CreateGroupAuditEvent(ctx context.Context, al *zap.Logger, db bun.IDB, action string, name string, id uuid.UUID, usersBefore, usersAfter, rolesBefore, rolesAfter []uuid.UUID) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Group %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"group_name": name,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("group.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
|
||||
cu, _, du := diffu(usersBefore, usersAfter)
|
||||
|
||||
cun, err := dao.GetUserNamesByIds(ctx, db, cu, &models.KratosIdentities{})
|
||||
if err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
dun, err := dao.GetUserNamesByIds(ctx, db, du, &models.KratosIdentities{})
|
||||
if err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
|
||||
for _, u := range cun {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("User %s added to group %s", u, name),
|
||||
Meta: map[string]string{
|
||||
"group_name": name,
|
||||
"username": u,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, "group.user.created", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, u := range dun {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("User %s deleted from group %s", u, name),
|
||||
Meta: map[string]string{
|
||||
"group_name": name,
|
||||
"username": u,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, "group.user.deleted", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
cr, _, dr := diffu(rolesBefore, rolesAfter)
|
||||
ncr, err := dao.GetNamesByIds(ctx, db, cr, &models.Role{})
|
||||
if err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
ndr, err := dao.GetNamesByIds(ctx, db, dr, &models.Role{})
|
||||
if err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
for _, r := range ncr {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Role %s added to group %s", r, name),
|
||||
Meta: map[string]string{
|
||||
"group_name": name,
|
||||
"roles_name": r, // TODO: add info like namespace and project
|
||||
},
|
||||
}
|
||||
// group.role.created is group.project.created in rcloud
|
||||
if err := audit.CreateV1Event(al, sd, detail, "group.role.created", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range ndr {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Role %s deleted from group %s", r, name),
|
||||
Meta: map[string]string{
|
||||
"group_name": name,
|
||||
"role_name": r,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, "group.role.deleted", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func CreateRoleAuditEvent(ctx context.Context, al *zap.Logger, action string, name string, id uuid.UUID, permissions []string) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Role %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"role_name": name,
|
||||
"permissions": strings.Join(permissions, ","), // TODO: Should we split it into individual ones?
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("role.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateProjectAuditEvent(ctx context.Context, al *zap.Logger, action string, name string, id uuid.UUID) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Project %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"project_name": name,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("project.%s.success", action), id.String()); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
func CreatePartnerAuditEvent(ctx context.Context, al *zap.Logger, action string, name string, id uuid.UUID) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Partner %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"partner_name": name,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("partner.%s.success", action), id.String()); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateOrganizationAuditEvent(ctx context.Context, al *zap.Logger, action string, name string, id uuid.UUID, settingsBefore, settingsAfter *systemv3.OrganizationSettings) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Organization %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"organization_name": name,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("organization.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
|
||||
if settingsBefore == nil && settingsAfter == nil {
|
||||
return
|
||||
}
|
||||
|
||||
bavail := settingsBefore != nil && settingsAfter != nil
|
||||
if !bavail || settingsBefore.IdleLogoutMin != settingsAfter.IdleLogoutMin {
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Idel logout settings updated for organization %s", name),
|
||||
Meta: map[string]string{
|
||||
"organization_name": name,
|
||||
},
|
||||
}
|
||||
|
||||
if settingsAfter != nil {
|
||||
detail.Meta = map[string]string{
|
||||
"organization_name": name,
|
||||
"idle_logout_min": string(settingsAfter.IdleLogoutMin),
|
||||
}
|
||||
}
|
||||
|
||||
if err := audit.CreateV1Event(al, sd, detail, "organization.idle.timeout.settings.updated", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
bavail = bavail && settingsBefore.Lockout != nil && settingsAfter.Lockout != nil
|
||||
|
||||
if !bavail ||
|
||||
settingsBefore.Lockout.Enabled != settingsAfter.Lockout.Enabled ||
|
||||
settingsBefore.Lockout.PeriodMin != settingsAfter.Lockout.PeriodMin ||
|
||||
settingsBefore.Lockout.Attempts != settingsAfter.Lockout.Attempts {
|
||||
|
||||
enabled := "false"
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Lockout settings updated for organization %s", name),
|
||||
Meta: map[string]string{
|
||||
"organization_name": name,
|
||||
},
|
||||
}
|
||||
|
||||
if settingsAfter != nil && settingsAfter.Lockout != nil {
|
||||
if settingsAfter.Lockout.Enabled {
|
||||
enabled = "true"
|
||||
}
|
||||
detail.Meta = map[string]string{
|
||||
"organization_name": name,
|
||||
"lockout_enabled": enabled,
|
||||
"lockout_period_min": string(settingsAfter.Lockout.PeriodMin),
|
||||
"lockout_attempts": string(settingsAfter.Lockout.Attempts),
|
||||
}
|
||||
}
|
||||
|
||||
if err := audit.CreateV1Event(al, sd, detail, "organization.lockout.settings.updated", ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CreateIdpAuditEvent(ctx context.Context, al *zap.Logger, action string, name string, id uuid.UUID) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Idp %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"idp_name": name,
|
||||
},
|
||||
}
|
||||
// idp.create.success is idp.config.created in rcloud
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("idp.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateOidcAuditEvent(ctx context.Context, al *zap.Logger, action string, name string, id uuid.UUID) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Oidc %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"oidc_name": name,
|
||||
},
|
||||
}
|
||||
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("oidc.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateApiKeyAuditEvent(ctx context.Context, al *zap.Logger, action string, id string) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("ApiKey %s %sd", id, action),
|
||||
Meta: map[string]string{
|
||||
"apikey": id,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("apikey.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateClusterAuditEvent(ctx context.Context, al *zap.Logger, action string, name string, id uuid.UUID) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Cluster %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"cluster_name": name,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("cluster.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: figure out how this is to be added
|
||||
func CreateLocationAuditEvent(ctx context.Context, al *zap.Logger, action string, name string, id uuid.UUID) {
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
_log.Warn("unable to create audit event: could not fetch info from context")
|
||||
return
|
||||
}
|
||||
|
||||
detail := &audit.EventDetail{
|
||||
Message: fmt.Sprintf("Location %s %sd", name, action),
|
||||
Meta: map[string]string{
|
||||
"location_name": name,
|
||||
},
|
||||
}
|
||||
if err := audit.CreateV1Event(al, sd, detail, fmt.Sprintf("location.%s.success", action), ""); err != nil {
|
||||
_log.Warn("unable to create audit event", err)
|
||||
}
|
||||
}
|
||||
+30
-21
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
bun "github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/driver/pgdriver"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -93,14 +94,15 @@ type clusterService struct {
|
||||
downloadData common.DownloadData
|
||||
clusterHandlers []event.Handler
|
||||
bs BootstrapService
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
// NewClusterService return new cluster service
|
||||
func NewClusterService(db *bun.DB, data *common.DownloadData, bs BootstrapService) ClusterService {
|
||||
return &clusterService{db: db, downloadData: *data, bs: bs}
|
||||
func NewClusterService(db *bun.DB, data *common.DownloadData, bs BootstrapService, al *zap.Logger) ClusterService {
|
||||
return &clusterService{db: db, downloadData: *data, bs: bs, al: al}
|
||||
}
|
||||
|
||||
func (es *clusterService) Create(ctx context.Context, cluster *infrav3.Cluster) (*infrav3.Cluster, error) {
|
||||
func (s *clusterService) Create(ctx context.Context, cluster *infrav3.Cluster) (*infrav3.Cluster, error) {
|
||||
var errormsg string
|
||||
if cluster.Metadata.Project == "" {
|
||||
cluster.Status = &commonv3.Status{
|
||||
@@ -112,7 +114,7 @@ func (es *clusterService) Create(ctx context.Context, cluster *infrav3.Cluster)
|
||||
}
|
||||
|
||||
var proj models.Project
|
||||
_, err := dao.GetByName(ctx, es.db, cluster.Metadata.Project, &proj)
|
||||
_, err := dao.GetByName(ctx, s.db, cluster.Metadata.Project, &proj)
|
||||
if err != nil {
|
||||
return &infrav3.Cluster{}, err
|
||||
}
|
||||
@@ -155,7 +157,7 @@ func (es *clusterService) Create(ctx context.Context, cluster *infrav3.Cluster)
|
||||
return cluster, fmt.Errorf(errormsg)
|
||||
}
|
||||
|
||||
clusterPresent, err := dao.GetByNamePartnerOrg(ctx, es.db, cluster.Metadata.Name, uuid.NullUUID{UUID: proj.PartnerId, Valid: true},
|
||||
clusterPresent, err := dao.GetByNamePartnerOrg(ctx, s.db, cluster.Metadata.Name, uuid.NullUUID{UUID: proj.PartnerId, Valid: true},
|
||||
uuid.NullUUID{UUID: proj.OrganizationId, Valid: true}, &models.Cluster{})
|
||||
if err != nil && err.Error() == "sql: no rows in result set" {
|
||||
_log.Infof("Skipping as first time cluster create ")
|
||||
@@ -166,7 +168,7 @@ func (es *clusterService) Create(ctx context.Context, cluster *infrav3.Cluster)
|
||||
|
||||
metro := &models.Metro{}
|
||||
if cluster.Spec.Metro != nil && cluster.Spec.Metro.Name != "" {
|
||||
if mdb, err := dao.GetByNamePartnerOrg(ctx, es.db, cluster.Spec.Metro.Name, uuid.NullUUID{UUID: proj.PartnerId, Valid: true}, uuid.NullUUID{UUID: uuid.Nil, Valid: false}, metro); err != nil {
|
||||
if mdb, err := dao.GetByNamePartnerOrg(ctx, s.db, cluster.Spec.Metro.Name, uuid.NullUUID{UUID: proj.PartnerId, Valid: true}, uuid.NullUUID{UUID: uuid.Nil, Valid: false}, metro); err != nil {
|
||||
errormsg = "Invalid cluster location, provide a valid metro name"
|
||||
cluster.Status = &commonv3.Status{
|
||||
ConditionType: "Create",
|
||||
@@ -235,7 +237,7 @@ func (es *clusterService) Create(ctx context.Context, cluster *infrav3.Cluster)
|
||||
|
||||
cluster.Spec.ClusterData.Health = infrav3.Health_EDGE_IGNORE
|
||||
|
||||
tx, err := es.db.BeginTx(ctx, &sql.TxOptions{})
|
||||
tx, err := s.db.BeginTx(ctx, &sql.TxOptions{})
|
||||
if err != nil {
|
||||
return &infrav3.Cluster{}, err
|
||||
}
|
||||
@@ -263,10 +265,10 @@ func (es *clusterService) Create(ctx context.Context, cluster *infrav3.Cluster)
|
||||
}
|
||||
_log.Infow("Created the cluster: ", "Cluster", edb)
|
||||
|
||||
clusterResp := es.prepareClusterResponse(ctx, cluster, edb, metro, pcList, true)
|
||||
clusterResp := s.prepareClusterResponse(ctx, cluster, edb, metro, pcList, true)
|
||||
|
||||
if clusterGeneration == constants.Cluster_V2 && edb.PartnerId != uuid.Nil && edb.OrganizationId != uuid.Nil {
|
||||
operatorSpecStr, err := clstrutil.GetClusterOperatorYaml(ctx, &es.downloadData, clusterResp)
|
||||
operatorSpecStr, err := clstrutil.GetClusterOperatorYaml(ctx, &s.downloadData, clusterResp)
|
||||
if err != nil {
|
||||
_log.Errorw("Error downloading v2 cluster operator yaml", "Error", err)
|
||||
return &infrav3.Cluster{}, err
|
||||
@@ -305,10 +307,11 @@ func (es *clusterService) Create(ctx context.Context, cluster *infrav3.Cluster)
|
||||
ID: edb.ID.String(),
|
||||
}
|
||||
|
||||
for _, h := range es.clusterHandlers {
|
||||
for _, h := range s.clusterHandlers {
|
||||
h.OnChange(ev)
|
||||
}
|
||||
|
||||
CreateClusterAuditEvent(ctx, s.al, AuditActionCreate, clusterResp.GetMetadata().GetName(), edb.ID)
|
||||
return clusterResp, nil
|
||||
}
|
||||
|
||||
@@ -472,7 +475,7 @@ func (s *clusterService) prepareClusterResponse(ctx context.Context, clstr *infr
|
||||
return clstr
|
||||
}
|
||||
|
||||
func (cs *clusterService) Update(ctx context.Context, cluster *infrav3.Cluster) (*infrav3.Cluster, error) {
|
||||
func (s *clusterService) Update(ctx context.Context, cluster *infrav3.Cluster) (*infrav3.Cluster, error) {
|
||||
|
||||
var errormsg string
|
||||
|
||||
@@ -485,7 +488,7 @@ func (cs *clusterService) Update(ctx context.Context, cluster *infrav3.Cluster)
|
||||
return cluster, fmt.Errorf("invalid cluster data, name is missing")
|
||||
}
|
||||
|
||||
edb, err := dao.GetByName(ctx, cs.db, cluster.Metadata.Name, &models.Cluster{})
|
||||
edb, err := dao.GetByName(ctx, s.db, cluster.Metadata.Name, &models.Cluster{})
|
||||
if err != nil {
|
||||
return &infrav3.Cluster{}, fmt.Errorf(errormsg)
|
||||
}
|
||||
@@ -532,7 +535,7 @@ func (cs *clusterService) Update(ctx context.Context, cluster *infrav3.Cluster)
|
||||
if cluster.Spec.Metro != nil && cdb.MetroId.String() != cluster.Spec.Metro.Id {
|
||||
metro := &models.Metro{}
|
||||
if cluster.Spec.Metro.Name != "" {
|
||||
if mdb, err := dao.GetByNamePartnerOrg(ctx, cs.db, cluster.Spec.Metro.Name, uuid.NullUUID{UUID: pid, Valid: true}, uuid.NullUUID{UUID: uuid.Nil, Valid: false}, metro); err != nil {
|
||||
if mdb, err := dao.GetByNamePartnerOrg(ctx, s.db, cluster.Spec.Metro.Name, uuid.NullUUID{UUID: pid, Valid: true}, uuid.NullUUID{UUID: uuid.Nil, Valid: false}, metro); err != nil {
|
||||
errormsg = "Invalid cluster location, provide a valid metro name"
|
||||
cluster.Status = &commonv3.Status{
|
||||
ConditionType: "Update",
|
||||
@@ -567,12 +570,12 @@ func (cs *clusterService) Update(ctx context.Context, cluster *infrav3.Cluster)
|
||||
}
|
||||
|
||||
}
|
||||
err = cdao.UpdateCluster(ctx, cs.db, cdb)
|
||||
err = cdao.UpdateCluster(ctx, s.db, cdb)
|
||||
if err != nil {
|
||||
return &infrav3.Cluster{}, err
|
||||
}
|
||||
|
||||
cs.notifyCluster(ctx, cluster)
|
||||
s.notifyCluster(ctx, cluster)
|
||||
|
||||
ev := event.Resource{
|
||||
PartnerID: cluster.Metadata.Partner,
|
||||
@@ -583,19 +586,21 @@ func (cs *clusterService) Update(ctx context.Context, cluster *infrav3.Cluster)
|
||||
ID: cluster.Metadata.Id,
|
||||
}
|
||||
|
||||
for _, h := range cs.clusterHandlers {
|
||||
for _, h := range s.clusterHandlers {
|
||||
h.OnChange(ev)
|
||||
}
|
||||
/*for _, h := range s.placementHandlers {
|
||||
h.OnChange(ev)
|
||||
}*/
|
||||
|
||||
CreateClusterAuditEvent(ctx, s.al, AuditActionUpdate, cluster.GetMetadata().GetName(), cdb.ID)
|
||||
|
||||
return cluster, nil
|
||||
}
|
||||
|
||||
func (cs *clusterService) Delete(ctx context.Context, cluster *infrav3.Cluster) error {
|
||||
func (s *clusterService) Delete(ctx context.Context, cluster *infrav3.Cluster) error {
|
||||
|
||||
cluster, err := cs.Get(ctx, func(qo *commonv3.QueryOptions) {
|
||||
cluster, err := s.Get(ctx, func(qo *commonv3.QueryOptions) {
|
||||
qo.Name = cluster.Metadata.Name
|
||||
qo.Project = cluster.Metadata.Project
|
||||
qo.Extended = true
|
||||
@@ -606,7 +611,7 @@ func (cs *clusterService) Delete(ctx context.Context, cluster *infrav3.Cluster)
|
||||
clusterId := cluster.Metadata.Id
|
||||
projectId := cluster.Metadata.Project
|
||||
|
||||
err = cs.deleteBootstrapAgentForCluster(ctx, cluster)
|
||||
err = s.deleteBootstrapAgentForCluster(ctx, cluster)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -616,7 +621,7 @@ func (cs *clusterService) Delete(ctx context.Context, cluster *infrav3.Cluster)
|
||||
_log.Debugw("setting cluster condition to pending delete", "name", cluster.Metadata.Name, "conditions", cluster.Spec.ClusterData.ClusterStatus.Conditions)
|
||||
clstrutil.SetClusterCondition(cluster, clstrutil.NewClusterDelete(constants.Pending, "deleted"))
|
||||
|
||||
err = cs.UpdateClusterConditionStatus(ctx, cluster)
|
||||
err = s.UpdateClusterConditionStatus(ctx, cluster)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not update cluster %s status to pending delete", cluster.Metadata.Name)
|
||||
}
|
||||
@@ -630,10 +635,14 @@ func (cs *clusterService) Delete(ctx context.Context, cluster *infrav3.Cluster)
|
||||
ID: clusterId,
|
||||
}
|
||||
|
||||
for _, h := range cs.clusterHandlers {
|
||||
for _, h := range s.clusterHandlers {
|
||||
h.OnChange(ev)
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(clusterId)
|
||||
if err == nil {
|
||||
CreateClusterAuditEvent(ctx, s.al, AuditActionDelete, cluster.GetMetadata().GetName(), id)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func TestCreateCluster(t *testing.T) {
|
||||
RelayAgentImage: "rafaysystems/relay:latest",
|
||||
}
|
||||
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db))
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db), getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
cuuid := uuid.New().String()
|
||||
@@ -74,7 +74,7 @@ func TestUpdateCluster(t *testing.T) {
|
||||
RelayAgentImage: "rafaysystems/relay:latest",
|
||||
}
|
||||
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db))
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db), getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
cuuid := uuid.New().String()
|
||||
@@ -108,7 +108,7 @@ func TestSelectCluster(t *testing.T) {
|
||||
RelayAgentImage: "rafaysystems/relay:latest",
|
||||
}
|
||||
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db))
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db), getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
cuuid := uuid.New().String()
|
||||
@@ -142,7 +142,7 @@ func TestGetCluster(t *testing.T) {
|
||||
RelayAgentImage: "rafaysystems/relay:latest",
|
||||
}
|
||||
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db))
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db), getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
cuuid := uuid.New().String()
|
||||
@@ -175,7 +175,7 @@ func TestListCluster(t *testing.T) {
|
||||
RelayAgentImage: "rafaysystems/relay:latest",
|
||||
}
|
||||
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db))
|
||||
ps := NewClusterService(db, downloadData, NewBootstrapService(db), getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
+77
-48
@@ -16,6 +16,7 @@ import (
|
||||
userv3 "github.com/RafayLabs/rcloud-base/proto/types/userpb/v3"
|
||||
"github.com/google/uuid"
|
||||
bun "github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -44,49 +45,66 @@ type GroupService interface {
|
||||
type groupService struct {
|
||||
db *bun.DB
|
||||
azc AuthzService
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
// NewGroupService return new group service
|
||||
func NewGroupService(db *bun.DB, azc AuthzService) GroupService {
|
||||
return &groupService{db: db, azc: azc}
|
||||
func NewGroupService(db *bun.DB, azc AuthzService, al *zap.Logger) GroupService {
|
||||
return &groupService{db: db, azc: azc, al: al}
|
||||
}
|
||||
|
||||
func (s *groupService) deleteGroupRoleRelaitons(ctx context.Context, db bun.IDB, groupId uuid.UUID, group *userv3.Group) (*userv3.Group, error) {
|
||||
// delete previous entries
|
||||
// deleteGroupRoleRelaitons deletes existing group-role relations
|
||||
func (s *groupService) deleteGroupRoleRelaitons(ctx context.Context, db bun.IDB, groupId uuid.UUID, group *userv3.Group) (*userv3.Group, []uuid.UUID, error) {
|
||||
// TODO: single delete command
|
||||
err := dao.DeleteX(ctx, db, "group_id", groupId, &models.GroupRole{})
|
||||
ids := []uuid.UUID{}
|
||||
gr := []models.GroupRole{}
|
||||
err := dao.DeleteXR(ctx, db, "group_id", groupId, &gr)
|
||||
if err != nil {
|
||||
return &userv3.Group{}, err
|
||||
return &userv3.Group{}, nil, err
|
||||
}
|
||||
err = dao.DeleteX(ctx, db, "group_id", groupId, &models.ProjectGroupRole{})
|
||||
if err != nil {
|
||||
return &userv3.Group{}, err
|
||||
for _, r := range gr {
|
||||
ids = append(ids, r.RoleId)
|
||||
}
|
||||
err = dao.DeleteX(ctx, db, "group_id", groupId, &models.ProjectGroupNamespaceRole{})
|
||||
|
||||
pgr := []models.ProjectGroupRole{}
|
||||
err = dao.DeleteXR(ctx, db, "group_id", groupId, &pgr)
|
||||
if err != nil {
|
||||
return &userv3.Group{}, err
|
||||
return &userv3.Group{}, nil, err
|
||||
}
|
||||
for _, r := range pgr {
|
||||
ids = append(ids, r.RoleId)
|
||||
}
|
||||
|
||||
pgnr := []models.ProjectGroupNamespaceRole{}
|
||||
err = dao.DeleteXR(ctx, db, "group_id", groupId, &pgnr)
|
||||
if err != nil {
|
||||
return &userv3.Group{}, nil, err
|
||||
}
|
||||
for _, r := range pgnr {
|
||||
ids = append(ids, r.RoleId)
|
||||
}
|
||||
|
||||
_, err = s.azc.DeletePolicies(ctx, &authzv1.Policy{Sub: "g:" + group.GetMetadata().GetName()})
|
||||
if err != nil {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to delete group-role relations from authz; %v", err)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to delete group-role relations from authz; %v", err)
|
||||
}
|
||||
return group, nil
|
||||
|
||||
return group, ids, nil
|
||||
}
|
||||
|
||||
// Map roles to groups
|
||||
func (s *groupService) createGroupRoleRelations(ctx context.Context, db bun.IDB, group *userv3.Group, ids parsedIds) (*userv3.Group, error) {
|
||||
// TODO: add transactions
|
||||
func (s *groupService) createGroupRoleRelations(ctx context.Context, db bun.IDB, group *userv3.Group, ids parsedIds) (*userv3.Group, []uuid.UUID, error) {
|
||||
projectNamespaceRoles := group.GetSpec().GetProjectNamespaceRoles()
|
||||
|
||||
var pgrs []models.ProjectGroupRole
|
||||
var grs []models.GroupRole
|
||||
var ps []*authzv1.Policy
|
||||
var rids []uuid.UUID
|
||||
for _, pnr := range projectNamespaceRoles {
|
||||
role := pnr.GetRole()
|
||||
entity, err := dao.GetByName(ctx, db, role, &models.Role{})
|
||||
if err != nil {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to find role '%v'", role)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to find role '%v'", role)
|
||||
}
|
||||
var roleId uuid.UUID
|
||||
var roleName string
|
||||
@@ -94,9 +112,10 @@ func (s *groupService) createGroupRoleRelations(ctx context.Context, db bun.IDB,
|
||||
if rle, ok := entity.(*models.Role); ok {
|
||||
roleId = rle.ID
|
||||
roleName = rle.Name
|
||||
rids = append(rids, rle.ID)
|
||||
scope = strings.ToLower(rle.Scope)
|
||||
} else {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to find role '%v'", role)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to find role '%v'", role)
|
||||
}
|
||||
|
||||
project := pnr.GetProject()
|
||||
@@ -122,7 +141,7 @@ func (s *groupService) createGroupRoleRelations(ctx context.Context, db bun.IDB,
|
||||
})
|
||||
case "organization":
|
||||
if org == "" {
|
||||
return &userv3.Group{}, fmt.Errorf("no org name provided for role '%v'", roleName)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("no org name provided for role '%v'", roleName)
|
||||
}
|
||||
gr := models.GroupRole{
|
||||
Trash: false,
|
||||
@@ -142,14 +161,14 @@ func (s *groupService) createGroupRoleRelations(ctx context.Context, db bun.IDB,
|
||||
})
|
||||
case "project":
|
||||
if org == "" {
|
||||
return &userv3.Group{}, fmt.Errorf("no org name provided for role '%v'", roleName)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("no org name provided for role '%v'", roleName)
|
||||
}
|
||||
if project == "" {
|
||||
return &userv3.Group{}, fmt.Errorf("no project name provided for role '%v'", roleName)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("no project name provided for role '%v'", roleName)
|
||||
}
|
||||
projectId, err := dao.GetProjectId(ctx, s.db, project)
|
||||
if err != nil {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to find project '%v'", project)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to find project '%v'", project)
|
||||
}
|
||||
pgr := models.ProjectGroupRole{
|
||||
Trash: false,
|
||||
@@ -174,49 +193,55 @@ func (s *groupService) createGroupRoleRelations(ctx context.Context, db bun.IDB,
|
||||
if len(pgrs) > 0 {
|
||||
_, err := dao.Create(ctx, db, &pgrs)
|
||||
if err != nil {
|
||||
return &userv3.Group{}, err
|
||||
return &userv3.Group{}, nil, err
|
||||
}
|
||||
}
|
||||
if len(grs) > 0 {
|
||||
_, err := dao.Create(ctx, db, &grs)
|
||||
if err != nil {
|
||||
return &userv3.Group{}, err
|
||||
return &userv3.Group{}, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(ps) > 0 {
|
||||
success, err := s.azc.CreatePolicies(ctx, &authzv1.Policies{Policies: ps})
|
||||
if err != nil || !success.Res {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to create mapping in authz; %v", err)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to create mapping in authz; %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return group, nil
|
||||
return group, rids, nil
|
||||
}
|
||||
|
||||
func (s *groupService) deleteGroupAccountRelations(ctx context.Context, db bun.IDB, groupId uuid.UUID, group *userv3.Group) (*userv3.Group, error) {
|
||||
err := dao.DeleteX(ctx, db, "group_id", groupId, &models.GroupAccount{})
|
||||
func (s *groupService) deleteGroupAccountRelations(ctx context.Context, db bun.IDB, groupId uuid.UUID, group *userv3.Group) (*userv3.Group, []uuid.UUID, error) {
|
||||
ga := []models.GroupAccount{}
|
||||
err := dao.DeleteXR(ctx, db, "group_id", groupId, &ga)
|
||||
if err != nil {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to delete user; %v", err)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to remove user from group user; %v", err)
|
||||
}
|
||||
|
||||
_, err = s.azc.DeleteUserGroups(ctx, &authzv1.UserGroup{Grp: "g:" + group.GetMetadata().GetName()})
|
||||
if err != nil {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to delete group-user relations from authz; %v", err)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to delete group-user relations from authz; %v", err)
|
||||
}
|
||||
return group, nil
|
||||
|
||||
ids := []uuid.UUID{}
|
||||
for _, r := range ga {
|
||||
ids = append(ids, r.AccountId)
|
||||
}
|
||||
return group, ids, nil
|
||||
}
|
||||
|
||||
// Update the users(account) mapped to each group
|
||||
func (s *groupService) createGroupAccountRelations(ctx context.Context, db bun.IDB, groupId uuid.UUID, group *userv3.Group) (*userv3.Group, error) {
|
||||
// TODO: add transactions
|
||||
func (s *groupService) createGroupAccountRelations(ctx context.Context, db bun.IDB, groupId uuid.UUID, group *userv3.Group) (*userv3.Group, []uuid.UUID, error) {
|
||||
var grpaccs []models.GroupAccount
|
||||
var ugs []*authzv1.UserGroup
|
||||
var uids []uuid.UUID
|
||||
for _, account := range unique(group.GetSpec().GetUsers()) {
|
||||
// FIXME: do combined lookup
|
||||
entity, err := dao.GetIdByTraits(ctx, db, account, &models.KratosIdentities{})
|
||||
if err != nil {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to find user '%v'", account)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to find user '%v'", account)
|
||||
}
|
||||
if acc, ok := entity.(*models.KratosIdentities); ok {
|
||||
grp := models.GroupAccount{
|
||||
@@ -227,6 +252,7 @@ func (s *groupService) createGroupAccountRelations(ctx context.Context, db bun.I
|
||||
GroupId: groupId,
|
||||
Active: true,
|
||||
}
|
||||
uids = append(uids, acc.ID)
|
||||
grpaccs = append(grpaccs, grp)
|
||||
ugs = append(ugs, &authzv1.UserGroup{
|
||||
Grp: "g:" + group.GetMetadata().GetName(),
|
||||
@@ -235,21 +261,19 @@ func (s *groupService) createGroupAccountRelations(ctx context.Context, db bun.I
|
||||
}
|
||||
}
|
||||
if len(grpaccs) == 0 {
|
||||
return group, nil
|
||||
return group, nil, nil
|
||||
}
|
||||
_, err := dao.Create(ctx, db, &grpaccs)
|
||||
if err != nil {
|
||||
return &userv3.Group{}, err
|
||||
return &userv3.Group{}, nil, err
|
||||
}
|
||||
|
||||
// TODO: revert our db inserts if this fails
|
||||
// Just FYI, the success can be false if we delete the db directly but casbin has it available internally
|
||||
_, err = s.azc.CreateUserGroups(ctx, &authzv1.UserGroups{UserGroups: ugs})
|
||||
if err != nil {
|
||||
return &userv3.Group{}, fmt.Errorf("unable to create mapping in authz; %v", err)
|
||||
return &userv3.Group{}, nil, fmt.Errorf("unable to create mapping in authz; %v", err)
|
||||
}
|
||||
|
||||
return group, nil
|
||||
return group, uids, nil
|
||||
}
|
||||
|
||||
// TODO: move this to utils, make it accept two strings (names)
|
||||
@@ -303,13 +327,13 @@ func (s *groupService) Create(ctx context.Context, group *userv3.Group) (*userv3
|
||||
//update v3 spec
|
||||
if grp, ok := entity.(*models.Group); ok {
|
||||
// we can get previous group using the id, find users/roles from that and delete those
|
||||
group, err = s.createGroupAccountRelations(ctx, tx, grp.ID, group)
|
||||
group, usersAfter, err := s.createGroupAccountRelations(ctx, tx, grp.ID, group)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, err
|
||||
}
|
||||
|
||||
group, err = s.createGroupRoleRelations(ctx, tx, group, parsedIds{Id: grp.ID, Partner: partnerId, Organization: organizationId})
|
||||
group, rolesAfter, err := s.createGroupRoleRelations(ctx, tx, group, parsedIds{Id: grp.ID, Partner: partnerId, Organization: organizationId})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, err
|
||||
@@ -320,9 +344,10 @@ func (s *groupService) Create(ctx context.Context, group *userv3.Group) (*userv3
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
|
||||
CreateGroupAuditEvent(ctx, s.al, s.db, AuditActionCreate, group.GetMetadata().GetName(), grp.ID, []uuid.UUID{}, usersAfter, []uuid.UUID{}, rolesAfter)
|
||||
return group, nil
|
||||
}
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, fmt.Errorf("unable to create group")
|
||||
}
|
||||
|
||||
@@ -423,22 +448,22 @@ func (s *groupService) Update(ctx context.Context, group *userv3.Group) (*userv3
|
||||
}
|
||||
|
||||
// update account/role links
|
||||
group, err = s.deleteGroupAccountRelations(ctx, tx, grp.ID, group)
|
||||
group, usersBefore, err := s.deleteGroupAccountRelations(ctx, tx, grp.ID, group)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, err
|
||||
}
|
||||
group, err = s.createGroupAccountRelations(ctx, tx, grp.ID, group)
|
||||
group, usersAfter, err := s.createGroupAccountRelations(ctx, tx, grp.ID, group)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, err
|
||||
}
|
||||
group, err = s.deleteGroupRoleRelaitons(ctx, tx, grp.ID, group)
|
||||
group, rolesBefore, err := s.deleteGroupRoleRelaitons(ctx, tx, grp.ID, group)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, err
|
||||
}
|
||||
group, err = s.createGroupRoleRelations(ctx, tx, group, parsedIds{Id: grp.ID, Partner: partnerId, Organization: organizationId})
|
||||
group, rolesAfter, err := s.createGroupRoleRelations(ctx, tx, group, parsedIds{Id: grp.ID, Partner: partnerId, Organization: organizationId})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, err
|
||||
@@ -462,6 +487,8 @@ func (s *groupService) Update(ctx context.Context, group *userv3.Group) (*userv3
|
||||
Users: group.Spec.Users, // TODO: update from db resp or no update?
|
||||
ProjectNamespaceRoles: group.Spec.ProjectNamespaceRoles,
|
||||
}
|
||||
|
||||
CreateGroupAuditEvent(ctx, s.al, s.db, AuditActionUpdate, group.GetMetadata().GetName(), grp.ID, usersBefore, usersAfter, rolesBefore, rolesAfter)
|
||||
}
|
||||
|
||||
return group, nil
|
||||
@@ -484,12 +511,12 @@ func (s *groupService) Delete(ctx context.Context, group *userv3.Group) (*userv3
|
||||
return &userv3.Group{}, err
|
||||
}
|
||||
|
||||
group, err = s.deleteGroupRoleRelaitons(ctx, tx, grp.ID, group)
|
||||
group, rolesBefore, err := s.deleteGroupRoleRelaitons(ctx, tx, grp.ID, group)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, err
|
||||
}
|
||||
group, err = s.deleteGroupAccountRelations(ctx, tx, grp.ID, group)
|
||||
group, usersBefore, err := s.deleteGroupAccountRelations(ctx, tx, grp.ID, group)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.Group{}, err
|
||||
@@ -505,6 +532,8 @@ func (s *groupService) Delete(ctx context.Context, group *userv3.Group) (*userv3
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
|
||||
CreateGroupAuditEvent(ctx, s.al, s.db, AuditActionDelete, group.GetMetadata().GetName(), grp.ID, usersBefore, []uuid.UUID{}, rolesBefore, []uuid.UUID{})
|
||||
return group, nil
|
||||
}
|
||||
|
||||
|
||||
+60
-162
@@ -84,16 +84,11 @@ func TestCreateGroupNoUsersNoRoles(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
mock.ExpectQuery(`SELECT "group"."id" FROM "authsrv_group" AS "group" WHERE .organization_id = '` + ouuid + `'. AND .partner_id = '` + puuid + `'. AND .name = 'group-` + guuid + `'.`).
|
||||
WillReturnError(fmt.Errorf("no data available"))
|
||||
|
||||
@@ -120,30 +115,22 @@ func TestCreateGroupDuplicate(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
// Try to recreate
|
||||
addFetchExpectation(mock, "group")
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectQuery(`INSERT INTO "authsrv_group"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(guuid))
|
||||
mock.ExpectCommit()
|
||||
|
||||
group := &userv3.Group{
|
||||
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid, Name: "group-" + guuid},
|
||||
Spec: &userv3.GroupSpec{},
|
||||
}
|
||||
|
||||
// Try to recreate
|
||||
mock.ExpectQuery(`SELECT "group"."id" FROM "authsrv_group" AS "group"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(guuid))
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
|
||||
mock.ExpectBegin()
|
||||
// TODO: more precise checks
|
||||
mock.ExpectQuery(`INSERT INTO "authsrv_group"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(guuid))
|
||||
mock.ExpectCommit()
|
||||
_, err := gs.Create(context.Background(), group)
|
||||
if err == nil {
|
||||
t.Fatal("should not be able to recreate group with same name")
|
||||
@@ -155,10 +142,10 @@ func TestCreateGroupDuplicate(t *testing.T) {
|
||||
func TestCreateGroupWithUsersNoRoles(t *testing.T) {
|
||||
tt := []struct {
|
||||
name string
|
||||
users []string
|
||||
users int
|
||||
}{
|
||||
{"single user", []string{"users-" + uuid.New().String()}},
|
||||
{"multiple users", []string{"users-" + uuid.New().String(), "users-" + uuid.New().String()}},
|
||||
{"single user", 1},
|
||||
{"multiple users", 2},
|
||||
}
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -166,26 +153,22 @@ func TestCreateGroupWithUsersNoRoles(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
// TODO: more precise checks
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
mock.ExpectQuery(`SELECT "group"."id" FROM "authsrv_group" AS "group" WHERE .organization_id = '` + ouuid + `'. AND .partner_id = '` + puuid + `'. AND .name = 'group-` + guuid + `'.`).
|
||||
WillReturnError(fmt.Errorf("no data available"))
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
addUnavailableExpectation(mock, "group", puuid, ouuid, guuid)
|
||||
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectQuery(`INSERT INTO "authsrv_group"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(guuid))
|
||||
for _, u := range tc.users {
|
||||
mock.ExpectQuery(`SELECT "identities"."id" FROM "identities" WHERE .*traits ->> 'email' = '` + u + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuid.New().String(), []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
|
||||
users := []string{}
|
||||
var i int
|
||||
for i = 0; i < tc.users; i++ {
|
||||
user := addUserFetchExpectation(mock)
|
||||
users = append(users, "user-"+user)
|
||||
}
|
||||
mock.ExpectQuery(`INSERT INTO "authsrv_groupaccount"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uuid.New().String()))
|
||||
@@ -193,7 +176,7 @@ func TestCreateGroupWithUsersNoRoles(t *testing.T) {
|
||||
|
||||
group := &userv3.Group{
|
||||
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid, Name: "group-" + guuid},
|
||||
Spec: &userv3.GroupSpec{Users: tc.users},
|
||||
Spec: &userv3.GroupSpec{Users: users},
|
||||
}
|
||||
group, err := gs.Create(context.Background(), group)
|
||||
if err != nil {
|
||||
@@ -201,19 +184,17 @@ func TestCreateGroupWithUsersNoRoles(t *testing.T) {
|
||||
}
|
||||
performGroupBasicChecks(t, group, guuid)
|
||||
for i, ru := range group.Spec.Users {
|
||||
if ru != tc.users[i] {
|
||||
t.Errorf("user id '%v' not found in resource response", tc.users[i])
|
||||
if ru != users[i] {
|
||||
t.Errorf("user id '%v' not found in resource response", users[i])
|
||||
}
|
||||
}
|
||||
performBasicAuthzChecks(t, mazc, 0, 0, 1, 0, 0, 0)
|
||||
performGroupBasicAuthzChecks(t, mazc, guuid, tc.users, []*userv3.ProjectNamespaceRole{})
|
||||
performGroupBasicAuthzChecks(t, mazc, guuid, users, []*userv3.ProjectNamespaceRole{})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateGroupNoUsersWithRoles(t *testing.T) {
|
||||
// projectid := uuid.New().String()
|
||||
// var namespaceid int64 = 7
|
||||
tt := []struct {
|
||||
name string
|
||||
roles []*userv3.ProjectNamespaceRole
|
||||
@@ -234,18 +215,12 @@ func TestCreateGroupNoUsersWithRoles(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
// TODO: more precise checks
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
mock.ExpectQuery(`SELECT "group"."id" FROM "authsrv_group" AS "group" WHERE .organization_id = '` + ouuid + `'. AND .partner_id = '` + puuid + `'. AND .name = 'group-` + guuid + `'.`).
|
||||
WillReturnError(fmt.Errorf("no data available"))
|
||||
|
||||
@@ -314,17 +289,12 @@ func TestCreateGroupWithUsersWithRoles(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
mock.ExpectQuery(`SELECT "group"."id" FROM "authsrv_group" AS "group" WHERE .organization_id = '` + ouuid + `'. AND .partner_id = '` + puuid + `'. AND .name = 'group-` + guuid + `'.`).WithArgs()
|
||||
|
||||
mock.ExpectBegin()
|
||||
@@ -397,36 +367,27 @@ func TestUpdateGroupWithUsersWithRoles(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
// performing update
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
mock.ExpectQuery(`SELECT "group"."id", "group"."name",.* FROM "authsrv_group" AS "group" WHERE .*name = 'group-` + guuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(guuid, "group-"+guuid))
|
||||
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec(`UPDATE "authsrv_groupaccount" AS "groupaccount" SET trash = TRUE WHERE ."group_id" = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
addGroupUserMappingsUpdateExpectation(mock, guuid)
|
||||
for _, u := range tc.users {
|
||||
// addUserFetchExpectation(mock) // TODO: look into this
|
||||
mock.ExpectQuery(`SELECT "identities"."id" FROM "identities" WHERE .*traits ->> 'email' = '` + u + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuid.New().String(), []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
}
|
||||
mock.ExpectQuery(`INSERT INTO "authsrv_groupaccount"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uuid.New().String()))
|
||||
mock.ExpectExec(`UPDATE "authsrv_grouprole" AS "grouprole" SET trash = TRUE WHERE ."group_id" = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_projectgrouprole" AS "projectgrouprole" SET trash = TRUE WHERE ."group_id" = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_projectgroupnamespacerole" AS "projectgroupnamespacerole" SET trash = TRUE WHERE ."group_id" = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
addGroupRoleMappingsUpdateExpectation(mock, guuid)
|
||||
mock.ExpectQuery(`SELECT "resourcerole"."id".* FROM "authsrv_resourcerole" AS "resourcerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name", "scope"}).AddRow(pruuid, "role-name", tc.scope))
|
||||
if tc.roles[0].Project != nil {
|
||||
@@ -470,30 +431,14 @@ func TestGroupDelete(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
mock.ExpectQuery(`SELECT "group"."id", "group"."name", .* FROM "authsrv_group" AS "group" WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(guuid, "group-"+guuid))
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
guuid := addFetchExpectation(mock, "group")
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec(`UPDATE "authsrv_grouprole" AS "grouprole" SET trash = TRUE WHERE ."group_id" = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_projectgrouprole" AS "projectgrouprole" SET trash = TRUE WHERE ."group_id" = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_projectgroupnamespacerole" AS "projectgroupnamespacerole" SET trash = TRUE WHERE ."group_id" = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_groupaccount" AS "groupaccount" SET trash = TRUE WHERE ."group_id" = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_group" AS "group" SET trash = TRUE WHERE .id = '` + guuid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
addGroupRoleMappingsUpdateExpectation(mock, guuid)
|
||||
addGroupUserMappingsUpdateExpectation(mock, guuid)
|
||||
addDeleteExpectation(mock, "group", guuid)
|
||||
mock.ExpectCommit()
|
||||
|
||||
group := &userv3.Group{
|
||||
@@ -510,14 +455,13 @@ func TestGroupDeleteNonExist(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "group"."id", "group"."name", .* FROM "authsrv_group" AS "group" WHERE`).
|
||||
WithArgs().WillReturnError(fmt.Errorf("No data available"))
|
||||
addUnavailableExpectation(mock, "group", puuid, ouuid, guuid)
|
||||
|
||||
group := &userv3.Group{
|
||||
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid, Name: "group-" + guuid},
|
||||
@@ -533,30 +477,16 @@ func TestGroupGetByName(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
uuuid := uuid.New().String()
|
||||
ruuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
mock.ExpectQuery(`SELECT "group"."id", "group"."name", .* FROM "authsrv_group" AS "group" WHERE .*name = 'group-` + guuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(guuid, "group-"+guuid))
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
addFetchByNameExpectation(mock, "group", guuid)
|
||||
mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" JOIN authsrv_groupaccount ON identities.id=authsrv_groupaccount.account_id WHERE .authsrv_groupaccount.group_id = '` + guuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE .authsrv_grouprole.group_id = '` + guuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgroupnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgroupnamespacerole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgroupnamespacerole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
addGroupRoleMappingsFetchExpectation(mock, guuid, puuid)
|
||||
|
||||
group := &userv3.Group{
|
||||
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid, Name: "group-" + guuid},
|
||||
@@ -573,8 +503,8 @@ func TestGroupGetByName(t *testing.T) {
|
||||
if len(group.GetSpec().GetProjectNamespaceRoles()) != 3 {
|
||||
t.Errorf("invalid number of roles returned for user, expected 3; got '%v'", len(group.GetSpec().GetProjectNamespaceRoles()))
|
||||
}
|
||||
if group.GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 9 {
|
||||
t.Errorf("invalid namespace in role returned for user, expected 9; got '%v'", group.GetSpec().GetProjectNamespaceRoles()[2].Namespace)
|
||||
if group.GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 7 {
|
||||
t.Errorf("invalid namespace in role returned for user, expected 7; got '%v'", group.GetSpec().GetProjectNamespaceRoles()[2].Namespace)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +513,7 @@ func TestGroupGetById(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -629,41 +559,25 @@ func TestGroupList(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid1 := uuid.New().String()
|
||||
guuid2 := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
uuuid := uuid.New().String()
|
||||
ruuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
_, _ = addOrgParterFetchExpectation(mock)
|
||||
mock.ExpectQuery(`SELECT "group"."id", "group"."name", .* FROM "authsrv_group" AS "group"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).
|
||||
AddRow(guuid1, "group-"+guuid1).AddRow(guuid2, "group-"+guuid2))
|
||||
|
||||
mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" JOIN authsrv_groupaccount ON identities.id=authsrv_groupaccount.account_id WHERE .authsrv_groupaccount.group_id = '` + guuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgroupnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgroupnamespacerole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgroupnamespacerole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
addGroupRoleMappingsFetchExpectation(mock, guuid1, pruuid)
|
||||
|
||||
mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" JOIN authsrv_groupaccount ON identities.id=authsrv_groupaccount.account_id WHERE .authsrv_groupaccount.group_id = '` + guuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgroupnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgroupnamespacerole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgroupnamespacerole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
addGroupRoleMappingsFetchExpectation(mock, guuid2, pruuid)
|
||||
|
||||
qo := &commonv3.QueryOptions{}
|
||||
grouplist, err := gs.List(context.Background(), query.WithOptions(qo))
|
||||
@@ -686,41 +600,25 @@ func TestGroupListFiltered(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewGroupService(db, &mazc)
|
||||
gs := NewGroupService(db, &mazc, getLogger())
|
||||
|
||||
guuid1 := uuid.New().String()
|
||||
guuid2 := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
uuuid := uuid.New().String()
|
||||
ruuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
puuid, ouuid := addOrgParterFetchExpectation(mock)
|
||||
mock.ExpectQuery(`SELECT "group"."id", "group"."name", .*WHERE .name ILIKE '%filter-query%'. AND .partner_id = '` + puuid + `'. AND .organization_id = '` + ouuid + `'. ORDER BY "email" asc LIMIT 50 OFFSET 20`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).
|
||||
AddRow(guuid1, "group-"+guuid1).AddRow(guuid2, "group-"+guuid2))
|
||||
|
||||
mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" JOIN authsrv_groupaccount ON identities.id=authsrv_groupaccount.account_id WHERE .authsrv_groupaccount.group_id = '` + guuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgroupnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgroupnamespacerole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgroupnamespacerole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
addGroupRoleMappingsFetchExpectation(mock, guuid1, pruuid)
|
||||
|
||||
mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" JOIN authsrv_groupaccount ON identities.id=authsrv_groupaccount.account_id WHERE .authsrv_groupaccount.group_id = '` + guuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgroupnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgroupnamespacerole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgroupnamespacerole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
addGroupRoleMappingsFetchExpectation(mock, guuid2, pruuid)
|
||||
|
||||
qo := &commonv3.QueryOptions{Q: "filter-query", Limit: 50, Offset: 20, OrderBy: "email", Order: "asc"}
|
||||
grouplist, err := gs.List(context.Background(), query.WithOptions(qo))
|
||||
|
||||
+11
-2
@@ -20,6 +20,7 @@ import (
|
||||
systemv3 "github.com/RafayLabs/rcloud-base/proto/types/systempb/v3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -36,10 +37,11 @@ type IdpService interface {
|
||||
type idpService struct {
|
||||
db *bun.DB
|
||||
appHost string
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
func NewIdpService(db *bun.DB, hostUrl string) IdpService {
|
||||
return &idpService{db: db, appHost: hostUrl}
|
||||
func NewIdpService(db *bun.DB, hostUrl string, al *zap.Logger) IdpService {
|
||||
return &idpService{db: db, appHost: hostUrl, al: al}
|
||||
}
|
||||
|
||||
func generateAcsURL(id string, hostUrl string) string {
|
||||
@@ -205,6 +207,9 @@ func (s *idpService) Create(ctx context.Context, idp *systemv3.Idp) (*systemv3.I
|
||||
SpEntityId: acsURL,
|
||||
},
|
||||
}
|
||||
|
||||
CreateIdpAuditEvent(ctx, s.al, AuditActionCreate, rv.GetMetadata().GetName(), entity.Id)
|
||||
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
@@ -381,6 +386,8 @@ func (s *idpService) Update(ctx context.Context, idp *systemv3.Idp) (*systemv3.I
|
||||
SpEntityId: acsURL,
|
||||
},
|
||||
}
|
||||
|
||||
CreateIdpAuditEvent(ctx, s.al, AuditActionUpdate, rv.GetMetadata().GetName(), entity.Id)
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
@@ -452,5 +459,7 @@ func (s *idpService) Delete(ctx context.Context, idp *systemv3.Idp) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
CreateIdpAuditEvent(ctx, s.al, AuditActionDelete, name, entity.Id)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
systemv3 "github.com/RafayLabs/rcloud-base/proto/types/systempb/v3"
|
||||
"github.com/google/uuid"
|
||||
bun "github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
@@ -31,10 +32,11 @@ type OIDCProviderService interface {
|
||||
type oidcProvider struct {
|
||||
db *bun.DB
|
||||
kratosUrl string
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
func NewOIDCProviderService(db *bun.DB, kratosUrl string) OIDCProviderService {
|
||||
return &oidcProvider{db: db, kratosUrl: kratosUrl}
|
||||
func NewOIDCProviderService(db *bun.DB, kratosUrl string, al *zap.Logger) OIDCProviderService {
|
||||
return &oidcProvider{db: db, kratosUrl: kratosUrl, al: al}
|
||||
}
|
||||
|
||||
func generateCallbackUrl(id string, kUrl string) string {
|
||||
@@ -152,6 +154,8 @@ func (s *oidcProvider) Create(ctx context.Context, provider *systemv3.OIDCProvid
|
||||
CallbackUrl: generateCallbackUrl(entity.Id.String(), s.kratosUrl),
|
||||
},
|
||||
}
|
||||
|
||||
CreateOidcAuditEvent(ctx, s.al, AuditActionCreate, rv.GetMetadata().GetName(), entity.Id)
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
@@ -374,6 +378,8 @@ func (s *oidcProvider) Update(ctx context.Context, provider *systemv3.OIDCProvid
|
||||
CallbackUrl: generateCallbackUrl(provider.GetMetadata().GetId(), s.kratosUrl),
|
||||
},
|
||||
}
|
||||
|
||||
CreateOidcAuditEvent(ctx, s.al, AuditActionUpdate, rv.GetMetadata().GetName(), entity.Id)
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
@@ -392,5 +398,7 @@ func (s *oidcProvider) Delete(ctx context.Context, provider *systemv3.OIDCProvid
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
CreateOidcAuditEvent(ctx, s.al, AuditActionDelete, name, entity.Id)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
systemv3 "github.com/RafayLabs/rcloud-base/proto/types/systempb/v3"
|
||||
"github.com/google/uuid"
|
||||
bun "github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -39,11 +40,12 @@ type OrganizationService interface {
|
||||
// organizationService implements OrganizationService
|
||||
type organizationService struct {
|
||||
db *bun.DB
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
// NewOrganizationService return new organization service
|
||||
func NewOrganizationService(db *bun.DB) OrganizationService {
|
||||
return &organizationService{db}
|
||||
func NewOrganizationService(db *bun.DB, al *zap.Logger) OrganizationService {
|
||||
return &organizationService{db, al}
|
||||
}
|
||||
|
||||
func (s *organizationService) Create(ctx context.Context, org *systemv3.Organization) (*systemv3.Organization, error) {
|
||||
@@ -99,6 +101,8 @@ func (s *organizationService) Create(ctx context.Context, org *systemv3.Organiza
|
||||
if createdOrg, ok := entity.(*models.Organization); ok {
|
||||
//update v3 spec
|
||||
org.Metadata.Id = createdOrg.ID.String()
|
||||
|
||||
CreateOrganizationAuditEvent(ctx, s.al, AuditActionCreate, org.GetMetadata().GetName(), createdOrg.ID, nil, org.GetSpec().GetSettings())
|
||||
}
|
||||
|
||||
return org, nil
|
||||
@@ -195,8 +199,11 @@ func (s *organizationService) Update(ctx context.Context, organization *systemv3
|
||||
}
|
||||
|
||||
if org, ok := entity.(*models.Organization); ok {
|
||||
settingsAfter := organization.GetSpec().GetSettings()
|
||||
settingsBefore := systemv3.OrganizationSettings{}
|
||||
_ = json.Unmarshal(org.Settings, &settingsBefore) // ignore any unmarshelling issues
|
||||
|
||||
sb, err := json.MarshalIndent(organization.GetSpec().GetSettings(), "", "\t")
|
||||
sb, err := json.MarshalIndent(settingsAfter, "", "\t")
|
||||
if err != nil {
|
||||
return &systemv3.Organization{}, err
|
||||
}
|
||||
@@ -226,6 +233,8 @@ func (s *organizationService) Update(ctx context.Context, organization *systemv3
|
||||
if err != nil {
|
||||
return &systemv3.Organization{}, err
|
||||
}
|
||||
|
||||
CreateOrganizationAuditEvent(ctx, s.al, AuditActionUpdate, organization.GetMetadata().GetName(), org.ID, &settingsBefore, settingsAfter)
|
||||
}
|
||||
|
||||
return organization, nil
|
||||
@@ -239,7 +248,7 @@ func (s *organizationService) Delete(ctx context.Context, organization *systemv3
|
||||
}
|
||||
|
||||
if org, ok := entity.(*models.Organization); ok {
|
||||
err := dao.Delete(ctx, s.db, org.ID, org)
|
||||
err := dao.DeleteR(ctx, s.db, org.ID, org)
|
||||
if err != nil {
|
||||
return &systemv3.Organization{}, err
|
||||
}
|
||||
@@ -247,6 +256,10 @@ func (s *organizationService) Delete(ctx context.Context, organization *systemv3
|
||||
//update v3 status
|
||||
organization.Metadata.Name = org.Name
|
||||
organization.Metadata.ModifiedAt = timestamppb.New(org.ModifiedAt)
|
||||
|
||||
orgSettings := systemv3.OrganizationSettings{}
|
||||
_ = json.Unmarshal(org.Settings, &orgSettings) // ignore any unmarshelling issues
|
||||
CreateOrganizationAuditEvent(ctx, s.al, AuditActionDelete, organization.GetMetadata().GetName(), org.ID, &orgSettings, nil)
|
||||
}
|
||||
return organization, nil
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ func TestCreateOrganization(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewOrganizationService(db)
|
||||
ps := NewOrganizationService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
@@ -47,7 +47,7 @@ func TestCreateOrganizationDuplicate(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
gs := NewOrganizationService(db)
|
||||
gs := NewOrganizationService(db, getLogger())
|
||||
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
@@ -69,15 +69,15 @@ func TestOrganizationDelete(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewOrganizationService(db)
|
||||
ps := NewOrganizationService(db, getLogger())
|
||||
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "organization"."id", "organization"."name", .* FROM "authsrv_organization" AS "organization" WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(ouuid, "organization-"+ouuid))
|
||||
|
||||
mock.ExpectExec(`UPDATE "authsrv_organization"`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectQuery(`UPDATE "authsrv_organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(ouuid, "organization-"+ouuid))
|
||||
|
||||
organization := &systemv3.Organization{
|
||||
Metadata: &v3.Metadata{Id: ouuid, Name: "organization-" + ouuid},
|
||||
@@ -92,7 +92,7 @@ func TestOrganizationDeleteNonExist(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewOrganizationService(db)
|
||||
ps := NewOrganizationService(db, getLogger())
|
||||
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
@@ -104,7 +104,7 @@ func TestOrganizationDeleteNonExist(t *testing.T) {
|
||||
}
|
||||
_, err := ps.Delete(context.Background(), organization)
|
||||
if err == nil {
|
||||
t.Fatal("deleted non existant organization")
|
||||
t.Fatal("deleted non existent organization")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func TestOrganizationGetByName(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewOrganizationService(db)
|
||||
ps := NewOrganizationService(db, getLogger())
|
||||
|
||||
partuuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
@@ -137,7 +137,7 @@ func TestOrganizationGetById(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewOrganizationService(db)
|
||||
ps := NewOrganizationService(db, getLogger())
|
||||
|
||||
partuuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -162,7 +162,7 @@ func TestOrganizationUpdate(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewOrganizationService(db)
|
||||
ps := NewOrganizationService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
|
||||
+10
-2
@@ -11,6 +11,7 @@ import (
|
||||
systemv3 "github.com/RafayLabs/rcloud-base/proto/types/systempb/v3"
|
||||
"github.com/google/uuid"
|
||||
bun "github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -33,11 +34,12 @@ type PartnerService interface {
|
||||
// partnerService implements PartnerService
|
||||
type partnerService struct {
|
||||
db *bun.DB
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
// NewPartnerService return new partner service
|
||||
func NewPartnerService(db *bun.DB) PartnerService {
|
||||
return &partnerService{db}
|
||||
func NewPartnerService(db *bun.DB, al *zap.Logger) PartnerService {
|
||||
return &partnerService{db, al}
|
||||
}
|
||||
|
||||
func (s *partnerService) Create(ctx context.Context, partner *systemv3.Partner) (*systemv3.Partner, error) {
|
||||
@@ -76,6 +78,8 @@ func (s *partnerService) Create(ctx context.Context, partner *systemv3.Partner)
|
||||
//update v3 spec
|
||||
partner.Metadata.Id = createdPartner.ID.String()
|
||||
partner.Metadata.ModifiedAt = timestamppb.New(createdPartner.ModifiedAt)
|
||||
|
||||
CreatePartnerAuditEvent(ctx, s.al, AuditActionCreate, partner.GetMetadata().GetName(), createdPartner.ID)
|
||||
}
|
||||
|
||||
return partner, nil
|
||||
@@ -242,6 +246,8 @@ func (s *partnerService) Update(ctx context.Context, partner *systemv3.Partner)
|
||||
//update metadata and status
|
||||
partner.Metadata.ModifiedAt = timestamppb.New(part.ModifiedAt)
|
||||
|
||||
CreatePartnerAuditEvent(ctx, s.al, AuditActionUpdate, partner.GetMetadata().GetName(), part.ID)
|
||||
|
||||
}
|
||||
|
||||
return partner, nil
|
||||
@@ -258,6 +264,8 @@ func (s *partnerService) Delete(ctx context.Context, partner *systemv3.Partner)
|
||||
if err != nil {
|
||||
return &systemv3.Partner{}, err
|
||||
}
|
||||
|
||||
CreatePartnerAuditEvent(ctx, s.al, AuditActionDelete, partner.GetMetadata().GetName(), part.ID)
|
||||
return partner, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ func TestCreatePartner(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewPartnerService(db)
|
||||
ps := NewPartnerService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -59,7 +59,7 @@ func TestCreatePartnerDuplicate(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
gs := NewPartnerService(db)
|
||||
gs := NewPartnerService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestPartnerDelete(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewPartnerService(db)
|
||||
ps := NewPartnerService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -104,7 +104,7 @@ func TestPartnerDeleteNonExist(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
gs := NewPartnerService(db)
|
||||
gs := NewPartnerService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -116,7 +116,7 @@ func TestPartnerDeleteNonExist(t *testing.T) {
|
||||
}
|
||||
_, err := gs.Delete(context.Background(), partner)
|
||||
if err == nil {
|
||||
t.Fatal("deleted non existant group")
|
||||
t.Fatal("deleted non existent group")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ func TestPartnerGetByName(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewPartnerService(db)
|
||||
ps := NewPartnerService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -144,7 +144,7 @@ func TestPartnerGetById(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewPartnerService(db)
|
||||
ps := NewPartnerService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -165,7 +165,7 @@ func TestPartnerUpdate(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ps := NewPartnerService(db)
|
||||
ps := NewPartnerService(db, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
|
||||
+12
-5
@@ -8,13 +8,12 @@ import (
|
||||
|
||||
"github.com/RafayLabs/rcloud-base/internal/dao"
|
||||
"github.com/RafayLabs/rcloud-base/internal/models"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/common"
|
||||
authzv1 "github.com/RafayLabs/rcloud-base/proto/types/authz"
|
||||
commonv3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
|
||||
v3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
|
||||
systemv3 "github.com/RafayLabs/rcloud-base/proto/types/systempb/v3"
|
||||
"github.com/google/uuid"
|
||||
bun "github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -44,11 +43,12 @@ type ProjectService interface {
|
||||
type projectService struct {
|
||||
db *bun.DB
|
||||
azc AuthzService
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
// NewProjectService return new project service
|
||||
func NewProjectService(db *bun.DB, azc AuthzService) ProjectService {
|
||||
return &projectService{db: db, azc: azc}
|
||||
func NewProjectService(db *bun.DB, azc AuthzService, al *zap.Logger) ProjectService {
|
||||
return &projectService{db: db, azc: azc, al: al}
|
||||
}
|
||||
|
||||
func (s *projectService) Create(ctx context.Context, project *systemv3.Project) (*systemv3.Project, error) {
|
||||
@@ -105,6 +105,8 @@ func (s *projectService) Create(ctx context.Context, project *systemv3.Project)
|
||||
project.Spec = &systemv3.ProjectSpec{
|
||||
Default: createdProject.Default,
|
||||
}
|
||||
|
||||
CreateProjectAuditEvent(ctx, s.al, AuditActionCreate, project.GetMetadata().GetName(), createdProject.ID)
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
@@ -282,6 +284,8 @@ func (s *projectService) Update(ctx context.Context, project *systemv3.Project)
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
|
||||
CreateProjectAuditEvent(ctx, s.al, AuditActionUpdate, project.GetMetadata().GetName(), proj.ID)
|
||||
}
|
||||
|
||||
return project, nil
|
||||
@@ -324,14 +328,17 @@ func (s *projectService) Delete(ctx context.Context, project *systemv3.Project)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
return &systemv3.Project{}, err
|
||||
}
|
||||
|
||||
CreateProjectAuditEvent(ctx, s.al, AuditActionDelete, project.GetMetadata().GetName(), proj.ID)
|
||||
}
|
||||
|
||||
return project, nil
|
||||
}
|
||||
|
||||
func (s *projectService) List(ctx context.Context, project *systemv3.Project) (*systemv3.ProjectList, error) {
|
||||
sd, ok := ctx.Value(common.SessionDataKey).(*commonv3.SessionData)
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
username := ""
|
||||
if !ok {
|
||||
return &systemv3.ProjectList{}, fmt.Errorf("cannot perform project listing without auth")
|
||||
|
||||
@@ -22,7 +22,7 @@ func TestCreateProject(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
ps := NewProjectService(db, &mazc)
|
||||
ps := NewProjectService(db, &mazc, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
@@ -50,7 +50,7 @@ func TestCreateProjectDuplicate(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
gs := NewProjectService(db, &mazc)
|
||||
gs := NewProjectService(db, &mazc, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -73,7 +73,7 @@ func TestProjectDelete(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
ps := NewProjectService(db, &mazc)
|
||||
ps := NewProjectService(db, &mazc, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -101,7 +101,7 @@ func TestProjectDeleteNonExist(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
ps := NewProjectService(db, &mazc)
|
||||
ps := NewProjectService(db, &mazc, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -113,7 +113,7 @@ func TestProjectDeleteNonExist(t *testing.T) {
|
||||
}
|
||||
_, err := ps.Delete(context.Background(), project)
|
||||
if err == nil {
|
||||
t.Fatal("deleted non existant project")
|
||||
t.Fatal("deleted non existent project")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ func TestProjectGetByName(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
ps := NewProjectService(db, &mazc)
|
||||
ps := NewProjectService(db, &mazc, getLogger())
|
||||
|
||||
partuuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
@@ -166,7 +166,7 @@ func TestProjectGetById(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
ps := NewProjectService(db, &mazc)
|
||||
ps := NewProjectService(db, &mazc, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
@@ -188,7 +188,7 @@ func TestProjectUpdate(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
ps := NewProjectService(db, &mazc)
|
||||
ps := NewProjectService(db, &mazc, getLogger())
|
||||
|
||||
puuid := uuid.New().String()
|
||||
|
||||
|
||||
+20
-11
@@ -14,6 +14,7 @@ import (
|
||||
rolev3 "github.com/RafayLabs/rcloud-base/proto/types/rolepb/v3"
|
||||
"github.com/google/uuid"
|
||||
bun "github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -42,11 +43,12 @@ type RoleService interface {
|
||||
type roleService struct {
|
||||
db *bun.DB
|
||||
azc AuthzService
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
// NewRoleService return new role service
|
||||
func NewRoleService(db *bun.DB, azc AuthzService) RoleService {
|
||||
return &roleService{db: db, azc: azc}
|
||||
func NewRoleService(db *bun.DB, azc AuthzService, al *zap.Logger) RoleService {
|
||||
return &roleService{db: db, azc: azc, al: al}
|
||||
}
|
||||
|
||||
func (s *roleService) getPartnerOrganization(ctx context.Context, db bun.IDB, role *rolev3.Role) (uuid.UUID, uuid.UUID, error) {
|
||||
@@ -166,17 +168,20 @@ func (s *roleService) Create(ctx context.Context, role *rolev3.Role) (*rolev3.Ro
|
||||
tx.Rollback()
|
||||
return &rolev3.Role{}, err
|
||||
}
|
||||
} else {
|
||||
tx.Rollback()
|
||||
return &rolev3.Role{}, fmt.Errorf("unable to create role '%v'", role.GetMetadata().GetName())
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
|
||||
CreateRoleAuditEvent(ctx, s.al, AuditActionCreate, role.GetMetadata().GetName(), createdRole.ID, role.GetSpec().GetRolepermissions())
|
||||
|
||||
return role, nil
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
return role, nil
|
||||
tx.Rollback()
|
||||
return &rolev3.Role{}, fmt.Errorf("unable to create role '%v'", role.GetMetadata().GetName())
|
||||
|
||||
}
|
||||
|
||||
@@ -279,6 +284,8 @@ func (s *roleService) Update(ctx context.Context, role *rolev3.Role) (*rolev3.Ro
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
|
||||
CreateRoleAuditEvent(ctx, s.al, AuditActionUpdate, role.GetMetadata().GetName(), rle.ID, role.GetSpec().GetRolepermissions())
|
||||
return role, nil
|
||||
}
|
||||
return &rolev3.Role{}, fmt.Errorf("unable to update role '%v'", role.GetMetadata().GetName())
|
||||
@@ -321,6 +328,8 @@ func (s *roleService) Delete(ctx context.Context, role *rolev3.Role) (*rolev3.Ro
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
|
||||
CreateRoleAuditEvent(ctx, s.al, AuditActionDelete, role.GetMetadata().GetName(), rle.ID, []string{})
|
||||
return role, nil
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -52,7 +52,7 @@ func TestCreateRole(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -87,7 +87,7 @@ func TestCreateRoleWithPermissions(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -126,7 +126,7 @@ func TestCreateRoleDuplicate(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -160,7 +160,7 @@ func TestUpdateRole(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -201,7 +201,7 @@ func TestRoleDelete(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -234,7 +234,7 @@ func TestRoleDeleteNonExist(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -248,7 +248,7 @@ func TestRoleDeleteNonExist(t *testing.T) {
|
||||
}
|
||||
_, err := rs.Delete(context.Background(), role)
|
||||
if err == nil {
|
||||
t.Error("deleted non existant role")
|
||||
t.Error("deleted non existent role")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -258,7 +258,7 @@ func TestRoleGetByName(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid := uuid.New().String()
|
||||
rruuid := uuid.New().String()
|
||||
@@ -289,7 +289,7 @@ func TestRoleGetById(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid := uuid.New().String()
|
||||
rruuid := uuid.New().String()
|
||||
@@ -316,7 +316,7 @@ func TestRoleList(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
mazc := mockAuthzClient{}
|
||||
rs := NewRoleService(db, &mazc)
|
||||
rs := NewRoleService(db, &mazc, getLogger())
|
||||
|
||||
ruuid1 := uuid.New().String()
|
||||
ruuid2 := uuid.New().String()
|
||||
|
||||
+167
-1
@@ -1,6 +1,24 @@
|
||||
package service
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/audit"
|
||||
"github.com/google/uuid"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func getLogger() *zap.Logger {
|
||||
ao := audit.AuditOptions{
|
||||
LogPath: "stdout",
|
||||
MaxSizeMB: 1,
|
||||
MaxBackups: 10, // Should we let sidecar do rotation?
|
||||
MaxAgeDays: 10, // Make these configurable via env
|
||||
}
|
||||
return audit.GetAuditLogger(&ao)
|
||||
}
|
||||
|
||||
func performBasicAuthzChecks(t *testing.T, mazc mockAuthzClient, cpCount, dpCount, cugCount, dugCount, crpmCount, drpmCount int) {
|
||||
if len(mazc.cp) != cpCount {
|
||||
@@ -37,3 +55,151 @@ func performBasicAuthProviderChecks(t *testing.T, ma mockAuthProvider, cCount, u
|
||||
t.Errorf("unexpected number of calls to Auth Provider Delete; expctex '%v', got '%v'", dCount, len(ma.d))
|
||||
}
|
||||
}
|
||||
|
||||
func idname(uid string, resource string) string {
|
||||
return resource + "-" + uid
|
||||
}
|
||||
|
||||
func idnamea(uid string, resource string) *string {
|
||||
name := resource + "-" + uid
|
||||
return &name
|
||||
}
|
||||
|
||||
func addFetchIdExpectation(mock sqlmock.Sqlmock, resource string) string {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT "` + resource + `"."id" FROM "authsrv_` + resource + `" AS "` + resource + `"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid))
|
||||
return uid
|
||||
}
|
||||
|
||||
func addFetchExpectation(mock sqlmock.Sqlmock, resource string) string {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT "` + resource + `"."id".* FROM "authsrv_` + resource + `" AS "` + resource + `"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(uid, "role-name"))
|
||||
return uid
|
||||
}
|
||||
|
||||
func addFetchByNameExpectation(mock sqlmock.Sqlmock, resource string, uid string) {
|
||||
mock.ExpectQuery(`SELECT "` + resource + `"."id", "` + resource + `"."name", .* FROM "authsrv_` + resource + `" AS "` + resource + `" WHERE .*name = '` + resource + `-` + uid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(uid, resource+"-"+uid))
|
||||
}
|
||||
|
||||
func addDeleteExpectation(mock sqlmock.Sqlmock, resource string, uid string) {
|
||||
mock.ExpectExec(`UPDATE "authsrv_` + resource + `" AS "` + resource + `" SET trash = TRUE WHERE .id = '` + uid).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
}
|
||||
|
||||
func addUnavailableExpectation(mock sqlmock.Sqlmock, resource, partner, org, uid string) {
|
||||
mock.ExpectQuery(`SELECT "` + resource + `"."id" FROM "authsrv_` + resource + `" AS "` + resource + `" WHERE .organization_id = '` + org + `'. AND .partner_id = '` + partner + `'. AND .name = '` + resource + `-` + uid + `'.`).
|
||||
WillReturnError(fmt.Errorf("no data available"))
|
||||
}
|
||||
|
||||
func addParterOrgFetchExpectation(mock sqlmock.Sqlmock) (string, string) {
|
||||
pid := uuid.New().String()
|
||||
oid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(oid))
|
||||
return pid, oid
|
||||
}
|
||||
|
||||
func addOrgParterFetchExpectation(mock sqlmock.Sqlmock) (string, string) {
|
||||
pid := uuid.New().String()
|
||||
oid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(oid))
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pid))
|
||||
return pid, oid
|
||||
}
|
||||
|
||||
func addResourceRoleFetchExpectation(mock sqlmock.Sqlmock, scope string) string {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT "resourcerole"."id".* FROM "authsrv_resourcerole" AS "resourcerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name", "scope"}).AddRow(uid, "role-"+uid, scope))
|
||||
return uid
|
||||
}
|
||||
|
||||
func addGroupUserMappingsUpdateExpectation(mock sqlmock.Sqlmock, group string) {
|
||||
mock.ExpectQuery(`UPDATE "authsrv_groupaccount" AS "groupaccount" SET trash = TRUE WHERE ."group_id" = '` + group + `'. AND .trash = false. RETURNING *`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uuid.New().String()))
|
||||
}
|
||||
|
||||
func addUserGroupMappingsUpdateExpectation(mock sqlmock.Sqlmock, account string) {
|
||||
mock.ExpectQuery(`UPDATE "authsrv_groupaccount" AS "groupaccount" SET trash = TRUE WHERE ."account_id" = '` + account + `'. AND .trash = false. RETURNING *`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uuid.New().String()))
|
||||
}
|
||||
|
||||
func addUserIdFetchExpectation(mock sqlmock.Sqlmock) string {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT "identities"."id" FROM "identities" WHERE .*traits ->> 'email' = 'user-` + uid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uid, []byte(`{"email":"user-`+uid+`", "first_name": "John", "last_name": "Doe", "description": "The OG user."}`)))
|
||||
return uid
|
||||
}
|
||||
|
||||
func addUserFetchExpectation(mock sqlmock.Sqlmock) string {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" WHERE .*traits ->> 'email' = 'user-` + uid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uid, []byte(`{"email":"user-`+uid+`", "first_name": "John", "last_name": "Doe", "description": "The OG user."}`)))
|
||||
return uid
|
||||
}
|
||||
|
||||
func addUsersGroupFetchExpectation(mock sqlmock.Sqlmock, user string) string {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + user + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + uid))
|
||||
return uid
|
||||
}
|
||||
|
||||
func addUserRoleMappingsFetchExpectation(mock sqlmock.Sqlmock, user string, project string) {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + user + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + uid))
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + user + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+uid, "project-"+project))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + user + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+uid, "project-"+project, 7))
|
||||
}
|
||||
|
||||
func addUserRoleMappingsUpdateExpectation(mock sqlmock.Sqlmock, uuuid string) string {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`UPDATE "authsrv_accountresourcerole" AS "accountresourcerole" SET trash = TRUE WHERE ."account_id" = '` + uuuid + `'. AND .trash = false. RETURNING *`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid))
|
||||
mock.ExpectQuery(`UPDATE "authsrv_projectaccountresourcerole" AS "projectaccountresourcerole" SET trash = TRUE WHERE ."account_id" = '` + uuuid + `'. AND .trash = false. RETURNING *`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid))
|
||||
mock.ExpectQuery(`UPDATE "authsrv_projectaccountnamespacerole" AS "projectaccountnamespacerole" SET trash = TRUE WHERE ."account_id" = '` + uuuid + `'. AND .trash = false. RETURNING *`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid))
|
||||
return uid
|
||||
}
|
||||
|
||||
func addGroupRoleMappingsFetchExpectation(mock sqlmock.Sqlmock, group string, project string) {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+uid, "group-"+group))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+uid, "project-"+project))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+uid, "project-"+project, 7))
|
||||
}
|
||||
|
||||
func addGroupRoleMappingsUpdateExpectation(mock sqlmock.Sqlmock, group string) string {
|
||||
uid := uuid.New().String()
|
||||
mock.ExpectQuery(`UPDATE "authsrv_grouprole" AS "grouprole" SET trash = TRUE WHERE ."group_id" = '` + group + `'. AND .trash = false. RETURNING *`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid))
|
||||
mock.ExpectQuery(`UPDATE "authsrv_projectgrouprole" AS "projectgrouprole" SET trash = TRUE WHERE ."group_id" = '` + group + `'. AND .trash = false. RETURNING *`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid))
|
||||
mock.ExpectQuery(`UPDATE "authsrv_projectgroupnamespacerole" AS "projectgroupnamespacerole" SET trash = TRUE WHERE ."group_id" = '` + group + `'. AND .trash = false. RETURNING *`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid))
|
||||
return uid
|
||||
}
|
||||
|
||||
func addSentryLookupExpectation(mock sqlmock.Sqlmock, users []string, partner, org string) {
|
||||
rows := sqlmock.NewRows([]string{"account_id"})
|
||||
for _, u := range users {
|
||||
rows.AddRow(u)
|
||||
}
|
||||
mock.ExpectQuery(`SELECT DISTINCT account_id FROM "sentry_account_permission" AS "sap" WHERE .partner_id = '` + partner + `'. AND .organization_id = '` + org + `'`).
|
||||
WithArgs().WillReturnRows(rows)
|
||||
}
|
||||
|
||||
+83
-55
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
bun "github.com/uptrace/bun"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/RafayLabs/rcloud-base/internal/dao"
|
||||
@@ -54,6 +55,7 @@ type userService struct {
|
||||
azc AuthzService
|
||||
ks ApiKeyService
|
||||
cc common.CliConfigDownloadData
|
||||
al *zap.Logger
|
||||
}
|
||||
|
||||
type userTraits struct {
|
||||
@@ -70,8 +72,8 @@ type parsedIds struct {
|
||||
Organization uuid.UUID
|
||||
}
|
||||
|
||||
func NewUserService(ap providers.AuthProvider, db *bun.DB, azc AuthzService, kss ApiKeyService, cfg common.CliConfigDownloadData) UserService {
|
||||
return &userService{ap: ap, db: db, azc: azc, ks: kss, cc: cfg}
|
||||
func NewUserService(ap providers.AuthProvider, db *bun.DB, azc AuthzService, kss ApiKeyService, cfg common.CliConfigDownloadData, al *zap.Logger) UserService {
|
||||
return &userService{ap: ap, db: db, azc: azc, ks: kss, cc: cfg, al: al}
|
||||
}
|
||||
|
||||
func getUserTraits(traits map[string]interface{}) userTraits {
|
||||
@@ -102,18 +104,18 @@ func getUserTraits(traits map[string]interface{}) userTraits {
|
||||
}
|
||||
|
||||
// Map roles to accounts
|
||||
func (s *userService) createUserRoleRelations(ctx context.Context, db bun.IDB, user *userv3.User, ids parsedIds) (*userv3.User, error) {
|
||||
func (s *userService) createUserRoleRelations(ctx context.Context, db bun.IDB, user *userv3.User, ids parsedIds) (*userv3.User, []uuid.UUID, error) {
|
||||
projectNamespaceRoles := user.GetSpec().GetProjectNamespaceRoles()
|
||||
|
||||
// TODO: add transactions
|
||||
var pars []models.ProjectAccountResourcerole
|
||||
var ars []models.AccountResourcerole
|
||||
var ps []*authzv1.Policy
|
||||
var rids []uuid.UUID
|
||||
for _, pnr := range projectNamespaceRoles {
|
||||
role := pnr.GetRole()
|
||||
entity, err := dao.GetByName(ctx, db, role, &models.Role{})
|
||||
if err != nil {
|
||||
return &userv3.User{}, fmt.Errorf("unable to find role '%v'", role)
|
||||
return &userv3.User{}, nil, fmt.Errorf("unable to find role '%v'", role)
|
||||
}
|
||||
var roleId uuid.UUID
|
||||
var roleName string
|
||||
@@ -121,9 +123,10 @@ func (s *userService) createUserRoleRelations(ctx context.Context, db bun.IDB, u
|
||||
if rle, ok := entity.(*models.Role); ok {
|
||||
roleId = rle.ID
|
||||
roleName = rle.Name
|
||||
rids = append(rids, rle.ID)
|
||||
scope = strings.ToLower(rle.Scope)
|
||||
} else {
|
||||
return &userv3.User{}, fmt.Errorf("unable to find role '%v'", role)
|
||||
return &userv3.User{}, nil, fmt.Errorf("unable to find role '%v'", role)
|
||||
}
|
||||
|
||||
project := pnr.GetProject()
|
||||
@@ -153,7 +156,7 @@ func (s *userService) createUserRoleRelations(ctx context.Context, db bun.IDB, u
|
||||
})
|
||||
case "organization":
|
||||
if org == "" {
|
||||
return &userv3.User{}, fmt.Errorf("no org name provided for role '%v'", roleName)
|
||||
return &userv3.User{}, nil, fmt.Errorf("no org name provided for role '%v'", roleName)
|
||||
}
|
||||
|
||||
ar := models.AccountResourcerole{
|
||||
@@ -178,14 +181,14 @@ func (s *userService) createUserRoleRelations(ctx context.Context, db bun.IDB, u
|
||||
})
|
||||
case "project":
|
||||
if org == "" {
|
||||
return &userv3.User{}, fmt.Errorf("no org name provided for role '%v'", roleName)
|
||||
return &userv3.User{}, nil, fmt.Errorf("no org name provided for role '%v'", roleName)
|
||||
}
|
||||
if project == "" {
|
||||
return &userv3.User{}, fmt.Errorf("no project name provided for role '%v'", roleName)
|
||||
return &userv3.User{}, nil, fmt.Errorf("no project name provided for role '%v'", roleName)
|
||||
}
|
||||
projectId, err := dao.GetProjectId(ctx, db, project)
|
||||
if err != nil {
|
||||
return user, fmt.Errorf("unable to find project '%v'", project)
|
||||
return user, nil, fmt.Errorf("unable to find project '%v'", project)
|
||||
}
|
||||
par := models.ProjectAccountResourcerole{
|
||||
CreatedAt: time.Now(),
|
||||
@@ -210,43 +213,43 @@ func (s *userService) createUserRoleRelations(ctx context.Context, db bun.IDB, u
|
||||
})
|
||||
default:
|
||||
if err != nil {
|
||||
return user, fmt.Errorf("namespace specific roles are not handled")
|
||||
return user, nil, fmt.Errorf("namespace specific roles are not handled")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(pars) > 0 {
|
||||
_, err := dao.Create(ctx, db, &pars)
|
||||
if err != nil {
|
||||
return &userv3.User{}, err
|
||||
return &userv3.User{}, nil, err
|
||||
}
|
||||
}
|
||||
if len(ars) > 0 {
|
||||
_, err := dao.Create(ctx, db, &ars)
|
||||
if err != nil {
|
||||
return &userv3.User{}, err
|
||||
return &userv3.User{}, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(ps) > 0 {
|
||||
success, err := s.azc.CreatePolicies(ctx, &authzv1.Policies{Policies: ps})
|
||||
if err != nil || !success.Res {
|
||||
return &userv3.User{}, fmt.Errorf("unable to create mapping in authz; %v", err)
|
||||
return &userv3.User{}, nil, fmt.Errorf("unable to create mapping in authz; %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return user, rids, nil
|
||||
}
|
||||
|
||||
// Update the groups mapped to each user(account)
|
||||
func (s *userService) createGroupAccountRelations(ctx context.Context, db bun.IDB, userId uuid.UUID, usr *userv3.User) (*userv3.User, error) {
|
||||
// TODO: add transactions
|
||||
func (s *userService) createGroupAccountRelations(ctx context.Context, db bun.IDB, userId uuid.UUID, usr *userv3.User) (*userv3.User, []uuid.UUID, error) {
|
||||
var grpaccs []models.GroupAccount
|
||||
var ugs []*authzv1.UserGroup
|
||||
var ids []uuid.UUID
|
||||
for _, group := range unique(usr.GetSpec().GetGroups()) {
|
||||
// FIXME: do combined lookup
|
||||
entity, err := dao.GetByName(ctx, s.db, group, &models.Group{})
|
||||
if err != nil {
|
||||
return &userv3.User{}, fmt.Errorf("unable to find group '%v'", group)
|
||||
return &userv3.User{}, nil, fmt.Errorf("unable to find group '%v'", group)
|
||||
}
|
||||
if grp, ok := entity.(*models.Group); ok {
|
||||
grp := models.GroupAccount{
|
||||
@@ -257,6 +260,7 @@ func (s *userService) createGroupAccountRelations(ctx context.Context, db bun.ID
|
||||
GroupId: grp.ID,
|
||||
Active: true,
|
||||
}
|
||||
ids = append(ids, grp.ID)
|
||||
grpaccs = append(grpaccs, grp)
|
||||
ugs = append(ugs, &authzv1.UserGroup{
|
||||
Grp: "g:" + group,
|
||||
@@ -265,34 +269,38 @@ func (s *userService) createGroupAccountRelations(ctx context.Context, db bun.ID
|
||||
}
|
||||
}
|
||||
if len(grpaccs) == 0 {
|
||||
return usr, nil
|
||||
return usr, []uuid.UUID{}, nil
|
||||
}
|
||||
_, err := dao.Create(ctx, db, &grpaccs)
|
||||
if err != nil {
|
||||
return &userv3.User{}, err
|
||||
return &userv3.User{}, []uuid.UUID{}, err
|
||||
}
|
||||
|
||||
// TODO: revert our db inserts if this fails
|
||||
// Just FYI, the success can be false if we delete the db directly but casbin has it available internally
|
||||
_, err = s.azc.CreateUserGroups(ctx, &authzv1.UserGroups{UserGroups: ugs})
|
||||
if err != nil {
|
||||
return &userv3.User{}, fmt.Errorf("unable to create mapping in authz; %v", err)
|
||||
return &userv3.User{}, []uuid.UUID{}, fmt.Errorf("unable to create mapping in authz; %v", err)
|
||||
}
|
||||
|
||||
return usr, nil
|
||||
return usr, ids, nil
|
||||
}
|
||||
|
||||
func (s *userService) deleteGroupAccountRelations(ctx context.Context, db bun.IDB, userId uuid.UUID, usr *userv3.User) (*userv3.User, error) {
|
||||
err := dao.DeleteX(ctx, db, "account_id", userId, &models.GroupAccount{})
|
||||
func (s *userService) deleteGroupAccountRelations(ctx context.Context, db bun.IDB, userId uuid.UUID, usr *userv3.User) (*userv3.User, []uuid.UUID, error) {
|
||||
ugs := []models.GroupAccount{}
|
||||
ids := []uuid.UUID{}
|
||||
err := dao.DeleteXR(ctx, db, "account_id", userId, &ugs)
|
||||
if err != nil {
|
||||
return &userv3.User{}, fmt.Errorf("unable to delete user; %v", err)
|
||||
return &userv3.User{}, ids, fmt.Errorf("unable to delete user; %v", err)
|
||||
}
|
||||
|
||||
_, err = s.azc.DeleteUserGroups(ctx, &authzv1.UserGroup{Grp: "u:" + usr.GetMetadata().GetName()})
|
||||
if err != nil {
|
||||
return &userv3.User{}, fmt.Errorf("unable to delete group-user relations from authz; %v", err)
|
||||
return &userv3.User{}, ids, fmt.Errorf("unable to delete group-user relations from authz; %v", err)
|
||||
}
|
||||
return usr, nil
|
||||
|
||||
for _, ug := range ugs {
|
||||
ids = append(ids, ug.GroupId)
|
||||
}
|
||||
return usr, ids, nil
|
||||
}
|
||||
|
||||
// FIXME: make this generic
|
||||
@@ -312,7 +320,6 @@ func (s *userService) getPartnerOrganization(ctx context.Context, db bun.IDB, us
|
||||
}
|
||||
|
||||
func (s *userService) Create(ctx context.Context, user *userv3.User) (*userv3.User, error) {
|
||||
// TODO: restrict endpoint to admin
|
||||
partnerId, organizationId, err := s.getPartnerOrganization(ctx, s.db, user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get partner and org id")
|
||||
@@ -336,13 +343,13 @@ func (s *userService) Create(ctx context.Context, user *userv3.User) (*userv3.Us
|
||||
return &userv3.User{}, err
|
||||
}
|
||||
|
||||
user, err = s.createUserRoleRelations(ctx, tx, user, parsedIds{Id: uid, Partner: partnerId, Organization: organizationId})
|
||||
user, rolesAfter, err := s.createUserRoleRelations(ctx, tx, user, parsedIds{Id: uid, Partner: partnerId, Organization: organizationId})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.User{}, err
|
||||
}
|
||||
|
||||
user, err = s.createGroupAccountRelations(ctx, tx, uuid.MustParse(id), user)
|
||||
user, groupsAfter, err := s.createGroupAccountRelations(ctx, tx, uuid.MustParse(id), user)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.User{}, err
|
||||
@@ -361,6 +368,7 @@ func (s *userService) Create(ctx context.Context, user *userv3.User) (*userv3.Us
|
||||
}
|
||||
user.Spec.RecoveryUrl = &rl
|
||||
|
||||
CreateUserAuditEvent(ctx, s.al, s.db, AuditActionCreate, user.GetMetadata().GetName(), uid, []uuid.UUID{}, rolesAfter, []uuid.UUID{}, groupsAfter)
|
||||
return user, nil
|
||||
}
|
||||
|
||||
@@ -452,10 +460,10 @@ func (s *userService) GetByName(ctx context.Context, user *userv3.User) (*userv3
|
||||
}
|
||||
|
||||
func (s *userService) GetUserInfo(ctx context.Context, user *userv3.User) (*userv3.UserInfo, error) {
|
||||
sd, ok := ctx.Value(common.SessionDataKey).(*commonv3.SessionData)
|
||||
sd, ok := GetSessionDataFromContext(ctx)
|
||||
username := ""
|
||||
if !ok {
|
||||
return &userv3.UserInfo{}, fmt.Errorf("cannot perform project listing without auth")
|
||||
return &userv3.UserInfo{}, fmt.Errorf("cannot get user info without auth")
|
||||
}
|
||||
username = sd.Username
|
||||
|
||||
@@ -517,26 +525,42 @@ func (s *userService) GetUserInfo(ctx context.Context, user *userv3.User) (*user
|
||||
return &userv3.UserInfo{}, fmt.Errorf("unable to get user info")
|
||||
}
|
||||
|
||||
func (s *userService) deleteUserRoleRelations(ctx context.Context, db bun.IDB, userId uuid.UUID, user *userv3.User) error {
|
||||
err := dao.DeleteX(ctx, db, "account_id", userId, &models.AccountResourcerole{})
|
||||
func (s *userService) deleteUserRoleRelations(ctx context.Context, db bun.IDB, userId uuid.UUID, user *userv3.User) ([]uuid.UUID, error) {
|
||||
ids := []uuid.UUID{}
|
||||
|
||||
ar := []models.AccountResourcerole{}
|
||||
err := dao.DeleteXR(ctx, db, "account_id", userId, &ar)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
err = dao.DeleteX(ctx, db, "account_id", userId, &models.ProjectAccountResourcerole{})
|
||||
if err != nil {
|
||||
return err
|
||||
for _, r := range ar {
|
||||
ids = append(ids, r.RoleId)
|
||||
}
|
||||
err = dao.DeleteX(ctx, db, "account_id", userId, &models.ProjectAccountNamespaceRole{})
|
||||
|
||||
par := []models.ProjectAccountResourcerole{}
|
||||
err = dao.DeleteXR(ctx, db, "account_id", userId, &par)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
for _, r := range par {
|
||||
ids = append(ids, r.RoleId)
|
||||
}
|
||||
|
||||
panr := []models.ProjectAccountNamespaceRole{}
|
||||
err = dao.DeleteXR(ctx, db, "account_id", userId, &panr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, r := range panr {
|
||||
ids = append(ids, r.RoleId)
|
||||
}
|
||||
|
||||
_, err = s.azc.DeletePolicies(ctx, &authzv1.Policy{Sub: "u:" + user.GetMetadata().GetName()})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to delete user-role relations from authz; %v", err)
|
||||
return nil, fmt.Errorf("unable to delete user-role relations from authz; %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func (s *userService) Update(ctx context.Context, user *userv3.User) (*userv3.User, error) {
|
||||
@@ -566,25 +590,25 @@ func (s *userService) Update(ctx context.Context, user *userv3.User) (*userv3.Us
|
||||
return &userv3.User{}, err
|
||||
}
|
||||
|
||||
err = s.deleteUserRoleRelations(ctx, tx, usr.ID, user)
|
||||
rolesBefore, err := s.deleteUserRoleRelations(ctx, tx, usr.ID, user)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.User{}, err
|
||||
}
|
||||
|
||||
user, err = s.deleteGroupAccountRelations(ctx, tx, usr.ID, user)
|
||||
user, groupsBefore, err := s.deleteGroupAccountRelations(ctx, tx, usr.ID, user)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.User{}, err
|
||||
}
|
||||
|
||||
user, err = s.createUserRoleRelations(ctx, tx, user, parsedIds{Id: usr.ID, Partner: partnerId, Organization: organizationId})
|
||||
user, rolesAfter, err := s.createUserRoleRelations(ctx, tx, user, parsedIds{Id: usr.ID, Partner: partnerId, Organization: organizationId})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.User{}, err
|
||||
}
|
||||
|
||||
user, err = s.createGroupAccountRelations(ctx, tx, usr.ID, user)
|
||||
user, groupsAfter, err := s.createGroupAccountRelations(ctx, tx, usr.ID, user)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userv3.User{}, err
|
||||
@@ -595,6 +619,8 @@ func (s *userService) Update(ctx context.Context, user *userv3.User) (*userv3.Us
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
|
||||
CreateUserAuditEvent(ctx, s.al, s.db, AuditActionUpdate, user.GetMetadata().GetName(), usr.ID, rolesBefore, rolesAfter, groupsBefore, groupsAfter)
|
||||
return user, nil
|
||||
|
||||
} else {
|
||||
@@ -617,29 +643,31 @@ func (s *userService) Delete(ctx context.Context, user *userv3.User) (*userrpcv3
|
||||
return &userrpcv3.DeleteUserResponse{}, err
|
||||
}
|
||||
|
||||
err = s.deleteUserRoleRelations(ctx, tx, usr.ID, user)
|
||||
rolesBefore, err := s.deleteUserRoleRelations(ctx, tx, usr.ID, user)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userrpcv3.DeleteUserResponse{}, err
|
||||
}
|
||||
|
||||
user, groupsBefore, err := s.deleteGroupAccountRelations(ctx, tx, usr.ID, user)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userrpcv3.DeleteUserResponse{}, fmt.Errorf("unable to delete user; %v", err)
|
||||
}
|
||||
|
||||
err = s.ap.Delete(ctx, usr.ID.String())
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userrpcv3.DeleteUserResponse{}, err
|
||||
}
|
||||
|
||||
err = dao.DeleteX(ctx, tx, "account_id", usr.ID, &models.GroupAccount{})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return &userrpcv3.DeleteUserResponse{}, fmt.Errorf("unable to delete user; %v", err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_log.Warn("unable to commit changes", err)
|
||||
}
|
||||
|
||||
CreateUserAuditEvent(ctx, s.al, s.db, AuditActionDelete, user.GetMetadata().GetName(), usr.ID, rolesBefore, []uuid.UUID{}, groupsBefore, []uuid.UUID{})
|
||||
return &userrpcv3.DeleteUserResponse{}, nil
|
||||
}
|
||||
return &userrpcv3.DeleteUserResponse{}, fmt.Errorf("unable to delete user '%v'", user.Metadata.Name)
|
||||
|
||||
+172
-363
@@ -62,17 +62,10 @@ func TestCreateUser(t *testing.T) {
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{}, getLogger())
|
||||
|
||||
uuuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectCommit()
|
||||
|
||||
@@ -92,25 +85,22 @@ func TestCreateUser(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateUserWithRole(t *testing.T) {
|
||||
pruuid := uuid.New().String()
|
||||
prname := "project-" + pruuid
|
||||
ruuid := uuid.New().String()
|
||||
rname := "project-" + ruuid
|
||||
var namespaceid int64 = 7
|
||||
tt := []struct {
|
||||
name string
|
||||
roles []*userv3.ProjectNamespaceRole
|
||||
role bool
|
||||
project bool
|
||||
namespace bool
|
||||
dbname string
|
||||
scope string
|
||||
shouldfail bool
|
||||
}{
|
||||
{"just role", []*userv3.ProjectNamespaceRole{{Role: rname}}, "authsrv_accountresourcerole", "system", false},
|
||||
{"just role org scope", []*userv3.ProjectNamespaceRole{{Role: rname}}, "authsrv_accountresourcerole", "organization", false},
|
||||
{"just project", []*userv3.ProjectNamespaceRole{{Project: &prname}}, "authsrv_accountrole", "system", true}, // no role creation without role
|
||||
{"just namespace", []*userv3.ProjectNamespaceRole{{Namespace: &namespaceid}}, "authsrv_accountrole", "system", true}, // no role creation without role,
|
||||
{"project and namespace", []*userv3.ProjectNamespaceRole{{Project: &prname, Namespace: &namespaceid}}, "authsrv_accountrole", "system", true}, // no role creation without role,
|
||||
{"project and role", []*userv3.ProjectNamespaceRole{{Project: &prname, Role: rname}}, "authsrv_projectaccountresourcerole", "project", false},
|
||||
{"project role namespace", []*userv3.ProjectNamespaceRole{{Project: &prname, Namespace: &namespaceid, Role: rname}}, "authsrv_projectaccountresourcerole", "project", false},
|
||||
{"just role", true, false, false, "authsrv_accountresourcerole", "system", false},
|
||||
{"just role org scope", true, false, false, "authsrv_accountresourcerole", "organization", false},
|
||||
{"just project", false, true, false, "authsrv_accountrole", "system", true}, // no role creation without role
|
||||
{"just namespace", false, false, true, "authsrv_accountrole", "system", true}, // no role creation without role,
|
||||
{"project and namespace", false, true, true, "authsrv_accountrole", "system", true}, // no role creation without role,
|
||||
{"project and role", true, true, false, "authsrv_projectaccountresourcerole", "project", false},
|
||||
{"project role namespace", true, true, true, "authsrv_projectaccountresourcerole", "project", false},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
@@ -120,24 +110,25 @@ func TestCreateUserWithRole(t *testing.T) {
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{}, getLogger())
|
||||
|
||||
uuuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectQuery(`SELECT "resourcerole"."id".* FROM "authsrv_resourcerole" AS "resourcerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name", "scope"}).AddRow(pruuid, "role-name", tc.scope))
|
||||
if tc.roles[0].Project != nil {
|
||||
mock.ExpectQuery(`SELECT "project"."id" FROM "authsrv_project" AS "project"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pruuid))
|
||||
ruuid := addResourceRoleFetchExpectation(mock, tc.scope)
|
||||
role := &userv3.ProjectNamespaceRole{}
|
||||
if tc.role {
|
||||
role.Role = idname(ruuid, "role")
|
||||
}
|
||||
if tc.project {
|
||||
pruuid := addFetchIdExpectation(mock, "project")
|
||||
role.Project = &pruuid
|
||||
}
|
||||
if tc.namespace {
|
||||
var ns int64 = 7
|
||||
role.Namespace = &ns
|
||||
}
|
||||
mock.ExpectQuery(fmt.Sprintf(`INSERT INTO "%v"`, tc.dbname)).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uuid.New().String()))
|
||||
@@ -145,8 +136,9 @@ func TestCreateUserWithRole(t *testing.T) {
|
||||
|
||||
user := &userv3.User{
|
||||
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid, Name: "user-" + uuuid},
|
||||
Spec: &userv3.UserSpec{ProjectNamespaceRoles: tc.roles},
|
||||
Spec: &userv3.UserSpec{ProjectNamespaceRoles: []*userv3.ProjectNamespaceRole{role}},
|
||||
}
|
||||
|
||||
user, err := us.Create(context.Background(), user)
|
||||
if tc.shouldfail {
|
||||
if err == nil {
|
||||
@@ -175,46 +167,24 @@ func TestUpdateUser(t *testing.T) {
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
|
||||
uuuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
|
||||
pruuid := uuid.New().String()
|
||||
prname := "project-" + pruuid
|
||||
ruuid := uuid.New().String()
|
||||
rname := "project-" + ruuid
|
||||
var namespaceid int64 = 7
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{}, getLogger())
|
||||
|
||||
// performing update
|
||||
mock.ExpectQuery(`SELECT "identities"."id" FROM "identities" WHERE .*traits ->> 'email' = 'user-` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
|
||||
uuuid := addUserIdFetchExpectation(mock)
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec(`UPDATE "authsrv_accountresourcerole" AS "accountresourcerole" SET trash = TRUE WHERE`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_projectaccountresourcerole" AS "projectaccountresourcerole" SET trash = TRUE WHERE`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_projectaccountnamespacerole" AS "projectaccountnamespacerole" SET trash = TRUE WHERE`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_groupaccount" AS "groupaccount" SET trash = TRUE WHERE`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectQuery(`SELECT "resourcerole"."id".* FROM "authsrv_resourcerole" AS "resourcerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name", "scope"}).AddRow(pruuid, "role-name", "project"))
|
||||
mock.ExpectQuery(`SELECT "project"."id" FROM "authsrv_project" AS "project"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pruuid))
|
||||
_ = addUserRoleMappingsUpdateExpectation(mock, uuuid)
|
||||
addUserGroupMappingsUpdateExpectation(mock, uuuid)
|
||||
ruuid := addResourceRoleFetchExpectation(mock, "project")
|
||||
pruuid := addFetchExpectation(mock, "project")
|
||||
mock.ExpectQuery(`INSERT INTO "authsrv_projectaccountresourcerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uuid.New().String()))
|
||||
mock.ExpectCommit()
|
||||
|
||||
var ns int64 = 7
|
||||
user := &userv3.User{
|
||||
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid, Name: "user-" + uuuid},
|
||||
Spec: &userv3.UserSpec{ProjectNamespaceRoles: []*userv3.ProjectNamespaceRole{{Project: &prname, Namespace: &namespaceid, Role: rname}}},
|
||||
Spec: &userv3.UserSpec{ProjectNamespaceRoles: []*userv3.ProjectNamespaceRole{{Project: idnamea(pruuid, "project"), Namespace: &ns, Role: idname(ruuid, "role")}}},
|
||||
}
|
||||
user, err := us.Update(context.Background(), user)
|
||||
if err != nil {
|
||||
@@ -233,28 +203,29 @@ func TestUserGetByName(t *testing.T) {
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{}, getLogger())
|
||||
|
||||
uuuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
guuid := uuid.New().String()
|
||||
ruuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "identities"."id", .* FROM "identities" WHERE .*traits ->> 'email' = 'user-` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
|
||||
uuuid := addUserFetchExpectation(mock)
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
|
||||
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid + `'`).
|
||||
@@ -268,8 +239,8 @@ func TestUserGetByName(t *testing.T) {
|
||||
t.Fatal("could not get user:", err)
|
||||
}
|
||||
performUserBasicChecks(t, user, uuuid)
|
||||
if user.GetMetadata().GetName() != "johndoe@provider.com" {
|
||||
t.Errorf("invalid email for user, expected johndoe@provider.com; got '%v'", user.GetMetadata().GetName())
|
||||
if user.GetMetadata().GetName() != "user-"+uuuid {
|
||||
t.Errorf("invalid email for user, expected '%v'; got '%v'", "user-"+uuuid, user.GetMetadata().GetName())
|
||||
}
|
||||
if len(user.GetSpec().GetGroups()) != 1 {
|
||||
t.Errorf("invalid number of groups returned for user, expected 2; got '%v'", len(user.GetSpec().GetGroups()))
|
||||
@@ -289,7 +260,7 @@ func TestUserGetInfo(t *testing.T) {
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{}, getLogger())
|
||||
|
||||
uuuid := uuid.New().String()
|
||||
fakeuuuid := uuid.New().String()
|
||||
@@ -361,32 +332,20 @@ func TestUserGetById(t *testing.T) {
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{}, getLogger())
|
||||
|
||||
uuuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
guuid := uuid.New().String()
|
||||
ruuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
// lookup by id
|
||||
mock.ExpectQuery(`SELECT "identities"."id",.* FROM "identities" WHERE .*id = '` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
|
||||
guuid := addUsersGroupFetchExpectation(mock, uuuid)
|
||||
addGroupRoleMappingsFetchExpectation(mock, guuid, pruuid)
|
||||
addUserRoleMappingsFetchExpectation(mock, uuuid, pruuid)
|
||||
|
||||
user := &userv3.User{
|
||||
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid, Id: uuuid},
|
||||
@@ -402,276 +361,132 @@ func TestUserGetById(t *testing.T) {
|
||||
if len(user.GetSpec().GetProjectNamespaceRoles()) != 6 {
|
||||
t.Errorf("invalid number of roles returned for user, expected 6; got '%v'", len(user.GetSpec().GetProjectNamespaceRoles()))
|
||||
}
|
||||
if user.GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 9 {
|
||||
t.Errorf("invalid namespace in role returned for user, expected 9; got '%v'", user.GetSpec().GetProjectNamespaceRoles()[2].Namespace)
|
||||
if user.GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 7 {
|
||||
t.Errorf("invalid namespace in role returned for user, expected 7; got '%v'", user.GetSpec().GetProjectNamespaceRoles()[2].Namespace)
|
||||
}
|
||||
|
||||
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
func TestUserList(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
|
||||
uuuid1 := uuid.New().String()
|
||||
uuuid2 := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
guuid := uuid.New().String()
|
||||
ruuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
mock.ExpectQuery(`SELECT "identities"."id", .*FROM "identities" LIMIT 10`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).
|
||||
AddRow(uuuid1, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)).
|
||||
AddRow(uuuid2, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
|
||||
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
|
||||
qo := &commonv3.QueryOptions{Organization: ouuid, Partner: puuid}
|
||||
userlist, err := us.List(context.Background(), query.WithOptions(qo))
|
||||
if err != nil {
|
||||
t.Fatal("could not list users:", err)
|
||||
tests := []struct {
|
||||
name string
|
||||
q string
|
||||
limit int64
|
||||
offset int64
|
||||
orderBy string
|
||||
order string
|
||||
role string
|
||||
group string
|
||||
projects []string
|
||||
utype string
|
||||
}{
|
||||
{"simple list", "", 50, 20, "", "", "", "", []string{}, ""},
|
||||
{"simple list with type", "", 50, 20, "", "", "", "", []string{}, "password"},
|
||||
{"sorted list", "", 50, 20, "email", "asc", "", "", []string{}, ""},
|
||||
{"sorted list without dir", "", 50, 20, "email", "", "", "", []string{}, ""},
|
||||
{"sorted list with q", "filter-query", 50, 20, "email", "asc", "", "", []string{}, ""},
|
||||
{"sorted list with role", "", 50, 20, "email", "asc", "role-name", "", []string{}, ""},
|
||||
{"sorted list with role and group", "", 50, 20, "email", "asc", "role-name", "group-name", []string{}, ""},
|
||||
{"sorted list with q and role", "filter-query", 50, 20, "email", "asc", "role-name", "", []string{}, ""},
|
||||
}
|
||||
if userlist.Metadata.Count != 2 {
|
||||
t.Fatalf("incorrect number of users returned, expected 2; got %v", userlist.Metadata.Count)
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{}, getLogger())
|
||||
|
||||
uuuid1 := uuid.New().String()
|
||||
uuuid2 := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
puuid, ouuid := addParterOrgFetchExpectation(mock)
|
||||
q := ""
|
||||
if tc.q != "" {
|
||||
q = ` AND .traits ->> 'email' ILIKE '%` + tc.q + `%'. OR .traits ->> 'first_name' ILIKE '%` + tc.q + `%'. OR .traits ->> 'last_name' ILIKE '%` + tc.q + `%'. `
|
||||
}
|
||||
order := ""
|
||||
if tc.orderBy != "" {
|
||||
order = `ORDER BY "traits ->> '` + tc.orderBy + `' `
|
||||
}
|
||||
if tc.order != "" {
|
||||
order = order + tc.order + `" `
|
||||
}
|
||||
if tc.role != "" {
|
||||
addFetchExpectation(mock, "resourcerole")
|
||||
}
|
||||
if tc.group != "" {
|
||||
addFetchExpectation(mock, "group")
|
||||
}
|
||||
if tc.role != "" || tc.group != "" || len(tc.projects) != 0 {
|
||||
addSentryLookupExpectation(mock, []string{uuuid1, uuuid2}, puuid, ouuid)
|
||||
mock.ExpectQuery(`SELECT "identities"."id", .*WHERE .id IN .'` + uuuid1 + `', '` + uuuid2 + `'.. ` + q + order + `LIMIT ` + fmt.Sprint(tc.limit) + ` OFFSET ` + fmt.Sprint(tc.offset)).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).
|
||||
AddRow(uuuid1, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)).
|
||||
AddRow(uuuid2, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
|
||||
} else {
|
||||
if tc.utype != "" {
|
||||
mock.ExpectQuery(`SELECT "identities"."id", .*, "identity_credential"."id" AS "identity_credential__id", .*FROM "identities" LEFT JOIN "identity_credentials" AS "identity_credential" ON ."identity_credential"."identity_id" = "identities"."id". LEFT JOIN "identity_credential_types" AS "identity_credential__identity_credential_type" ON ."identity_credential__identity_credential_type"."id" = "identity_credential"."identity_credential_type_id". WHERE .name = '` + tc.utype + `'. LIMIT 50 OFFSET 20`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).
|
||||
AddRow(uuuid1, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)).
|
||||
AddRow(uuuid2, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
|
||||
} else {
|
||||
mock.ExpectQuery(`SELECT "identities"."id".* LIMIT 50 OFFSET 20$`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).
|
||||
AddRow(uuuid1, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)).
|
||||
AddRow(uuuid2, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
|
||||
}
|
||||
}
|
||||
|
||||
guuid := addUsersGroupFetchExpectation(mock, uuuid1)
|
||||
addGroupRoleMappingsFetchExpectation(mock, guuid, pruuid)
|
||||
addUserRoleMappingsFetchExpectation(mock, uuuid1, pruuid)
|
||||
|
||||
guuid = addUsersGroupFetchExpectation(mock, uuuid2)
|
||||
addGroupRoleMappingsFetchExpectation(mock, guuid, pruuid)
|
||||
addUserRoleMappingsFetchExpectation(mock, uuuid2, pruuid)
|
||||
|
||||
qo := &commonv3.QueryOptions{
|
||||
Q: tc.q,
|
||||
Limit: tc.limit,
|
||||
Offset: tc.offset,
|
||||
OrderBy: tc.orderBy,
|
||||
Order: tc.order,
|
||||
Organization: ouuid,
|
||||
Partner: puuid,
|
||||
Role: tc.role,
|
||||
Group: tc.group,
|
||||
Type: tc.utype,
|
||||
}
|
||||
|
||||
userlist, err := us.List(context.Background(), query.WithOptions(qo))
|
||||
if err != nil {
|
||||
t.Fatal("could not list users:", err)
|
||||
}
|
||||
if userlist.Metadata.Count != 2 {
|
||||
t.Fatalf("incorrect number of users returned, expected 2; got %v", userlist.Metadata.Count)
|
||||
}
|
||||
if userlist.Items[0].Metadata.Name != "johndoe@provider.com" || userlist.Items[1].Metadata.Name != "johndoe@provider.com" {
|
||||
t.Errorf("incorrect user names returned when listing; expected '%v' and '%v'; got '%v' and '%v'", "johndoe@provider.com", "johndoe@provider.com", userlist.Items[0].Metadata.Name, userlist.Items[1].Metadata.Name)
|
||||
}
|
||||
if len(userlist.Items[0].GetSpec().GetGroups()) != 1 {
|
||||
t.Errorf("invalid number of groups returned for user, expected 1; got '%v'", len(userlist.Items[0].GetSpec().GetGroups()))
|
||||
}
|
||||
|
||||
if len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()) != 6 {
|
||||
t.Errorf("invalid number of roles returned for user, expected 6; got '%v'", len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()))
|
||||
}
|
||||
if userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 7 {
|
||||
t.Errorf("invalid namespace in role returned for user, expected 7; got '%v'", userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].Namespace)
|
||||
}
|
||||
|
||||
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
|
||||
|
||||
})
|
||||
}
|
||||
if userlist.Items[0].Metadata.Name != "johndoe@provider.com" || userlist.Items[1].Metadata.Name != "johndoe@provider.com" {
|
||||
t.Errorf("incorrect user names returned when listing; expected '%v' and '%v'; got '%v' and '%v'", "johndoe@provider.com", "johndoe@provider.com", userlist.Items[0].Metadata.Name, userlist.Items[1].Metadata.Name)
|
||||
}
|
||||
if len(userlist.Items[0].GetSpec().GetGroups()) != 1 {
|
||||
t.Errorf("invalid number of groups returned for user, expected 1; got '%v'", len(userlist.Items[0].GetSpec().GetGroups()))
|
||||
}
|
||||
|
||||
if len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()) != 6 {
|
||||
t.Errorf("invalid number of roles returned for user, expected 6; got '%v'", len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()))
|
||||
}
|
||||
if userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 9 {
|
||||
t.Errorf("invalid namespace in role returned for user, expected 9; got '%v'", userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].Namespace)
|
||||
}
|
||||
|
||||
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
func TestUserListWithType(t *testing.T) {
|
||||
// TODO: merge these tests
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
|
||||
uuuid1 := uuid.New().String()
|
||||
uuuid2 := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
guuid := uuid.New().String()
|
||||
ruuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
mock.ExpectQuery(`SELECT "identities"."id", "identities"."schema_id", "identities"."traits", "identities"."created_at", "identities"."updated_at", "identities"."state", "identities"."state_changed_at", "identities"."nid", "identity_credential"."id" AS "identity_credential__id", "identity_credential"."identity_id" AS "identity_credential__identity_id", "identity_credential"."identity_credential_type_id" AS "identity_credential__identity_credential_type_id", "identity_credential__identity_credential_type"."id" AS "identity_credential__identity_credential_type__id", "identity_credential__identity_credential_type"."name" AS "identity_credential__identity_credential_type__name" FROM "identities" LEFT JOIN "identity_credentials" AS "identity_credential" ON ."identity_credential"."identity_id" = "identities"."id". LEFT JOIN "identity_credential_types" AS "identity_credential__identity_credential_type" ON ."identity_credential__identity_credential_type"."id" = "identity_credential"."identity_credential_type_id". WHERE .name = 'password'. LIMIT 10`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).
|
||||
AddRow(uuuid1, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)).
|
||||
AddRow(uuuid2, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
|
||||
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
|
||||
qo := &commonv3.QueryOptions{Organization: ouuid, Partner: puuid, Type: "password"}
|
||||
userlist, err := us.List(context.Background(), query.WithOptions(qo))
|
||||
if err != nil {
|
||||
t.Fatal("could not list users:", err)
|
||||
}
|
||||
if userlist.Metadata.Count != 2 {
|
||||
t.Fatalf("incorrect number of users returned, expected 2; got %v", userlist.Metadata.Count)
|
||||
}
|
||||
if userlist.Items[0].Metadata.Name != "johndoe@provider.com" || userlist.Items[1].Metadata.Name != "johndoe@provider.com" {
|
||||
t.Errorf("incorrect user names returned when listing; expected '%v' and '%v'; got '%v' and '%v'", "johndoe@provider.com", "johndoe@provider.com", userlist.Items[0].Metadata.Name, userlist.Items[1].Metadata.Name)
|
||||
}
|
||||
if len(userlist.Items[0].GetSpec().GetGroups()) != 1 {
|
||||
t.Errorf("invalid number of groups returned for user, expected 1; got '%v'", len(userlist.Items[0].GetSpec().GetGroups()))
|
||||
}
|
||||
|
||||
if len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()) != 6 {
|
||||
t.Errorf("invalid number of roles returned for user, expected 6; got '%v'", len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()))
|
||||
}
|
||||
if userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 9 {
|
||||
t.Errorf("invalid namespace in role returned for user, expected 9; got '%v'", userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].Namespace)
|
||||
}
|
||||
|
||||
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
func TestUserFiltered(t *testing.T) {
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
|
||||
uuuid1 := uuid.New().String()
|
||||
uuuid2 := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
ouuid := uuid.New().String()
|
||||
guuid := uuid.New().String()
|
||||
ruuid := uuid.New().String()
|
||||
pruuid := uuid.New().String()
|
||||
|
||||
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
|
||||
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
|
||||
mock.ExpectQuery(`SELECT "group"."id" FROM "authsrv_group" AS "group" WHERE .name = 'group-name'. AND .trash = FALSE.`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(guuid))
|
||||
mock.ExpectQuery(`SELECT DISTINCT account_id FROM "sentry_account_permission" AS "sap" WHERE .partner_id = '` + puuid + `'. AND .organization_id = '` + ouuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"account_id"}).AddRow(uuuid1).AddRow(uuuid2))
|
||||
mock.ExpectQuery(`SELECT "identities"."id", .*WHERE .id IN .'` + uuuid1 + `', '` + uuuid2 + `'.. AND .traits ->> 'email' ILIKE '%filter-query%'. OR .traits ->> 'first_name' ILIKE '%filter-query%'. OR .traits ->> 'last_name' ILIKE '%filter-query%'. ORDER BY "traits ->> 'email' asc" LIMIT 50 OFFSET 20`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).
|
||||
AddRow(uuuid1, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)).
|
||||
AddRow(uuuid2, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
|
||||
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + guuid).AddRow("group2-" + guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group2-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid1 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
|
||||
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
|
||||
AddRow("group-" + guuid).AddRow("group2-" + guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group2-"+guuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
|
||||
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
|
||||
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid2 + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
|
||||
|
||||
qo := &commonv3.QueryOptions{Q: "filter-query", Limit: 50, Offset: 20, OrderBy: "email", Order: "asc", Organization: ouuid, Partner: puuid, Group: "group-name"}
|
||||
userlist, err := us.List(context.Background(), query.WithOptions(qo))
|
||||
if err != nil {
|
||||
t.Fatal("could not list users:", err)
|
||||
}
|
||||
if userlist.Metadata.Count != 2 {
|
||||
t.Fatalf("incorrect number of users returned, expected 2; got %v", userlist.Metadata.Count)
|
||||
}
|
||||
|
||||
if userlist.Items[0].Metadata.Name != "johndoe@provider.com" {
|
||||
t.Errorf("incorrect user names returned when listing; expected '%v' and '%v'; got '%v' and '%v'", "johndoe@provider.com", "johndoe@provider.com", userlist.Items[0].Metadata.Name, userlist.Items[1].Metadata.Name)
|
||||
}
|
||||
|
||||
if len(userlist.Items[0].GetSpec().GetGroups()) != 2 {
|
||||
t.Errorf("invalid number of groups returned for user, expected 2; got '%v'", len(userlist.Items[0].GetSpec().GetGroups()))
|
||||
}
|
||||
|
||||
if len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()) != 9 {
|
||||
t.Errorf("invalid number of roles returned for user, expected 3; got '%v'", len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()))
|
||||
}
|
||||
if userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 9 {
|
||||
t.Errorf("invalid namespace in role returned for user, expected 9; got '%v'", userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].Namespace)
|
||||
}
|
||||
|
||||
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
func TestUserDelete(t *testing.T) {
|
||||
@@ -680,7 +495,7 @@ func TestUserDelete(t *testing.T) {
|
||||
|
||||
ap := &mockAuthProvider{}
|
||||
mazc := mockAuthzClient{}
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
|
||||
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{}, getLogger())
|
||||
|
||||
uuuid := uuid.New().String()
|
||||
puuid := uuid.New().String()
|
||||
@@ -689,15 +504,9 @@ func TestUserDelete(t *testing.T) {
|
||||
mock.ExpectQuery(`SELECT "identities"."id" FROM "identities" WHERE .*traits ->> 'email' = 'user-` + uuuid + `'`).
|
||||
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec(`UPDATE "authsrv_accountresourcerole" AS "accountresourcerole" SET trash = TRUE WHERE`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_projectaccountresourcerole" AS "projectaccountresourcerole" SET trash = TRUE WHERE`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec(`UPDATE "authsrv_projectaccountnamespacerole" AS "projectaccountnamespacerole" SET trash = TRUE WHERE`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
_ = addUserRoleMappingsUpdateExpectation(mock, uuuid)
|
||||
// User delete is via kratos
|
||||
mock.ExpectExec(`UPDATE "authsrv_groupaccount" AS "groupaccount" SET trash = TRUE WHERE`).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
addUserGroupMappingsUpdateExpectation(mock, uuuid)
|
||||
mock.ExpectCommit()
|
||||
|
||||
user := &userv3.User{
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/RafayLabs/rcloud-base/internal/dao"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/common"
|
||||
commonv3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
@@ -29,6 +31,15 @@ func contains(s []string, str string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func containsu(s []uuid.UUID, id uuid.UUID) bool {
|
||||
for _, v := range s {
|
||||
if v == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func remove(l []string, item string) []string {
|
||||
for i, other := range l {
|
||||
if other == item {
|
||||
@@ -38,6 +49,47 @@ func remove(l []string, item string) []string {
|
||||
return l
|
||||
}
|
||||
|
||||
func diff(before, after []string) ([]string, []string, []string) {
|
||||
cu := []string{}
|
||||
uu := []string{}
|
||||
du := []string{}
|
||||
|
||||
for _, u := range after {
|
||||
if contains(before, u) {
|
||||
uu = append(uu, u)
|
||||
} else {
|
||||
cu = append(du, u)
|
||||
}
|
||||
}
|
||||
for _, u := range before {
|
||||
if !contains(uu, u) && !contains(du, u) {
|
||||
du = append(cu, u)
|
||||
}
|
||||
}
|
||||
return cu, uu, du
|
||||
}
|
||||
|
||||
// Given two lists, return newly created, unchanged and deleted items
|
||||
func diffu(before, after []uuid.UUID) ([]uuid.UUID, []uuid.UUID, []uuid.UUID) {
|
||||
cu := []uuid.UUID{}
|
||||
uu := []uuid.UUID{}
|
||||
du := []uuid.UUID{}
|
||||
|
||||
for _, u := range after {
|
||||
if containsu(before, u) {
|
||||
uu = append(uu, u)
|
||||
} else {
|
||||
cu = append(du, u)
|
||||
}
|
||||
}
|
||||
for _, u := range before {
|
||||
if !containsu(uu, u) && !containsu(du, u) {
|
||||
du = append(cu, u)
|
||||
}
|
||||
}
|
||||
return cu, uu, du
|
||||
}
|
||||
|
||||
func getPartnerOrganization(ctx context.Context, db bun.IDB, partner, org string) (uuid.UUID, uuid.UUID, error) {
|
||||
partnerId, err := dao.GetPartnerId(ctx, db, partner)
|
||||
if err != nil {
|
||||
@@ -50,3 +102,8 @@ func getPartnerOrganization(ctx context.Context, db bun.IDB, partner, org string
|
||||
return partnerId, organizationId, nil
|
||||
|
||||
}
|
||||
|
||||
func GetSessionDataFromContext(ctx context.Context) (*commonv3.SessionData, bool) {
|
||||
s, ok := ctx.Value(common.SessionDataKey).(*commonv3.SessionData)
|
||||
return s, ok
|
||||
}
|
||||
|
||||
@@ -516,9 +516,12 @@ type SessionData struct {
|
||||
Idp string `protobuf:"bytes,15,opt,name=idp,proto3" json:"idp,omitempty"`
|
||||
IsOrgAdmin map[string]bool `protobuf:"bytes,16,rep,name=is_org_admin,json=isOrgAdmin,proto3" json:"is_org_admin,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
||||
ClientType ClientType `protobuf:"varint,17,opt,name=client_type,json=clientType,proto3,enum=rafay.dev.types.common.v3.ClientType" json:"client_type,omitempty"`
|
||||
IsAllNsAccess map[string]bool `protobuf:"bytes,18,rep,name=is_all_ns_access,json=isAllNsAccess,proto3" json:"is_all_ns_access,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
||||
Namespaces []*NamespaceData `protobuf:"bytes,19,rep,name=namespaces,proto3" json:"namespaces,omitempty"`
|
||||
Project *ProjectData `protobuf:"bytes,20,opt,name=project,proto3" json:"project,omitempty"`
|
||||
ClientHost string `protobuf:"bytes,18,opt,name=client_host,json=clientHost,proto3" json:"client_host,omitempty"`
|
||||
ClientIp string `protobuf:"bytes,19,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
|
||||
ClientUa string `protobuf:"bytes,20,opt,name=client_ua,json=clientUa,proto3" json:"client_ua,omitempty"`
|
||||
IsAllNsAccess map[string]bool `protobuf:"bytes,21,rep,name=is_all_ns_access,json=isAllNsAccess,proto3" json:"is_all_ns_access,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
||||
Namespaces []*NamespaceData `protobuf:"bytes,22,rep,name=namespaces,proto3" json:"namespaces,omitempty"`
|
||||
Project *ProjectData `protobuf:"bytes,23,opt,name=project,proto3" json:"project,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SessionData) Reset() {
|
||||
@@ -672,6 +675,27 @@ func (x *SessionData) GetClientType() ClientType {
|
||||
return ClientType_ClientTypeNotSet
|
||||
}
|
||||
|
||||
func (x *SessionData) GetClientHost() string {
|
||||
if x != nil {
|
||||
return x.ClientHost
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SessionData) GetClientIp() string {
|
||||
if x != nil {
|
||||
return x.ClientIp
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SessionData) GetClientUa() string {
|
||||
if x != nil {
|
||||
return x.ClientUa
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SessionData) GetIsAllNsAccess() map[string]bool {
|
||||
if x != nil {
|
||||
return x.IsAllNsAccess
|
||||
@@ -796,7 +820,7 @@ var file_proto_types_commonpb_v3_auth_proto_rawDesc = []byte{
|
||||
0x6c, 0x12, 0x3a, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x26, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65,
|
||||
0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x72, 0x6f, 0x6a,
|
||||
0x65, 0x63, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0xae, 0x09,
|
||||
0x65, 0x63, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x89, 0x0a,
|
||||
0x0a, 0x0b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a,
|
||||
0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e,
|
||||
@@ -841,80 +865,86 @@ var file_proto_types_commonpb_v3_auth_proto_rawDesc = []byte{
|
||||
0x74, 0x79, 0x70, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x72, 0x61, 0x66,
|
||||
0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
|
||||
0x65, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x62, 0x0a,
|
||||
0x10, 0x69, 0x73, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6e, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73,
|
||||
0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e,
|
||||
0x65, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a,
|
||||
0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x12, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x1b,
|
||||
0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x13, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x61, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x61, 0x12, 0x62, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x61,
|
||||
0x6c, 0x6c, 0x5f, 0x6e, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x15, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x39, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74,
|
||||
0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x53,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x73, 0x41, 0x6c, 0x6c,
|
||||
0x4e, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x69,
|
||||
0x73, 0x41, 0x6c, 0x6c, 0x4e, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x48, 0x0a, 0x0a,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x28, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70,
|
||||
0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
|
||||
0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e,
|
||||
0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||
0x2e, 0x76, 0x33, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e,
|
||||
0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4e, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x52, 0x0d, 0x69, 0x73, 0x41, 0x6c, 0x6c, 0x4e, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73,
|
||||
0x73, 0x12, 0x48, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18,
|
||||
0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x64, 0x65,
|
||||
0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76,
|
||||
0x33, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52,
|
||||
0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x07, 0x70,
|
||||
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72,
|
||||
0x61, 0x66, 0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
|
||||
0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x1a, 0x6e, 0x0a,
|
||||
0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x72, 0x6c, 0x73, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x43, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e,
|
||||
0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e,
|
||||
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x4d, 0x65, 0x74, 0x68, 0x6f,
|
||||
0x64, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a,
|
||||
0x0f, 0x49, 0x73, 0x4f, 0x72, 0x67, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x40, 0x0a, 0x12,
|
||||
0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4e, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbe,
|
||||
0x01, 0x0a, 0x18, 0x49, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x6f,
|
||||
0x77, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x73,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x72, 0x61,
|
||||
0x66, 0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72,
|
||||
0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x61, 0x66,
|
||||
0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x61,
|
||||
0x74, 0x61, 0x52, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2a,
|
||||
0x6f, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x1b, 0x0a,
|
||||
0x17, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x72, 0x55, 0x52, 0x4c,
|
||||
0x4e, 0x6f, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x03,
|
||||
0x2a, 0x3c, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e,
|
||||
0x41, 0x75, 0x74, 0x68, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x6f, 0x74, 0x53, 0x65, 0x74, 0x10, 0x00,
|
||||
0x12, 0x10, 0x0a, 0x0c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x6f, 0x67, 0x69, 0x6e,
|
||||
0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x10, 0x02, 0x2a, 0x38,
|
||||
0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10,
|
||||
0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x6f, 0x74, 0x53, 0x65, 0x74,
|
||||
0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x42, 0x52, 0x4f, 0x57, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12,
|
||||
0x07, 0x0a, 0x03, 0x43, 0x4c, 0x49, 0x10, 0x02, 0x42, 0xf6, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d,
|
||||
0x2e, 0x76, 0x33, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52,
|
||||
0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x1a, 0x6e, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x55, 0x72, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
|
||||
0x43, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d,
|
||||
0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x42, 0x09, 0x41, 0x75, 0x74, 0x68,
|
||||
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x52, 0x61, 0x66, 0x61, 0x79, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x72, 0x63,
|
||||
0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
|
||||
0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2f, 0x76,
|
||||
0x33, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x76, 0x33, 0xa2, 0x02, 0x04, 0x52, 0x44, 0x54,
|
||||
0x43, 0xaa, 0x02, 0x19, 0x52, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x44, 0x65, 0x76, 0x2e, 0x54, 0x79,
|
||||
0x70, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x33, 0xca, 0x02, 0x19,
|
||||
0x52, 0x61, 0x66, 0x61, 0x79, 0x5c, 0x44, 0x65, 0x76, 0x5c, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c,
|
||||
0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x56, 0x33, 0xe2, 0x02, 0x25, 0x52, 0x61, 0x66, 0x61,
|
||||
0x79, 0x5c, 0x44, 0x65, 0x76, 0x5c, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x43, 0x6f, 0x6d, 0x6d,
|
||||
0x6f, 0x6e, 0x5c, 0x56, 0x33, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||
0x61, 0xea, 0x02, 0x1d, 0x52, 0x61, 0x66, 0x61, 0x79, 0x3a, 0x3a, 0x44, 0x65, 0x76, 0x3a, 0x3a,
|
||||
0x54, 0x79, 0x70, 0x65, 0x73, 0x3a, 0x3a, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3a, 0x3a, 0x56,
|
||||
0x33, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75,
|
||||
0x72, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a, 0x0f, 0x49, 0x73, 0x4f, 0x72,
|
||||
0x67, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x40, 0x0a, 0x12, 0x49, 0x73, 0x41, 0x6c, 0x6c,
|
||||
0x4e, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbe, 0x01, 0x0a, 0x18, 0x49, 0x73,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x64,
|
||||
0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||
0x76, 0x33, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73,
|
||||
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e,
|
||||
0x12, 0x48, 0x0a, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x61, 0x66, 0x61, 0x79, 0x2e, 0x64, 0x65,
|
||||
0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76,
|
||||
0x33, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x73,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2a, 0x6f, 0x0a, 0x0d, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55,
|
||||
0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x64, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x72, 0x55, 0x52, 0x4c, 0x4e, 0x6f, 0x74, 0x41, 0x6c,
|
||||
0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x10, 0x03, 0x2a, 0x3c, 0x0a, 0x08, 0x41,
|
||||
0x75, 0x74, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x54,
|
||||
0x79, 0x70, 0x65, 0x4e, 0x6f, 0x74, 0x53, 0x65, 0x74, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x53,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0a, 0x0a,
|
||||
0x06, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x10, 0x02, 0x2a, 0x38, 0x0a, 0x0a, 0x43, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x6f, 0x74, 0x53, 0x65, 0x74, 0x10, 0x00, 0x12, 0x0b, 0x0a,
|
||||
0x07, 0x42, 0x52, 0x4f, 0x57, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x4c,
|
||||
0x49, 0x10, 0x02, 0x42, 0xf6, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x72, 0x61, 0x66, 0x61,
|
||||
0x79, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x42, 0x09, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x50, 0x01, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x52,
|
||||
0x61, 0x66, 0x61, 0x79, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x72, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d,
|
||||
0x62, 0x61, 0x73, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73,
|
||||
0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2f, 0x76, 0x33, 0x3b, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x6f, 0x6e, 0x76, 0x33, 0xa2, 0x02, 0x04, 0x52, 0x44, 0x54, 0x43, 0xaa, 0x02, 0x19, 0x52,
|
||||
0x61, 0x66, 0x61, 0x79, 0x2e, 0x44, 0x65, 0x76, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43,
|
||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x33, 0xca, 0x02, 0x19, 0x52, 0x61, 0x66, 0x61, 0x79,
|
||||
0x5c, 0x44, 0x65, 0x76, 0x5c, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||
0x6e, 0x5c, 0x56, 0x33, 0xe2, 0x02, 0x25, 0x52, 0x61, 0x66, 0x61, 0x79, 0x5c, 0x44, 0x65, 0x76,
|
||||
0x5c, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x56, 0x33,
|
||||
0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1d, 0x52,
|
||||
0x61, 0x66, 0x61, 0x79, 0x3a, 0x3a, 0x44, 0x65, 0x76, 0x3a, 0x3a, 0x54, 0x79, 0x70, 0x65, 0x73,
|
||||
0x3a, 0x3a, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x33, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -70,9 +70,12 @@ message SessionData {
|
||||
string idp = 15;
|
||||
map<string, bool> is_org_admin = 16;
|
||||
ClientType client_type = 17;
|
||||
map<string, bool> is_all_ns_access = 18;
|
||||
repeated NamespaceData namespaces = 19;
|
||||
ProjectData project = 20;
|
||||
string client_host = 18;
|
||||
string client_ip = 19;
|
||||
string client_ua = 20;
|
||||
map<string, bool> is_all_ns_access = 21;
|
||||
repeated NamespaceData namespaces = 22;
|
||||
ProjectData project = 23;
|
||||
}
|
||||
|
||||
message IsRequestAllowedResponse {
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/RafayLabs/rcloud-base/internal/dao"
|
||||
"github.com/RafayLabs/rcloud-base/internal/models"
|
||||
providers "github.com/RafayLabs/rcloud-base/internal/provider/kratos"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/audit"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/common"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/enforcer"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/service"
|
||||
@@ -51,6 +52,7 @@ const (
|
||||
dbUserEnv = "DB_USER"
|
||||
dbPasswordEnv = "DB_PASSWORD"
|
||||
kratosAddrEnv = "KRATOS_ADDR"
|
||||
auditFileEnv = "AUDIT_LOG_FILE"
|
||||
)
|
||||
|
||||
func addResourcePermissions(db *bun.DB, basePath string) error {
|
||||
@@ -109,7 +111,9 @@ func main() {
|
||||
viper.SetDefault(dbUserEnv, "admindbuser")
|
||||
viper.SetDefault(dbPasswordEnv, "admindbpassword")
|
||||
viper.SetDefault(kratosAddrEnv, "http://localhost:4433")
|
||||
viper.SetDefault(auditFileEnv, "audit.log")
|
||||
|
||||
viper.BindEnv(auditFileEnv)
|
||||
viper.BindEnv(dbAddrEnv)
|
||||
viper.BindEnv(dbNameEnv)
|
||||
viper.BindEnv(dbUserEnv)
|
||||
@@ -121,6 +125,7 @@ func main() {
|
||||
dbUser := viper.GetString(dbUserEnv)
|
||||
dbPassword := viper.GetString(dbPasswordEnv)
|
||||
kratosAddr := viper.GetString(kratosAddrEnv)
|
||||
auditFile := viper.GetString(auditFileEnv)
|
||||
|
||||
content, err := ioutil.ReadFile(path.Join("scripts", "initialize", "roles", "ztka", "roles.json"))
|
||||
if err != nil {
|
||||
@@ -148,6 +153,14 @@ func main() {
|
||||
kratosConfig.Servers[0].URL = kratosAddr
|
||||
kc := kclient.NewAPIClient(kratosConfig)
|
||||
|
||||
ao := audit.AuditOptions{
|
||||
LogPath: auditFile,
|
||||
MaxSizeMB: 1,
|
||||
MaxBackups: 10, // Should we let sidecar do rotation?
|
||||
MaxAgeDays: 10, // Make these configurable via env
|
||||
}
|
||||
auditLogger := audit.GetAuditLogger(&ao)
|
||||
|
||||
// authz services
|
||||
gormDb, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
@@ -159,12 +172,12 @@ func main() {
|
||||
}
|
||||
as := service.NewAuthzService(db, enforcer)
|
||||
|
||||
ps := service.NewPartnerService(db)
|
||||
os := service.NewOrganizationService(db)
|
||||
rs := service.NewRoleService(db, as)
|
||||
gs := service.NewGroupService(db, as)
|
||||
us := service.NewUserService(providers.NewKratosAuthProvider(kc), db, as, nil, common.CliConfigDownloadData{})
|
||||
prs := service.NewProjectService(db, as)
|
||||
ps := service.NewPartnerService(db, auditLogger)
|
||||
os := service.NewOrganizationService(db, auditLogger)
|
||||
rs := service.NewRoleService(db, as, auditLogger)
|
||||
gs := service.NewGroupService(db, as, auditLogger)
|
||||
us := service.NewUserService(providers.NewKratosAuthProvider(kc), db, as, nil, common.CliConfigDownloadData{}, auditLogger)
|
||||
prs := service.NewProjectService(db, as, auditLogger)
|
||||
|
||||
//check if there are role permissions already present
|
||||
existingPermissions := &[]models.ResourceRolePermission{}
|
||||
@@ -287,6 +300,5 @@ retry:
|
||||
goto retry
|
||||
}
|
||||
|
||||
fmt.Println("Org Admin signup URL: ", orgA.Spec.RecoveryUrl)
|
||||
|
||||
fmt.Println("Org Admin signup URL: ", *orgA.Spec.RecoveryUrl)
|
||||
}
|
||||
|
||||
+1
-2
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/RafayLabs/rcloud-base/pkg/common"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/query"
|
||||
"github.com/RafayLabs/rcloud-base/pkg/service"
|
||||
rpcv3 "github.com/RafayLabs/rcloud-base/proto/rpc/user"
|
||||
@@ -75,7 +74,7 @@ func (s *userServer) UpdateUser(ctx context.Context, req *userpbv3.User) (*userp
|
||||
}
|
||||
|
||||
func (s *userServer) DownloadCliConfig(ctx context.Context, req *rpcv3.CliConfigRequest) (*commonv3.HttpBody, error) {
|
||||
sessData, ok := ctx.Value(common.SessionDataKey).(*commonv3.SessionData)
|
||||
sessData, ok := service.GetSessionDataFromContext(ctx)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to retrieve session data")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user