mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 21:47:23 +00:00
Project commands (#26)
* feat: eventstore repository * fix: remove gorm * version * feat: pkg * feat: add some files for project * feat: eventstore without eventstore-lib * rename files * gnueg * fix: key json * fix: add object * fix: change imports * fix: internal models * fix: some imports * fix: global model * fix: add some functions on repo * feat(eventstore): sdk * fix(eventstore): search query * fix(eventstore): rename app to eventstore * delete empty test * remove unused func * merge master * fix(eventstore): tests * fix(models): delete unused struct * fix: some funcitons * feat(eventstore): implemented push events * fix: move project eventstore to project package * fix: change project eventstore funcs * feat(eventstore): overwrite context data * fix: change project eventstore * fix: add project repo to mgmt server * feat(types): SQL-config * fix: commented code * feat(eventstore): options to overwrite editor * feat: auth interceptor and cockroach migrations * fix: migrations * fix: fix filter * fix: not found on getbyid * fix: add sequence * fix: add some tests * fix(eventstore): nullable sequence * fix: add some tests * merge * fix: add some tests * fix(migrations): correct statements for sequence * fix: add some tests * fix: add some tests * fix: changes from mr * Update internal/eventstore/models/field.go Co-Authored-By: livio-a <livio.a@gmail.com> * fix(eventstore): code quality * fix: add types to aggregate/Event-types * fix(eventstore): rename modifier* to editor* * fix(eventstore): delete editor_org * fix(migrations): remove editor_org field, rename modifier_* to editor_* * fix: generate files * fix(eventstore): tests * fix(eventstore): rename modifier to editor * fix(migrations): add cluster migration, fix(migrations): fix typo of host in clean clsuter * fix(eventstore): move health * fix(eventstore): AggregateTypeFilter aggregateType as param * code quality * feat: start implementing project members * feat: remove member funcs * feat: remove member model * feat: remove member events * feat: remove member repo model * fix: better error func testing * Update docs/local.md Co-Authored-By: Silvan <silvan.reusser@gmail.com> * Update docs/local.md Co-Authored-By: Silvan <silvan.reusser@gmail.com> * fix: mr requests * fix: md file Co-authored-by: adlerhurst <silvan.reusser@gmail.com> Co-authored-by: livio-a <livio.a@gmail.com>
This commit is contained in:
parent
007fc9e9bd
commit
c07ed83c41
@ -16,7 +16,17 @@ Mgmt:
|
||||
ServerPort: 50010
|
||||
GatewayPort: 50011
|
||||
CustomHeaders:
|
||||
- x-caos-
|
||||
- x-zitadel-
|
||||
Repository:
|
||||
Eventstore:
|
||||
ServiceName: 'ManagementAPI'
|
||||
Repository:
|
||||
SQL:
|
||||
Host: $CR_HOST
|
||||
Port: $CR_PORT
|
||||
User: 'management'
|
||||
Database: 'management'
|
||||
SSLmode: disable
|
||||
|
||||
Auth:
|
||||
API:
|
||||
@ -24,7 +34,7 @@ Auth:
|
||||
ServerPort: 50020
|
||||
GatewayPort: 50021
|
||||
CustomHeaders:
|
||||
- x-caos-
|
||||
- x-zitadel-
|
||||
|
||||
Login:
|
||||
# will get port range 5003x
|
||||
@ -35,7 +45,7 @@ Admin:
|
||||
ServerPort: 50040
|
||||
GatewayPort: 50041
|
||||
CustomHeaders:
|
||||
- x-caos-
|
||||
- x-zitadel-
|
||||
|
||||
Console:
|
||||
Port: 50050
|
||||
|
33
docs/local.md
Normal file
33
docs/local.md
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
## local development
|
||||
|
||||
### start cockroach in docker
|
||||
|
||||
```bash
|
||||
docker rm -f zitadel-db &&
|
||||
rm -rf ${GOPATH}/src/github.com/caos/zitadel/cockroach-data &&
|
||||
docker run -d \
|
||||
--name=zitadel-db \
|
||||
--hostname=zitadel-db \
|
||||
-p 26257:26257 -p 8080:8080 \
|
||||
-v "${GOPATH}/src/github.com/caos/zitadel/cockroach-data/zitadel1:/cockroach/cockroach-data" \
|
||||
cockroachdb/cockroach:v19.2.2 start --insecure
|
||||
```
|
||||
|
||||
### local database migrations
|
||||
|
||||
#### local migrate
|
||||
|
||||
`go generate $GOPATH/src/github.com/caos/zitadel/migrations/cockroach/migrate_local.go`
|
||||
|
||||
#### local cleanup
|
||||
|
||||
`go generate $GOPATH/src/github.com/caos/zitadel/migrations/cockroach/clean_local.go`
|
||||
|
||||
|
||||
### Connect to Cockroach
|
||||
|
||||
`docker exec -it "zitadel-db" /cockroach/cockroach sql --insecure`
|
||||
|
||||
#### Should show eventstore, management, admin, auth
|
||||
`show databases;`
|
12
go.mod
12
go.mod
@ -10,7 +10,7 @@ require (
|
||||
github.com/Masterminds/goutils v1.1.0 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible
|
||||
github.com/aws/aws-sdk-go v1.30.1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.30.4 // indirect
|
||||
github.com/caos/logging v0.0.1
|
||||
github.com/cockroachdb/cockroach-go v0.0.0-20200312223839-f565e4789405
|
||||
github.com/envoyproxy/protoc-gen-validate v0.3.0
|
||||
@ -32,14 +32,14 @@ require (
|
||||
github.com/nicksnyder/go-i18n/v2 v2.0.3
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/sirupsen/logrus v1.5.0 // indirect
|
||||
github.com/sony/sonyflake v1.0.0
|
||||
github.com/stretchr/testify v1.5.1
|
||||
go.opencensus.io v0.22.3
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect
|
||||
golang.org/x/crypto v0.0.0-20200403201458-baeed622b8d8
|
||||
golang.org/x/text v0.3.2
|
||||
golang.org/x/tools v0.0.0-20200331202046-9d5940d49312
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940
|
||||
golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b
|
||||
google.golang.org/api v0.21.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200403120447-c50568487044
|
||||
google.golang.org/grpc v1.28.0
|
||||
google.golang.org/protobuf v1.20.1
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
|
25
go.sum
25
go.sum
@ -9,8 +9,6 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0 h1:MZQCQQaRwOrAcuKjiHWHrgKykt4fZyuwF2dtiG3fGW8=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.55.0 h1:eoz/lYxKSL4CNAiaUJ0ZfD1J3bfMYbU5B3rwM1C1EIU=
|
||||
cloud.google.com/go v0.55.0/go.mod h1:ZHmoY+/lIMNkN2+fBmuTiqZ4inFhvQad8ft7MT8IV5Y=
|
||||
cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
@ -24,9 +22,6 @@ cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIA
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.0 h1:Jaz7WbqjtfoCPa1KbfisCX+P5aM3DizEY9pQMU0oAQo=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.0/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.0/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.1 h1:RX9W6FelAqTVnBi/bRXJLXr9n18v4QkQwZYIdnNS51I=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.1/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
@ -50,10 +45,10 @@ github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQY
|
||||
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
||||
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.30.0 h1:7NDwnnQrI1Ivk0bXLzMmuX5ozzOwteHOsAs4druW7gI=
|
||||
github.com/aws/aws-sdk-go v1.30.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.30.1 h1:cUMxtoFvIHhScZgv17tGxw15r6rVKJHR1hsIFRx9hcA=
|
||||
github.com/aws/aws-sdk-go v1.30.1/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.30.4 h1:dpQgypC3rld2Uuz+/2u+0nbfmmyEWxau6v1hdAlvoc8=
|
||||
github.com/aws/aws-sdk-go v1.30.4/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/caos/logging v0.0.1 h1:YSGtO2/+5OWdwilBCou50akoDHAT/OhkbrolkVlR6U0=
|
||||
github.com/caos/logging v0.0.1 h1:YSGtO2/+5OWdwilBCou50akoDHAT/OhkbrolkVlR6U0=
|
||||
github.com/caos/logging v0.0.1/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0=
|
||||
@ -75,6 +70,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@ -243,6 +240,8 @@ github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q=
|
||||
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
|
||||
github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM=
|
||||
github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
@ -278,6 +277,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200403201458-baeed622b8d8 h1:fpnn/HnJONpIu6hkXi1u/7rR0NzilgWr4T0JmWkEitk=
|
||||
golang.org/x/crypto v0.0.0-20200403201458-baeed622b8d8/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -328,7 +329,6 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -371,7 +371,6 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA=
|
||||
@ -419,11 +418,12 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56 h1:DFtSed2q3HtNuVazwVDZ4nSRS/JrZEig0gz2BY4VNrg=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200317043434-63da46f3035e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 h1:kDtqNkeBrZb8B+atrj50B5XLHpzXXqcCdZPP/ApQ5NY=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200331202046-9d5940d49312 h1:2PHG+Ia3gK1K2kjxZnSylizb//eyaMG8gDFbOG7wLV8=
|
||||
golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b h1:AFZdJUT7jJYXQEC29hYH/WZkoV7+KhwxQGmdZ19yYoY=
|
||||
golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -442,6 +442,8 @@ google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.21.0 h1:zS+Q/CJJnVlXpXQVIz+lH0ZT2lBuT2ac7XD8Y/3w6hY=
|
||||
google.golang.org/api v0.21.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@ -467,9 +469,10 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200403120447-c50568487044 h1:112OPFAnKD+XtZhdffFnz17dEbiCTCKfnNQCAWmwFzA=
|
||||
google.golang.org/genproto v0.0.0-20200403120447-c50568487044/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
@ -19,11 +19,16 @@ func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID s
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var perms []string
|
||||
//TODO: Remove as soon as authentification is implemented
|
||||
if CheckInternal(ctx) {
|
||||
return ctx, nil
|
||||
}
|
||||
if requiredAuthOption.Permission == authenticated {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
ctx, perms, err := getUserMethodPermissions(ctx, verifier, requiredAuthOption.Permission, authConfig)
|
||||
ctx, perms, err = getUserMethodPermissions(ctx, verifier, requiredAuthOption.Permission, authConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -32,6 +37,7 @@ func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID s
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,11 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/api"
|
||||
grpc_util "github.com/caos/zitadel/internal/api/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type key int
|
||||
@ -38,14 +41,21 @@ type TokenVerifier interface {
|
||||
}
|
||||
|
||||
func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t TokenVerifier) (_ context.Context, err error) {
|
||||
userID, clientID, agentID, err := verifyAccessToken(ctx, token, t)
|
||||
var userID, projectID, clientID, agentID string
|
||||
//TODO: Remove as soon an authentification is implemented
|
||||
if CheckInternal(ctx) {
|
||||
userID = grpc_util.GetHeader(ctx, api.ZitadelUserID)
|
||||
projectID = grpc_util.GetHeader(ctx, api.ZitadelClientID)
|
||||
agentID = grpc_util.GetHeader(ctx, api.ZitadelAgentID)
|
||||
} else {
|
||||
userID, clientID, agentID, err = verifyAccessToken(ctx, token, t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
projectID, err := t.GetProjectIDByClientID(ctx, clientID)
|
||||
projectID, err = t.GetProjectIDByClientID(ctx, clientID)
|
||||
logging.LogWithFields("AUTH-GfAoV", "clientID", clientID).OnError(err).Warn("could not read projectid by clientid")
|
||||
|
||||
}
|
||||
return context.WithValue(ctx, dataKey, CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID}), nil
|
||||
}
|
||||
|
||||
@ -58,3 +68,17 @@ func GetPermissionsFromCtx(ctx context.Context) []string {
|
||||
ctxPermission, _ := ctx.Value(permissionsKey).([]string)
|
||||
return ctxPermission
|
||||
}
|
||||
|
||||
//TODO: Remove as soon an authentification is implemented
|
||||
func CheckInternal(ctx context.Context) bool {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
v, ok := md[api.LoginKey]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
ok, _ = strconv.ParseBool(v[0])
|
||||
return ok
|
||||
}
|
||||
|
7
internal/api/auth/context_mock.go
Normal file
7
internal/api/auth/context_mock.go
Normal file
@ -0,0 +1,7 @@
|
||||
package auth
|
||||
|
||||
import "context"
|
||||
|
||||
func NewMockContext(orgID, userID string) context.Context {
|
||||
return context.WithValue(nil, dataKey, CtxData{UserID: userID, OrgID: orgID})
|
||||
}
|
@ -16,7 +16,7 @@ type testVerifier struct {
|
||||
}
|
||||
|
||||
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token string) (string, string, string, error) {
|
||||
return "", "", "", nil
|
||||
return "userID", "clientID", "agentID", nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) ResolveGrants(ctx context.Context, sub, orgID string) ([]*Grant, error) {
|
||||
|
@ -19,11 +19,14 @@ func AuthorizationInterceptor(verifier auth.TokenVerifier, authConfig *auth.Conf
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
authToken := grpc_util.GetAuthorizationHeader(ctx)
|
||||
authToken := ""
|
||||
//TODO: Remoce check internal as soon as authentification is implemented
|
||||
if !auth.CheckInternal(ctx) {
|
||||
authToken = grpc_util.GetAuthorizationHeader(ctx)
|
||||
if authToken == "" {
|
||||
return nil, status.Error(codes.Unauthenticated, "auth header missing")
|
||||
}
|
||||
|
||||
}
|
||||
orgID := grpc_util.GetHeader(ctx, api.ZitadelOrgID)
|
||||
|
||||
ctx, err := auth.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt)
|
||||
|
@ -9,4 +9,9 @@ const (
|
||||
Origin = "origin"
|
||||
|
||||
ZitadelOrgID = "x-zitadel-orgid"
|
||||
//TODO: Remove as soon an authentification is implemented
|
||||
ZitadelUserID = "x-zitadel-userid"
|
||||
ZitadelClientID = "x-zitadel-clientid"
|
||||
ZitadelAgentID = "x-zitadel-agentid"
|
||||
LoginKey = "x-zitadel-login"
|
||||
)
|
||||
|
@ -57,3 +57,7 @@ func (es *eventstore) FilterEvents(ctx context.Context, searchQuery *models.Sear
|
||||
}
|
||||
return es.repo.Filter(ctx, searchQuery)
|
||||
}
|
||||
|
||||
func (es *eventstore) Health(ctx context.Context) error {
|
||||
return es.repo.Health(ctx)
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func (app *eventstore) Health(ctx context.Context) error {
|
||||
return app.repo.Health(ctx)
|
||||
}
|
@ -24,11 +24,11 @@ func (m *MockRepository) ExpectFilterFail(query *models.SearchQuery, err error)
|
||||
}
|
||||
|
||||
func (m *MockRepository) ExpectPush(aggregates ...*models.Aggregate) *MockRepository {
|
||||
m.EXPECT().PushEvents(context.Background(), aggregates).Return(nil).MaxTimes(1)
|
||||
m.EXPECT().PushAggregates(context.Background(), aggregates).Return(nil).MaxTimes(1)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *MockRepository) ExpectPushError(err error, aggregates ...*models.Aggregate) *MockRepository {
|
||||
m.EXPECT().PushEvents(context.Background(), aggregates).Return(err).MaxTimes(1)
|
||||
m.EXPECT().PushAggregates(context.Background(), aggregates).Return(err).MaxTimes(1)
|
||||
return m
|
||||
}
|
||||
|
@ -81,17 +81,3 @@ func (mr *MockRepositoryMockRecorder) PushAggregates(arg0 interface{}, arg1 ...i
|
||||
varargs := append([]interface{}{arg0}, arg1...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PushAggregates", reflect.TypeOf((*MockRepository)(nil).PushAggregates), varargs...)
|
||||
}
|
||||
|
||||
// PushEvents mocks base method
|
||||
func (m *MockRepository) PushEvents(arg0 context.Context, arg1 [][]*models.Event) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PushEvents", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PushEvents indicates an expected call of PushEvents
|
||||
func (mr *MockRepositoryMockRecorder) PushEvents(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PushEvents", reflect.TypeOf((*MockRepository)(nil).PushEvents), arg0, arg1)
|
||||
}
|
||||
|
@ -17,10 +17,11 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
eventColumns = []string{"id", "creation_date", "event_type", "event_sequence", "previous_sequence", "event_data", "editor_service", "editor_user", "resource_owner", "aggregate_type", "aggregate_id", "aggregate_version"}
|
||||
expectedFilterEventsLimitFormat = regexp.MustCompile(selectEscaped + ` ORDER BY event_sequence LIMIT \$1`).String()
|
||||
expectedFilterEventsDescFormat = regexp.MustCompile(selectEscaped + ` ORDER BY event_sequence DESC`).String()
|
||||
expectedFilterEventsAggregateIDLimit = regexp.MustCompile(selectEscaped + ` WHERE aggregate_id = \$1 ORDER BY event_sequence LIMIT \$2`).String()
|
||||
expectedFilterEventsAggregateIDTypeLimit = regexp.MustCompile(selectEscaped + ` WHERE aggregate_id = \$1 AND aggregate_type IN \(\$2\) ORDER BY event_sequence LIMIT \$3`).String()
|
||||
expectedFilterEventsAggregateIDTypeLimit = regexp.MustCompile(selectEscaped + ` WHERE aggregate_id = \$1 AND aggregate_type = ANY\(\$2\) ORDER BY event_sequence LIMIT \$3`).String()
|
||||
expectedGetAllEvents = regexp.MustCompile(selectEscaped + ` ORDER BY event_sequence`).String()
|
||||
|
||||
expectedInsertStatement = regexp.MustCompile(`insert into eventstore\.events ` +
|
||||
@ -31,8 +32,8 @@ var (
|
||||
`ELSE NULL ` +
|
||||
`end ` +
|
||||
`where \(` +
|
||||
`\(select count\(id\) from eventstore\.events where event_sequence >= \$14 AND aggregate_type = \$15 AND aggregate_id = \$16\) = 1 OR ` +
|
||||
`\(\(select count\(id\) from eventstore\.events where aggregate_type = \$17 and aggregate_id = \$18\) = 0 AND \$19 = 0\)\) RETURNING id, event_sequence, creation_date`).String()
|
||||
`\(select count\(id\) from eventstore\.events where event_sequence >= COALESCE\(\$14, 0\) AND aggregate_type = \$15 AND aggregate_id = \$16\) = 1 OR ` +
|
||||
`\(\(select count\(id\) from eventstore\.events where aggregate_type = \$17 and aggregate_id = \$18\) = 0 AND COALESCE\(\$19, 0\) = 0\)\) RETURNING id, event_sequence, creation_date`).String()
|
||||
)
|
||||
|
||||
type dbMock struct {
|
||||
@ -107,8 +108,8 @@ func (db *dbMock) expectInsertEvent(e *models.Event, returnedID string, returned
|
||||
e.Type, e.AggregateType, e.AggregateID, e.AggregateVersion, sqlmock.AnyArg(), e.Data, e.EditorUser, e.EditorService, e.ResourceOwner,
|
||||
e.AggregateType, e.AggregateID,
|
||||
e.AggregateType, e.AggregateID,
|
||||
e.PreviousSequence, e.AggregateType, e.AggregateID,
|
||||
e.AggregateType, e.AggregateID, e.PreviousSequence,
|
||||
Sequence(e.PreviousSequence), e.AggregateType, e.AggregateID,
|
||||
e.AggregateType, e.AggregateID, Sequence(e.PreviousSequence),
|
||||
).
|
||||
WillReturnRows(
|
||||
sqlmock.NewRows([]string{"id", "event_sequence", "creation_date"}).
|
||||
@ -124,8 +125,8 @@ func (db *dbMock) expectInsertEventError(e *models.Event) *dbMock {
|
||||
e.Type, e.AggregateType, e.AggregateID, e.AggregateVersion, sqlmock.AnyArg(), e.Data, e.EditorUser, e.EditorService, e.ResourceOwner,
|
||||
e.AggregateType, e.AggregateID,
|
||||
e.AggregateType, e.AggregateID,
|
||||
e.PreviousSequence, e.AggregateType, e.AggregateID,
|
||||
e.AggregateType, e.AggregateID, e.PreviousSequence,
|
||||
Sequence(e.PreviousSequence), e.AggregateType, e.AggregateID,
|
||||
e.AggregateType, e.AggregateID, Sequence(e.PreviousSequence),
|
||||
).
|
||||
WillReturnError(sql.ErrTxDone)
|
||||
|
||||
@ -133,9 +134,9 @@ func (db *dbMock) expectInsertEventError(e *models.Event) *dbMock {
|
||||
}
|
||||
|
||||
func (db *dbMock) expectFilterEventsLimit(limit uint64, eventCount int) *dbMock {
|
||||
rows := sqlmock.NewRows([]string{"id", "creation_date"})
|
||||
rows := sqlmock.NewRows(eventColumns)
|
||||
for i := 0; i < eventCount; i++ {
|
||||
rows.AddRow(fmt.Sprint("event", i), time.Now())
|
||||
rows.AddRow(fmt.Sprint("event", i), time.Now(), "eventType", Sequence(i+1), Sequence(i), nil, "svc", "hodor", "org", "aggType", "aggID", "v1.0.0")
|
||||
}
|
||||
db.mock.ExpectQuery(expectedFilterEventsLimitFormat).
|
||||
WithArgs(limit).
|
||||
@ -144,9 +145,9 @@ func (db *dbMock) expectFilterEventsLimit(limit uint64, eventCount int) *dbMock
|
||||
}
|
||||
|
||||
func (db *dbMock) expectFilterEventsDesc(eventCount int) *dbMock {
|
||||
rows := sqlmock.NewRows([]string{"id", "creation_date"})
|
||||
rows := sqlmock.NewRows(eventColumns)
|
||||
for i := eventCount; i > 0; i-- {
|
||||
rows.AddRow(fmt.Sprint("event", i), time.Now())
|
||||
rows.AddRow(fmt.Sprint("event", i), time.Now(), "eventType", Sequence(i+1), Sequence(i), nil, "svc", "hodor", "org", "aggType", "aggID", "v1.0.0")
|
||||
}
|
||||
db.mock.ExpectQuery(expectedFilterEventsDescFormat).
|
||||
WillReturnRows(rows)
|
||||
@ -154,9 +155,9 @@ func (db *dbMock) expectFilterEventsDesc(eventCount int) *dbMock {
|
||||
}
|
||||
|
||||
func (db *dbMock) expectFilterEventsAggregateIDLimit(aggregateID string, limit uint64) *dbMock {
|
||||
rows := sqlmock.NewRows([]string{"id", "creation_date"})
|
||||
rows := sqlmock.NewRows(eventColumns)
|
||||
for i := limit; i > 0; i-- {
|
||||
rows.AddRow(fmt.Sprint("event", i), time.Now())
|
||||
rows.AddRow(fmt.Sprint("event", i), time.Now(), "eventType", Sequence(i+1), Sequence(i), nil, "svc", "hodor", "org", "aggType", "aggID", "v1.0.0")
|
||||
}
|
||||
db.mock.ExpectQuery(expectedFilterEventsAggregateIDLimit).
|
||||
WithArgs(aggregateID, limit).
|
||||
@ -165,9 +166,9 @@ func (db *dbMock) expectFilterEventsAggregateIDLimit(aggregateID string, limit u
|
||||
}
|
||||
|
||||
func (db *dbMock) expectFilterEventsAggregateIDTypeLimit(aggregateID, aggregateType string, limit uint64) *dbMock {
|
||||
rows := sqlmock.NewRows([]string{"id", "creation_date"})
|
||||
rows := sqlmock.NewRows(eventColumns)
|
||||
for i := limit; i > 0; i-- {
|
||||
rows.AddRow(fmt.Sprint("event", i), time.Now())
|
||||
rows.AddRow(fmt.Sprint("event", i), time.Now(), "eventType", Sequence(i+1), Sequence(i), nil, "svc", "hodor", "org", "aggType", "aggID", "v1.0.0")
|
||||
}
|
||||
db.mock.ExpectQuery(expectedFilterEventsAggregateIDTypeLimit).
|
||||
WithArgs(aggregateID, pq.Array([]string{aggregateType}), limit).
|
||||
|
@ -57,14 +57,14 @@ func (db *SQL) Filter(ctx context.Context, searchQuery *es_models.SearchQuery) (
|
||||
|
||||
for rows.Next() {
|
||||
event := new(models.Event)
|
||||
events = append(events, event)
|
||||
var previousSequence Sequence
|
||||
|
||||
rows.Scan(
|
||||
err = rows.Scan(
|
||||
&event.ID,
|
||||
&event.CreationDate,
|
||||
&event.Type,
|
||||
&event.Sequence,
|
||||
&event.PreviousSequence,
|
||||
&previousSequence,
|
||||
&event.Data,
|
||||
&event.EditorService,
|
||||
&event.EditorUser,
|
||||
@ -73,6 +73,14 @@ func (db *SQL) Filter(ctx context.Context, searchQuery *es_models.SearchQuery) (
|
||||
&event.AggregateID,
|
||||
&event.AggregateVersion,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
logging.Log("SQL-wHNPo").WithError(err).Warn("unable to scan row")
|
||||
return nil, errors.ThrowInternal(err, "SQL-BfZwF", "unable to scan row")
|
||||
}
|
||||
|
||||
event.PreviousSequence = uint64(previousSequence)
|
||||
events = append(events, event)
|
||||
}
|
||||
|
||||
return events, nil
|
||||
@ -98,7 +106,7 @@ func prepareWhere(searchQuery *es_models.SearchQuery) (clause string, values []i
|
||||
for i, filter := range searchQuery.Filters {
|
||||
value := filter.GetValue()
|
||||
switch value.(type) {
|
||||
case []bool, []float64, []int64, []string, *[]bool, *[]float64, *[]int64, *[]string:
|
||||
case []bool, []float64, []int64, []string, []models.AggregateType, *[]bool, *[]float64, *[]int64, *[]string, *[]models.AggregateType:
|
||||
value = pq.Array(value)
|
||||
}
|
||||
|
||||
@ -118,7 +126,7 @@ func getCondition(filter *es_models.Filter) string {
|
||||
|
||||
func prepareConditionFormat(operation es_models.Operation) string {
|
||||
if operation == es_models.Operation_In {
|
||||
return "%s %s (?)"
|
||||
return "%s %s ANY(?)"
|
||||
}
|
||||
return "%s %s ?"
|
||||
}
|
||||
@ -133,9 +141,9 @@ func getField(field es_models.Field) string {
|
||||
return "event_sequence"
|
||||
case es_models.Field_ResourceOwner:
|
||||
return "resource_owner"
|
||||
case es_models.Field_ModifierService:
|
||||
case es_models.Field_EditorService:
|
||||
return "editor_service"
|
||||
case es_models.Field_ModifierUser:
|
||||
case es_models.Field_EditorUser:
|
||||
return "editor_user"
|
||||
}
|
||||
return ""
|
||||
@ -143,14 +151,12 @@ func getField(field es_models.Field) string {
|
||||
|
||||
func getOperation(operation es_models.Operation) string {
|
||||
switch operation {
|
||||
case es_models.Operation_Equals:
|
||||
case es_models.Operation_Equals, es_models.Operation_In:
|
||||
return "="
|
||||
case es_models.Operation_Greater:
|
||||
return ">"
|
||||
case es_models.Operation_Less:
|
||||
return "<"
|
||||
case es_models.Operation_In:
|
||||
return "IN"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ func TestSQL_Filter(t *testing.T) {
|
||||
}
|
||||
events, err := sql.Filter(context.Background(), tt.args.searchQuery)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("SQL.UnlockAggregates() error = %v, wantErr %v", err, tt.wantErr)
|
||||
t.Errorf("SQL.Filter() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if tt.eventsLen != 0 && len(events) != tt.eventsLen {
|
||||
t.Errorf("events has wrong length got: %d want %d", len(events), tt.eventsLen)
|
||||
@ -142,7 +142,7 @@ func Test_getCondition(t *testing.T) {
|
||||
args: args{
|
||||
filter: es_models.NewFilter(es_models.Field_AggregateType, []string{"a", "b"}, es_models.Operation_In),
|
||||
},
|
||||
want: "aggregate_type IN (?)",
|
||||
want: "aggregate_type = ANY(?)",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -20,9 +20,9 @@ const insertStmt = "insert into eventstore.events " +
|
||||
"end " +
|
||||
"where (" +
|
||||
// exactly one event of requested aggregate must have a >= sequence (last inserted event)
|
||||
"(select count(id) from eventstore.events where event_sequence >= $14 AND aggregate_type = $15 AND aggregate_id = $16) = 1 OR " +
|
||||
"(select count(id) from eventstore.events where event_sequence >= COALESCE($14, 0) AND aggregate_type = $15 AND aggregate_id = $16) = 1 OR " +
|
||||
// previous sequence = 0, no events must exist for the requested aggregate
|
||||
"((select count(id) from eventstore.events where aggregate_type = $17 and aggregate_id = $18) = 0 AND $19 = 0)) " +
|
||||
"((select count(id) from eventstore.events where aggregate_type = $17 and aggregate_id = $18) = 0 AND COALESCE($19, 0) = 0)) " +
|
||||
"RETURNING id, event_sequence, creation_date"
|
||||
|
||||
func (db *SQL) PushAggregates(ctx context.Context, aggregates ...*models.Aggregate) (err error) {
|
||||
@ -52,10 +52,8 @@ func (db *SQL) PushAggregates(ctx context.Context, aggregates ...*models.Aggrega
|
||||
}
|
||||
|
||||
func insertEvents(stmt *sql.Stmt, events []*models.Event) error {
|
||||
previousSequence := events[0].PreviousSequence
|
||||
currentSequence := Sequence(events[0].PreviousSequence)
|
||||
for _, event := range events {
|
||||
event.PreviousSequence = previousSequence
|
||||
|
||||
if event.Data == nil || len(event.Data) == 0 {
|
||||
//json decoder failes with EOF if json text is empty
|
||||
event.Data = []byte("{}")
|
||||
@ -64,8 +62,8 @@ func insertEvents(stmt *sql.Stmt, events []*models.Event) error {
|
||||
rows, err := stmt.Query(event.Type, event.AggregateType, event.AggregateID, event.AggregateVersion, event.CreationDate, event.Data, event.EditorUser, event.EditorService, event.ResourceOwner,
|
||||
event.AggregateType, event.AggregateID,
|
||||
event.AggregateType, event.AggregateID,
|
||||
event.PreviousSequence, event.AggregateType, event.AggregateID,
|
||||
event.AggregateType, event.AggregateID, event.PreviousSequence)
|
||||
currentSequence, event.AggregateType, event.AggregateID,
|
||||
event.AggregateType, event.AggregateID, currentSequence)
|
||||
|
||||
if err != nil {
|
||||
logging.Log("SQL-EXA0q").WithError(err).Info("query failed")
|
||||
@ -76,7 +74,7 @@ func insertEvents(stmt *sql.Stmt, events []*models.Event) error {
|
||||
rowInserted := false
|
||||
for rows.Next() {
|
||||
rowInserted = true
|
||||
err = rows.Scan(&event.ID, &event.Sequence, &event.CreationDate)
|
||||
err = rows.Scan(&event.ID, ¤tSequence, &event.CreationDate)
|
||||
logging.Log("SQL-rAvLD").OnError(err).Info("unable to scan result into event")
|
||||
}
|
||||
|
||||
@ -84,7 +82,7 @@ func insertEvents(stmt *sql.Stmt, events []*models.Event) error {
|
||||
return errors.ThrowAlreadyExists(nil, "SQL-GKcAa", "wrong sequence")
|
||||
}
|
||||
|
||||
previousSequence = event.Sequence
|
||||
event.Sequence = uint64(currentSequence)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
27
internal/eventstore/internal/repository/sql/sequence.go
Normal file
27
internal/eventstore/internal/repository/sql/sequence.go
Normal file
@ -0,0 +1,27 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
)
|
||||
|
||||
// Sequence represents a number that may be null.
|
||||
// Sequence implements the sql.Scanner interface so
|
||||
type Sequence uint64
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *Sequence) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
*n = 0
|
||||
return nil
|
||||
}
|
||||
*n = Sequence(value.(int64))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (seq Sequence) Value() (driver.Value, error) {
|
||||
if seq == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return int64(seq), nil
|
||||
}
|
@ -7,6 +7,6 @@ const (
|
||||
Field_AggregateID
|
||||
Field_LatestSequence
|
||||
Field_ResourceOwner
|
||||
Field_ModifierService
|
||||
Field_ModifierUser
|
||||
Field_EditorService
|
||||
Field_EditorUser
|
||||
)
|
||||
|
@ -33,7 +33,7 @@ func (q *SearchQuery) AggregateIDFilter(id string) *SearchQuery {
|
||||
return q.setFilter(NewFilter(Field_AggregateID, id, Operation_Equals))
|
||||
}
|
||||
|
||||
func (q *SearchQuery) AggregateTypeFilter(types ...string) *SearchQuery {
|
||||
func (q *SearchQuery) AggregateTypeFilter(types ...AggregateType) *SearchQuery {
|
||||
return q.setFilter(NewFilter(Field_AggregateType, types, Operation_In))
|
||||
}
|
||||
|
||||
|
25
internal/management/auth/token_verifier.go
Normal file
25
internal/management/auth/token_verifier.go
Normal file
@ -0,0 +1,25 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
)
|
||||
|
||||
type TokenVerifier struct {
|
||||
}
|
||||
|
||||
func Start() (v *TokenVerifier) {
|
||||
return new(TokenVerifier)
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) VerifyAccessToken(ctx context.Context, token string) (string, string, string, error) {
|
||||
return "", "", "", nil
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) ResolveGrants(ctx context.Context, userID, orgID string) ([]*auth.Grant, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) GetProjectIDByClientID(ctx context.Context, clientID string) (string, error) {
|
||||
return "", nil
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
package management
|
||||
|
||||
type Config struct{}
|
73
internal/management/repository/eventsourcing/project.go
Normal file
73
internal/management/repository/eventsourcing/project.go
Normal file
@ -0,0 +1,73 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
||||
)
|
||||
|
||||
type ProjectRepo struct {
|
||||
ProjectEvents *proj_event.ProjectEventstore
|
||||
//view *view.View
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) ProjectByID(ctx context.Context, id string) (project *proj_model.Project, err error) {
|
||||
//viewProject, err := repo.view.ProjectByID(id)
|
||||
//if err != nil && !caos_errs.IsNotFound(err) {
|
||||
// return nil, err
|
||||
//}
|
||||
//if viewProject != nil {
|
||||
// project = org_view.ProjectToModel(viewProject)
|
||||
//} else {
|
||||
project = proj_model.NewProject(id)
|
||||
//}
|
||||
return repo.ProjectEvents.ProjectByID(ctx, project)
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) CreateProject(ctx context.Context, name string) (*proj_model.Project, error) {
|
||||
project := &proj_model.Project{Name: name}
|
||||
project, err := repo.ProjectEvents.CreateProject(ctx, project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return project, nil
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) UpdateProject(ctx context.Context, project *proj_model.Project) (*proj_model.Project, error) {
|
||||
existingProject, err := repo.ProjectByID(ctx, project.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
project, err = repo.ProjectEvents.UpdateProject(ctx, existingProject, project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return project, err
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) DeactivateProject(ctx context.Context, id string) (*proj_model.Project, error) {
|
||||
project, err := repo.ProjectByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
project, err = repo.ProjectEvents.DeactivateProject(ctx, project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return project, err
|
||||
}
|
||||
|
||||
func (repo *ProjectRepo) ReactivateProject(ctx context.Context, id string) (*proj_model.Project, error) {
|
||||
project, err := repo.ProjectByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
project, err = repo.ProjectEvents.ReactivateProject(ctx, project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return project, err
|
||||
}
|
48
internal/management/repository/eventsourcing/repository.go
Normal file
48
internal/management/repository/eventsourcing/repository.go
Normal file
@ -0,0 +1,48 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
||||
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Eventstore es_int.Config
|
||||
//View view.ViewConfig
|
||||
//Spooler spooler.SpoolerConfig
|
||||
}
|
||||
|
||||
type EsRepository struct {
|
||||
//spooler *es_spooler.Spooler
|
||||
ProjectRepo
|
||||
}
|
||||
|
||||
func Start(conf Config) (*EsRepository, error) {
|
||||
es, err := es_int.Start(conf.Eventstore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//view, sql, err := mgmt_view.StartView(conf.View)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
//conf.Spooler.View = view
|
||||
//conf.Spooler.EsClient = es.Client
|
||||
//conf.Spooler.SQL = sql
|
||||
//spool := spooler.StartSpooler(conf.Spooler)
|
||||
|
||||
project, err := es_proj.StartProject(es_proj.ProjectConfig{Eventstore: es})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &EsRepository{
|
||||
ProjectRepo{project},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (repo *EsRepository) Health() error {
|
||||
return repo.ProjectEvents.Health(context.Background())
|
||||
}
|
14
internal/management/repository/project.go
Normal file
14
internal/management/repository/project.go
Normal file
@ -0,0 +1,14 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
)
|
||||
|
||||
type ProjectRepository interface {
|
||||
ProjectByID(ctx context.Context, id string) (*model.Project, error)
|
||||
CreateProject(ctx context.Context, name string) (*model.Project, error)
|
||||
UpdateProject(ctx context.Context, project *model.Project) (*model.Project, error)
|
||||
DeactivateProject(ctx context.Context, id string) (*model.Project, error)
|
||||
ReactivateProject(ctx context.Context, id string) (*model.Project, error)
|
||||
}
|
6
internal/management/repository/repository.go
Normal file
6
internal/management/repository/repository.go
Normal file
@ -0,0 +1,6 @@
|
||||
package repository
|
||||
|
||||
type Repository interface {
|
||||
Health() error
|
||||
ProjectRepository
|
||||
}
|
35
internal/project/model/project.go
Normal file
35
internal/project/model/project.go
Normal file
@ -0,0 +1,35 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
in_model "github.com/caos/zitadel/internal/model"
|
||||
)
|
||||
|
||||
type Project struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
State ProjectState
|
||||
Name string
|
||||
}
|
||||
|
||||
type ProjectState in_model.Enum
|
||||
|
||||
var states = []string{"Active", "Inactive"}
|
||||
|
||||
func NewProject(id string) *Project {
|
||||
return &Project{ObjectRoot: es_models.ObjectRoot{ID: id}, State: Active}
|
||||
}
|
||||
|
||||
func (p *Project) IsActive() bool {
|
||||
if p.State == Active {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Project) IsValid() bool {
|
||||
if p.Name == "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
23
internal/project/model/state.go
Normal file
23
internal/project/model/state.go
Normal file
@ -0,0 +1,23 @@
|
||||
package model
|
||||
|
||||
type state int32
|
||||
|
||||
func (s state) String() string {
|
||||
return states[s]
|
||||
}
|
||||
|
||||
const (
|
||||
Active state = iota
|
||||
Inactive
|
||||
)
|
||||
|
||||
func ProjectStateToInt(s ProjectState) int32 {
|
||||
if s == nil {
|
||||
return 0
|
||||
}
|
||||
return int32(s.(state))
|
||||
}
|
||||
|
||||
func ProjectStateFromInt(index int32) ProjectState {
|
||||
return state(index)
|
||||
}
|
37
internal/project/model/types.go
Normal file
37
internal/project/model/types.go
Normal file
@ -0,0 +1,37 @@
|
||||
package model
|
||||
|
||||
import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
const (
|
||||
ProjectAggregate models.AggregateType = "project"
|
||||
|
||||
ProjectAdded models.EventType = "project.added"
|
||||
ProjectChanged models.EventType = "project.changed"
|
||||
ProjectDeactivated models.EventType = "project.deactivated"
|
||||
ProjectReactivated models.EventType = "project.reactivated"
|
||||
|
||||
ProjectMemberAdded models.EventType = "project.member.added"
|
||||
ProjectMemberChanged models.EventType = "project.member.changed"
|
||||
ProjectMemberRemoved models.EventType = "project.member.removed"
|
||||
|
||||
ProjectRoleAdded models.EventType = "project.role.added"
|
||||
ProjectRoleRemoved models.EventType = "project.role.removed"
|
||||
|
||||
ProjectGrantAdded models.EventType = "project.grant.added"
|
||||
ProjectGrantChanged models.EventType = "project.grant.changed"
|
||||
ProjectGrantDeactivated models.EventType = "project.grant.deactivated"
|
||||
ProjectGrantReactivated models.EventType = "project.grant.reactivated"
|
||||
|
||||
GrantMemberAdded models.EventType = "project.grant.member.added"
|
||||
GrantMemberChanged models.EventType = "project.grant.member.changed"
|
||||
GrantMemberRemoved models.EventType = "project.grant.member.removed"
|
||||
|
||||
ApplicationAdded models.EventType = "project.application.added"
|
||||
ApplicationChanged models.EventType = "project.application.changed"
|
||||
ApplicationDeactivated models.EventType = "project.application.deactivated"
|
||||
ApplicationReactivated models.EventType = "project.application.reactivated"
|
||||
|
||||
OIDCConfigAdded models.EventType = "project.application.config.oidc.added"
|
||||
OIDCConfigChanged models.EventType = "project.application.config.oidc.changed"
|
||||
OIDCConfigSecretChanged models.EventType = "project.application.config.oidc.secret.changed"
|
||||
)
|
55
internal/project/repository/eventsourcing/events.go
Normal file
55
internal/project/repository/eventsourcing/events.go
Normal file
@ -0,0 +1,55 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/caos/logging"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
)
|
||||
|
||||
func ProjectFromEvents(project *Project, events ...*es_models.Event) (*Project, error) {
|
||||
if project == nil {
|
||||
project = &Project{}
|
||||
}
|
||||
|
||||
return project, project.AppendEvents(events...)
|
||||
}
|
||||
|
||||
func (p *Project) AppendEvents(events ...*es_models.Event) error {
|
||||
for _, event := range events {
|
||||
if err := p.AppendEvent(event); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Project) AppendEvent(event *es_models.Event) error {
|
||||
p.ObjectRoot.AppendEvent(event)
|
||||
|
||||
switch event.Type {
|
||||
case model.ProjectAdded, model.ProjectChanged:
|
||||
if err := json.Unmarshal(event.Data, p); err != nil {
|
||||
logging.Log("EVEN-idl93").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
p.State = model.ProjectStateToInt(model.Active)
|
||||
return nil
|
||||
case model.ProjectDeactivated:
|
||||
return p.appendDeactivatedEvent()
|
||||
case model.ProjectReactivated:
|
||||
return p.appendReactivatedEvent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Project) appendDeactivatedEvent() error {
|
||||
p.State = model.ProjectStateToInt(model.Inactive)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Project) appendReactivatedEvent() error {
|
||||
p.State = model.ProjectStateToInt(model.Active)
|
||||
return nil
|
||||
}
|
169
internal/project/repository/eventsourcing/events_test.go
Normal file
169
internal/project/repository/eventsourcing/events_test.go
Normal file
@ -0,0 +1,169 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestProjectFromEvents(t *testing.T) {
|
||||
type args struct {
|
||||
event []*es_models.Event
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "project from events, ok",
|
||||
args: args{
|
||||
event: []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded},
|
||||
},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "project from events, nil project",
|
||||
args: args{
|
||||
event: []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded},
|
||||
},
|
||||
project: nil,
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.project != nil {
|
||||
data, _ := json.Marshal(tt.args.project)
|
||||
tt.args.event[0].Data = data
|
||||
}
|
||||
result, _ := ProjectFromEvents(tt.args.project, tt.args.event...)
|
||||
if result.Name != tt.result.Name {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.result.Name, result.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendEvent(t *testing.T) {
|
||||
type args struct {
|
||||
event *es_models.Event
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append added event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "append change event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectChanged},
|
||||
project: &Project{Name: "ProjectName"},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active), Name: "ProjectName"},
|
||||
},
|
||||
{
|
||||
name: "append deactivate event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectDeactivated},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Inactive)},
|
||||
},
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
event: &es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectReactivated},
|
||||
},
|
||||
result: &Project{ObjectRoot: es_models.ObjectRoot{ID: "ID"}, State: int32(model.Active)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.project != nil {
|
||||
data, _ := json.Marshal(tt.args.project)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
result := &Project{}
|
||||
result.AppendEvent(tt.args.event)
|
||||
if result.State != tt.result.State {
|
||||
t.Errorf("got wrong result state: expected: %v, actual: %v ", tt.result.State, result.State)
|
||||
}
|
||||
if result.Name != tt.result.Name {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.result.Name, result.Name)
|
||||
}
|
||||
if result.ObjectRoot.ID != tt.result.ObjectRoot.ID {
|
||||
t.Errorf("got wrong result id: expected: %v, actual: %v ", tt.result.ObjectRoot.ID, result.ObjectRoot.ID)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendDeactivatedEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
project: &Project{},
|
||||
},
|
||||
result: &Project{State: int32(model.Inactive)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.args.project.appendDeactivatedEvent()
|
||||
if tt.args.project.State != tt.result.State {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, tt.args.project)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendReactivatedEvent(t *testing.T) {
|
||||
type args struct {
|
||||
project *Project
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Project
|
||||
}{
|
||||
{
|
||||
name: "append reactivate event",
|
||||
args: args{
|
||||
project: &Project{},
|
||||
},
|
||||
result: &Project{State: int32(model.Active)},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.args.project.appendReactivatedEvent()
|
||||
if tt.args.project.State != tt.result.State {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, tt.args.project)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
110
internal/project/repository/eventsourcing/eventstore.go
Normal file
110
internal/project/repository/eventsourcing/eventstore.go
Normal file
@ -0,0 +1,110 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
)
|
||||
|
||||
type ProjectEventstore struct {
|
||||
es_int.Eventstore
|
||||
}
|
||||
|
||||
type ProjectConfig struct {
|
||||
es_int.Eventstore
|
||||
}
|
||||
|
||||
func StartProject(conf ProjectConfig) (*ProjectEventstore, error) {
|
||||
return &ProjectEventstore{Eventstore: conf.Eventstore}, nil
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ProjectByID(ctx context.Context, project *proj_model.Project) (*proj_model.Project, error) {
|
||||
filter, err := ProjectByIDQuery(project.ID, project.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := es.Eventstore.FilterEvents(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(events) == 0 {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "EVENT-8due3", "Could not find project events")
|
||||
}
|
||||
foundProject, err := ProjectFromEvents(nil, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ProjectToModel(foundProject), nil
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) CreateProject(ctx context.Context, project *proj_model.Project) (*proj_model.Project, error) {
|
||||
if !project.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Name is required")
|
||||
}
|
||||
project.State = proj_model.Active
|
||||
repoProject := ProjectFromModel(project)
|
||||
projectAggregate, err := ProjectCreateAggregate(ctx, es.Eventstore.AggregateCreator(), repoProject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = es.PushAggregates(ctx, projectAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoProject.AppendEvents(projectAggregate.Events...)
|
||||
return ProjectToModel(repoProject), nil
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) UpdateProject(ctx context.Context, existing *proj_model.Project, new *proj_model.Project) (*proj_model.Project, error) {
|
||||
if !new.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Name is required")
|
||||
}
|
||||
repoExisting := ProjectFromModel(existing)
|
||||
repoNew := ProjectFromModel(new)
|
||||
projectAggregate, err := ProjectUpdateAggregate(ctx, es.AggregateCreator(), repoExisting, repoNew)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = es.PushAggregates(ctx, projectAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoExisting.AppendEvents(projectAggregate.Events...)
|
||||
return ProjectToModel(repoExisting), nil
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) DeactivateProject(ctx context.Context, existing *proj_model.Project) (*proj_model.Project, error) {
|
||||
if !existing.IsActive() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-die45", "project must be active")
|
||||
}
|
||||
repoExisting := ProjectFromModel(existing)
|
||||
projectAggregate, err := ProjectDeactivateAggregate(ctx, es.AggregateCreator(), repoExisting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = es.PushAggregates(ctx, projectAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoExisting.AppendEvents(projectAggregate.Events...)
|
||||
return ProjectToModel(repoExisting), nil
|
||||
}
|
||||
|
||||
func (es *ProjectEventstore) ReactivateProject(ctx context.Context, existing *proj_model.Project) (*proj_model.Project, error) {
|
||||
if existing.IsActive() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-die45", "project must be inactive")
|
||||
}
|
||||
repoExisting := ProjectFromModel(existing)
|
||||
projectAggregate, err := ProjectReactivateAggregate(ctx, es.AggregateCreator(), repoExisting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = es.PushAggregates(ctx, projectAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoExisting.AppendEvents(projectAggregate.Events...)
|
||||
return ProjectToModel(repoExisting), nil
|
||||
}
|
33
internal/project/repository/eventsourcing/eventstore_mock.go
Normal file
33
internal/project/repository/eventsourcing/eventstore_mock.go
Normal file
@ -0,0 +1,33 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/caos/zitadel/internal/eventstore/mock"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func GetMockProjectByIDOK(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
data, _ := json.Marshal(Project{Name: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs}
|
||||
}
|
||||
|
||||
func GetMockProjectByIDNoEvents(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
events := []*es_models.Event{}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs}
|
||||
}
|
||||
|
||||
func GetMockManipulateProject(ctrl *gomock.Controller) *ProjectEventstore {
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return &ProjectEventstore{Eventstore: mockEs}
|
||||
}
|
311
internal/project/repository/eventsourcing/eventstore_test.go
Normal file
311
internal/project/repository/eventsourcing/eventstore_test.go
Normal file
@ -0,0 +1,311 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestProjectByID(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *ProjectEventstore
|
||||
project *model.Project
|
||||
}
|
||||
type res struct {
|
||||
project *model.Project
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project from events, ok",
|
||||
args: args{
|
||||
es: GetMockProjectByIDOK(ctrl),
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "project from events, no events",
|
||||
args: args{
|
||||
es: GetMockProjectByIDNoEvents(ctrl),
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "project from events, no id",
|
||||
args: args{
|
||||
es: GetMockProjectByIDNoEvents(ctrl),
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.ProjectByID(nil, tt.args.project)
|
||||
|
||||
if !tt.res.wantErr && result.ID != tt.res.project.ID {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.project.ID, result.ID)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateProject(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *ProjectEventstore
|
||||
ctx context.Context
|
||||
project *model.Project
|
||||
}
|
||||
type res struct {
|
||||
project *model.Project
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project from events, ok",
|
||||
args: args{
|
||||
es: GetMockManipulateProject(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "Name"},
|
||||
},
|
||||
res: res{
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "Name"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create project no name",
|
||||
args: args{
|
||||
es: GetMockManipulateProject(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.CreateProject(tt.args.ctx, tt.args.project)
|
||||
|
||||
if !tt.res.wantErr && result.ID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Name != tt.res.project.Name {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.project.Name, result.Name)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateProject(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *ProjectEventstore
|
||||
ctx context.Context
|
||||
existing *model.Project
|
||||
new *model.Project
|
||||
}
|
||||
type res struct {
|
||||
project *model.Project
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project from events, ok",
|
||||
args: args{
|
||||
es: GetMockManipulateProject(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "Name"},
|
||||
new: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "NameNew"},
|
||||
},
|
||||
res: res{
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "NameNew"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create project no name",
|
||||
args: args{
|
||||
es: GetMockManipulateProject(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "Name"},
|
||||
new: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: ""},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.UpdateProject(tt.args.ctx, tt.args.existing, tt.args.new)
|
||||
|
||||
if !tt.res.wantErr && result.ID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Name != tt.res.project.Name {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.project.Name, result.Name)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeactivateProject(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *ProjectEventstore
|
||||
ctx context.Context
|
||||
existing *model.Project
|
||||
new *model.Project
|
||||
}
|
||||
type res struct {
|
||||
project *model.Project
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "deactivate project, ok",
|
||||
args: args{
|
||||
es: GetMockManipulateProject(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "Name", State: model.Active},
|
||||
},
|
||||
res: res{
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "NameNew", State: model.Inactive},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deactivate project with inactive state",
|
||||
args: args{
|
||||
es: GetMockManipulateProject(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "Name", State: model.Inactive},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.DeactivateProject(tt.args.ctx, tt.args.existing)
|
||||
|
||||
if !tt.res.wantErr && result.ID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.State != tt.res.project.State {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.project.State, result.State)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReactivateProject(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *ProjectEventstore
|
||||
ctx context.Context
|
||||
existing *model.Project
|
||||
new *model.Project
|
||||
}
|
||||
type res struct {
|
||||
project *model.Project
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "deactivate project, ok",
|
||||
args: args{
|
||||
es: GetMockManipulateProject(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "Name", State: model.Inactive},
|
||||
},
|
||||
res: res{
|
||||
project: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "NameNew", State: model.Active},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deactivate project with inactive state",
|
||||
args: args{
|
||||
es: GetMockManipulateProject(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Project{ObjectRoot: es_models.ObjectRoot{ID: "ID", Sequence: 1}, Name: "Name", State: model.Active},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.ReactivateProject(tt.args.ctx, tt.args.existing)
|
||||
|
||||
if !tt.res.wantErr && result.ID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.State != tt.res.project.State {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.project.State, result.State)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
131
internal/project/repository/eventsourcing/project.go
Normal file
131
internal/project/repository/eventsourcing/project.go
Normal file
@ -0,0 +1,131 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/sony/sonyflake"
|
||||
)
|
||||
|
||||
var idGenerator = sonyflake.NewSonyflake(sonyflake.Settings{})
|
||||
|
||||
const (
|
||||
projectVersion = "v1"
|
||||
)
|
||||
|
||||
type Project struct {
|
||||
es_models.ObjectRoot
|
||||
Name string `json:"name,omitempty"`
|
||||
State int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (p *Project) Changes(changed *Project) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 1)
|
||||
if changed.Name != "" && p.Name != changed.Name {
|
||||
changes["name"] = changed.Name
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func ProjectFromModel(project *model.Project) *Project {
|
||||
return &Project{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
ID: project.ObjectRoot.ID,
|
||||
Sequence: project.Sequence,
|
||||
ChangeDate: project.ChangeDate,
|
||||
CreationDate: project.CreationDate,
|
||||
},
|
||||
Name: project.Name,
|
||||
State: model.ProjectStateToInt(project.State),
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectToModel(project *Project) *model.Project {
|
||||
return &model.Project{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
ID: project.ID,
|
||||
ChangeDate: project.ChangeDate,
|
||||
CreationDate: project.CreationDate,
|
||||
Sequence: project.Sequence,
|
||||
},
|
||||
Name: project.Name,
|
||||
State: model.ProjectStateFromInt(project.State),
|
||||
}
|
||||
}
|
||||
|
||||
func ProjectByIDQuery(id string, latestSequence uint64) (*es_models.SearchQuery, error) {
|
||||
if id == "" {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dke74", "id should be filled")
|
||||
}
|
||||
return ProjectQuery(latestSequence).
|
||||
AggregateIDFilter(id), nil
|
||||
}
|
||||
|
||||
func ProjectQuery(latestSequence uint64) *es_models.SearchQuery {
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.ProjectAggregate).
|
||||
LatestSequenceFilter(latestSequence)
|
||||
}
|
||||
|
||||
func ProjectAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, id string, sequence uint64) (*es_models.Aggregate, error) {
|
||||
return aggCreator.NewAggregate(ctx, id, model.ProjectAggregate, projectVersion, sequence)
|
||||
}
|
||||
|
||||
func ProjectCreateAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, project *Project) (*es_models.Aggregate, error) {
|
||||
if project == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-kdie6", "project should not be nil")
|
||||
}
|
||||
var err error
|
||||
id, err := idGenerator.NextID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
project.ID = strconv.FormatUint(id, 10)
|
||||
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, project.ID, project.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return agg.AppendEvent(model.ProjectAdded, project)
|
||||
}
|
||||
|
||||
func ProjectUpdateAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, existing *Project, new *Project) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dk93d", "existing project should not be nil")
|
||||
}
|
||||
if new == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dhr74", "new project should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing.ID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := existing.Changes(new)
|
||||
return agg.AppendEvent(model.ProjectChanged, changes)
|
||||
}
|
||||
|
||||
func ProjectDeactivateAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, existing *Project) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-ueh45", "existing project should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing.ID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.ProjectDeactivated, nil)
|
||||
}
|
||||
|
||||
func ProjectReactivateAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, existing *Project) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-37dur", "existing project should not be nil")
|
||||
}
|
||||
agg, err := ProjectAggregate(ctx, aggCreator, existing.ID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.ProjectReactivated, nil)
|
||||
}
|
453
internal/project/repository/eventsourcing/project_test.go
Normal file
453
internal/project/repository/eventsourcing/project_test.go
Normal file
@ -0,0 +1,453 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestChanges(t *testing.T) {
|
||||
type args struct {
|
||||
existing *Project
|
||||
new *Project
|
||||
}
|
||||
type res struct {
|
||||
changesLen int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project name changes",
|
||||
args: args{
|
||||
existing: &Project{Name: "Name"},
|
||||
new: &Project{Name: "NameChanged"},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes",
|
||||
args: args{
|
||||
existing: &Project{Name: "Name"},
|
||||
new: &Project{Name: "Name"},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
changes := tt.args.existing.Changes(tt.args.new)
|
||||
if len(changes) != tt.res.changesLen {
|
||||
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectByIDQuery(t *testing.T) {
|
||||
type args struct {
|
||||
id string
|
||||
sequence uint64
|
||||
}
|
||||
type res struct {
|
||||
filterLen int
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project by id query ok",
|
||||
args: args{
|
||||
id: "ID",
|
||||
sequence: 1,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "project by id query, no id",
|
||||
args: args{
|
||||
sequence: 1,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 3,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
query, err := ProjectByIDQuery(tt.args.id, tt.args.sequence)
|
||||
if !tt.res.wantErr && query == nil {
|
||||
t.Errorf("query should not be nil")
|
||||
}
|
||||
if !tt.res.wantErr && len(query.Filters) != tt.res.filterLen {
|
||||
t.Errorf("got wrong filter len: expected: %v, actual: %v ", tt.res.filterLen, len(query.Filters))
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectQuery(t *testing.T) {
|
||||
type args struct {
|
||||
sequence uint64
|
||||
}
|
||||
type res struct {
|
||||
filterLen int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project query ok",
|
||||
args: args{
|
||||
sequence: 1,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
query := ProjectQuery(tt.args.sequence)
|
||||
if query == nil {
|
||||
t.Errorf("query should not be nil")
|
||||
}
|
||||
if len(query.Filters) != tt.res.filterLen {
|
||||
t.Errorf("got wrong filter len: expected: %v, actual: %v ", tt.res.filterLen, len(query.Filters))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
aggCreator *models.AggregateCreator
|
||||
id string
|
||||
sequence uint64
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
aggType models.AggregateType
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
id: "ID",
|
||||
sequence: 1,
|
||||
},
|
||||
res: res{
|
||||
eventLen: 0,
|
||||
aggType: model.ProjectAggregate,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, _ := ProjectAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.id, tt.args.sequence)
|
||||
|
||||
if agg == nil {
|
||||
t.Errorf("agg should not be nil")
|
||||
}
|
||||
if len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectCreateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
new *Project
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &Project{ObjectRoot: models.ObjectRoot{ID: "ID"}, Name: "ProjectName", State: int32(model.Active)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectAdded,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new project nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectAdded,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := ProjectCreateAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.new)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectUpdateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *Project
|
||||
new *Project
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &Project{ObjectRoot: models.ObjectRoot{ID: "ID"}, Name: "ProjectName", State: int32(model.Active)},
|
||||
new: &Project{ObjectRoot: models.ObjectRoot{ID: "ID"}, Name: "ProjectName_Changed", State: int32(model.Active)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectChanged,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing project nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectChanged,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new project nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &Project{ObjectRoot: models.ObjectRoot{ID: "ID"}, Name: "ProjectName", State: int32(model.Active)},
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectChanged,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := ProjectUpdateAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.existing, tt.args.new)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectDeactivateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *Project
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project deactivate aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &Project{ObjectRoot: models.ObjectRoot{ID: "ID"}, Name: "ProjectName", State: int32(model.Active)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectDeactivated,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing project nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectDeactivated,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := ProjectDeactivateAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.existing)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectReactivateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *Project
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "project reactivate aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &Project{ObjectRoot: models.ObjectRoot{ID: "ID"}, Name: "ProjectName", State: int32(model.Inactive)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectReactivated,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing project nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: model.ProjectReactivated,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := ProjectReactivateAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.existing)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -83,7 +83,7 @@ func templatesAuth_method_mappingGoTmpl() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/auth_method_mapping.go.tmpl", size: 1013, mode: os.FileMode(420), modTime: time.Unix(1585129064, 0)}
|
||||
info := bindataFileInfo{name: "templates/auth_method_mapping.go.tmpl", size: 1013, mode: os.FileMode(420), modTime: time.Unix(1586159062, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -182,7 +182,6 @@ type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"templates": &bintree{nil, map[string]*bintree{
|
||||
"auth_method_mapping.go.tmpl": &bintree{templatesAuth_method_mappingGoTmpl, map[string]*bintree{}},
|
||||
@ -235,3 +234,4 @@ func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
}
|
||||
|
||||
|
49
migrations/cockroach/V1.0__eventstore.sql
Normal file
49
migrations/cockroach/V1.0__eventstore.sql
Normal file
@ -0,0 +1,49 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE DATABASE eventstore;
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE USER eventstore;
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE ON DATABASE eventstore TO eventstore;
|
||||
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE SEQUENCE eventstore.event_seq;
|
||||
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE eventstore.events (
|
||||
id UUID DEFAULT gen_random_uuid(),
|
||||
|
||||
event_type TEXT,
|
||||
aggregate_type TEXT NOT NULL,
|
||||
aggregate_id TEXT NOT NULL,
|
||||
aggregate_version TEXT NOT NULL,
|
||||
event_sequence BIGINT NOT NULL DEFAULT nextval('eventstore.event_seq'),
|
||||
previous_sequence BIGINT UNIQUE,
|
||||
creation_date TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
event_data JSONB,
|
||||
editor_user TEXT NOT NULL,
|
||||
editor_service TEXT NOT NULL,
|
||||
resource_owner TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE eventstore.locks (
|
||||
aggregate_type TEXT NOT NULL,
|
||||
aggregate_id TEXT NOT NULL,
|
||||
until TIMESTAMPTZ,
|
||||
UNIQUE (aggregate_type, aggregate_id)
|
||||
);
|
||||
|
||||
COMMIT;
|
16
migrations/cockroach/V1.1__management.sql
Normal file
16
migrations/cockroach/V1.1__management.sql
Normal file
@ -0,0 +1,16 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE DATABASE management;
|
||||
|
||||
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE USER management;
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON DATABASE management TO management;
|
||||
GRANT SELECT, INSERT, UPDATE ON DATABASE eventstore TO management;
|
||||
GRANT SELECT, INSERT, UPDATE ON TABLE eventstore.* TO management;
|
||||
|
||||
COMMIT;
|
5
migrations/cockroach/clean_cluster.go
Normal file
5
migrations/cockroach/clean_cluster.go
Normal file
@ -0,0 +1,5 @@
|
||||
//+build ignore
|
||||
|
||||
package migrations
|
||||
|
||||
//go:generate flyway -url=jdbc:postgresql://cockroachdb-public:26257/defaultdb -user=root -password= -locations=filesystem:./ clean
|
5
migrations/cockroach/clean_local.go
Normal file
5
migrations/cockroach/clean_local.go
Normal file
@ -0,0 +1,5 @@
|
||||
//+build ignore
|
||||
|
||||
package migrations
|
||||
|
||||
//go:generate flyway -url=jdbc:postgresql://localhost:26257/defaultdb -user=root -password= -locations=filesystem:./ clean
|
5
migrations/cockroach/migrate_cluster.go
Normal file
5
migrations/cockroach/migrate_cluster.go
Normal file
@ -0,0 +1,5 @@
|
||||
//+build ignore
|
||||
|
||||
package migrations
|
||||
|
||||
//go:generate flyway -url=jdbc:postgresql://cockroachdb-public:26257/defaultdb -user=root -password= -locations=filesystem:./ migrate
|
5
migrations/cockroach/migrate_local.go
Normal file
5
migrations/cockroach/migrate_local.go
Normal file
@ -0,0 +1,5 @@
|
||||
//+build ignore
|
||||
|
||||
package migrations
|
||||
|
||||
//go:generate flyway -url=jdbc:postgresql://localhost:26257/defaultdb -user=root -password= -locations=filesystem:./ migrate
|
@ -1150,11 +1150,11 @@ var fileDescriptor_73a7fc70dcc2027c = []byte{
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConnInterface
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion6
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// AdminServiceClient is the client API for AdminService service.
|
||||
//
|
||||
@ -1173,10 +1173,10 @@ type AdminServiceClient interface {
|
||||
}
|
||||
|
||||
type adminServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewAdminServiceClient(cc grpc.ClientConnInterface) AdminServiceClient {
|
||||
func NewAdminServiceClient(cc *grpc.ClientConn) AdminServiceClient {
|
||||
return &adminServiceClient{cc}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/protobuf/descriptor"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
@ -23,11 +24,13 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = descriptor.ForMessage
|
||||
|
||||
func request_AdminService_Healthz_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
@ -38,6 +41,15 @@ func request_AdminService_Healthz_0(ctx context.Context, marshaler runtime.Marsh
|
||||
|
||||
}
|
||||
|
||||
func local_request_AdminService_Healthz_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.Healthz(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_AdminService_Ready_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -47,6 +59,15 @@ func request_AdminService_Ready_0(ctx context.Context, marshaler runtime.Marshal
|
||||
|
||||
}
|
||||
|
||||
func local_request_AdminService_Ready_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.Ready(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_AdminService_Validate_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -56,6 +77,15 @@ func request_AdminService_Validate_0(ctx context.Context, marshaler runtime.Mars
|
||||
|
||||
}
|
||||
|
||||
func local_request_AdminService_Validate_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.Validate(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_AdminService_IsOrgUnique_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
@ -64,7 +94,10 @@ func request_AdminService_IsOrgUnique_0(ctx context.Context, marshaler runtime.M
|
||||
var protoReq UniqueOrgRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_AdminService_IsOrgUnique_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AdminService_IsOrgUnique_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@ -73,6 +106,19 @@ func request_AdminService_IsOrgUnique_0(ctx context.Context, marshaler runtime.M
|
||||
|
||||
}
|
||||
|
||||
func local_request_AdminService_IsOrgUnique_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq UniqueOrgRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_AdminService_IsOrgUnique_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.IsOrgUnique(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_AdminService_GetOrgByID_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq OrgID
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -100,6 +146,33 @@ func request_AdminService_GetOrgByID_0(ctx context.Context, marshaler runtime.Ma
|
||||
|
||||
}
|
||||
|
||||
func local_request_AdminService_GetOrgByID_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq OrgID
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := server.GetOrgByID(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_AdminService_SearchOrgs_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq OrgSearchRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -117,6 +190,23 @@ func request_AdminService_SearchOrgs_0(ctx context.Context, marshaler runtime.Ma
|
||||
|
||||
}
|
||||
|
||||
func local_request_AdminService_SearchOrgs_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq OrgSearchRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.SearchOrgs(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_AdminService_SetUpOrg_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq OrgSetUpRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
@ -134,6 +224,171 @@ func request_AdminService_SetUpOrg_0(ctx context.Context, marshaler runtime.Mars
|
||||
|
||||
}
|
||||
|
||||
func local_request_AdminService_SetUpOrg_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq OrgSetUpRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.SetUpOrg(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterAdminServiceHandlerServer registers the http handlers for service AdminService to "mux".
|
||||
// UnaryRPC :call AdminServiceServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AdminServiceServer) error {
|
||||
|
||||
mux.Handle("GET", pattern_AdminService_Healthz_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_AdminService_Healthz_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AdminService_Healthz_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_AdminService_Ready_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_AdminService_Ready_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AdminService_Ready_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_AdminService_Validate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_AdminService_Validate_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AdminService_Validate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_AdminService_IsOrgUnique_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_AdminService_IsOrgUnique_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AdminService_IsOrgUnique_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_AdminService_GetOrgByID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_AdminService_GetOrgByID_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AdminService_GetOrgByID_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_AdminService_SearchOrgs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_AdminService_SearchOrgs_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AdminService_SearchOrgs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_AdminService_SetUpOrg_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_AdminService_SetUpOrg_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AdminService_SetUpOrg_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterAdminServiceHandlerFromEndpoint is same as RegisterAdminServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterAdminServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
@ -316,19 +571,19 @@ func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_AdminService_Healthz_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"healthz"}, ""))
|
||||
pattern_AdminService_Healthz_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"healthz"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_AdminService_Ready_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"ready"}, ""))
|
||||
pattern_AdminService_Ready_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"ready"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_AdminService_Validate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"validate"}, ""))
|
||||
pattern_AdminService_Validate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"validate"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_AdminService_IsOrgUnique_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_isunique"}, ""))
|
||||
pattern_AdminService_IsOrgUnique_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_isunique"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_AdminService_GetOrgByID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"orgs", "id"}, ""))
|
||||
pattern_AdminService_GetOrgByID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"orgs", "id"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_AdminService_SearchOrgs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_search"}, ""))
|
||||
pattern_AdminService_SearchOrgs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_search"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_AdminService_SetUpOrg_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_setup"}, ""))
|
||||
pattern_AdminService_SetUpOrg_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"orgs", "_setup"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -167,7 +167,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/protobufStruct"
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -178,19 +178,6 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"protobufListValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Repeated field of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
|
||||
},
|
||||
"protobufNullValue": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@ -199,51 +186,6 @@
|
||||
"default": "NULL_VALUE",
|
||||
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
|
||||
},
|
||||
"protobufStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fields": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Unordered map of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
|
||||
},
|
||||
"protobufValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"null_value": {
|
||||
"$ref": "#/definitions/protobufNullValue",
|
||||
"description": "Represents a null value."
|
||||
},
|
||||
"number_value": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Represents a double value."
|
||||
},
|
||||
"string_value": {
|
||||
"type": "string",
|
||||
"description": "Represents a string value."
|
||||
},
|
||||
"bool_value": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "Represents a boolean value."
|
||||
},
|
||||
"struct_value": {
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Represents a structured value."
|
||||
},
|
||||
"list_value": {
|
||||
"$ref": "#/definitions/protobufListValue",
|
||||
"description": "Represents a repeated `Value`."
|
||||
}
|
||||
},
|
||||
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
|
||||
},
|
||||
"v1CreateOrgRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -8,9 +8,9 @@ import (
|
||||
context "context"
|
||||
grpc "github.com/caos/zitadel/pkg/admin/api/grpc"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
empty "github.com/golang/protobuf/ptypes/empty"
|
||||
struct0 "github.com/golang/protobuf/ptypes/struct"
|
||||
grpc0 "google.golang.org/grpc"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
structpb "google.golang.org/protobuf/types/known/structpb"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
@ -58,14 +58,14 @@ func (mr *MockAdminServiceClientMockRecorder) GetOrgByID(arg0, arg1 interface{},
|
||||
}
|
||||
|
||||
// Healthz mocks base method
|
||||
func (m *MockAdminServiceClient) Healthz(arg0 context.Context, arg1 *empty.Empty, arg2 ...grpc0.CallOption) (*empty.Empty, error) {
|
||||
func (m *MockAdminServiceClient) Healthz(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Healthz", varargs...)
|
||||
ret0, _ := ret[0].(*empty.Empty)
|
||||
ret0, _ := ret[0].(*emptypb.Empty)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
@ -98,14 +98,14 @@ func (mr *MockAdminServiceClientMockRecorder) IsOrgUnique(arg0, arg1 interface{}
|
||||
}
|
||||
|
||||
// Ready mocks base method
|
||||
func (m *MockAdminServiceClient) Ready(arg0 context.Context, arg1 *empty.Empty, arg2 ...grpc0.CallOption) (*empty.Empty, error) {
|
||||
func (m *MockAdminServiceClient) Ready(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Ready", varargs...)
|
||||
ret0, _ := ret[0].(*empty.Empty)
|
||||
ret0, _ := ret[0].(*emptypb.Empty)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
@ -158,14 +158,14 @@ func (mr *MockAdminServiceClientMockRecorder) SetUpOrg(arg0, arg1 interface{}, a
|
||||
}
|
||||
|
||||
// Validate mocks base method
|
||||
func (m *MockAdminServiceClient) Validate(arg0 context.Context, arg1 *empty.Empty, arg2 ...grpc0.CallOption) (*struct0.Struct, error) {
|
||||
func (m *MockAdminServiceClient) Validate(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc0.CallOption) (*structpb.Struct, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Validate", varargs...)
|
||||
ret0, _ := ret[0].(*struct0.Struct)
|
||||
ret0, _ := ret[0].(*structpb.Struct)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -535,7 +535,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/protobufStruct"
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -546,19 +546,6 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"protobufListValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Repeated field of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
|
||||
},
|
||||
"protobufNullValue": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@ -567,51 +554,6 @@
|
||||
"default": "NULL_VALUE",
|
||||
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
|
||||
},
|
||||
"protobufStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fields": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Unordered map of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
|
||||
},
|
||||
"protobufValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"null_value": {
|
||||
"$ref": "#/definitions/protobufNullValue",
|
||||
"description": "Represents a null value."
|
||||
},
|
||||
"number_value": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Represents a double value."
|
||||
},
|
||||
"string_value": {
|
||||
"type": "string",
|
||||
"description": "Represents a string value."
|
||||
},
|
||||
"bool_value": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "Represents a boolean value."
|
||||
},
|
||||
"struct_value": {
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Represents a structured value."
|
||||
},
|
||||
"list_value": {
|
||||
"$ref": "#/definitions/protobufListValue",
|
||||
"description": "Represents a repeated `Value`."
|
||||
}
|
||||
},
|
||||
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
|
||||
},
|
||||
"v1Gender": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@ -886,6 +828,10 @@
|
||||
},
|
||||
"street_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -901,6 +847,10 @@
|
||||
"isEmailVerified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -916,6 +866,10 @@
|
||||
"is_phone_verified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -945,6 +899,10 @@
|
||||
},
|
||||
"gender": {
|
||||
"$ref": "#/definitions/v1Gender"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -974,6 +932,10 @@
|
||||
},
|
||||
"user_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -46,10 +46,6 @@ func (s *Server) ResendMyEmailVerificationMail(ctx context.Context, _ *empty.Emp
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-dh69i", "Not implemented")
|
||||
}
|
||||
|
||||
func (s *Server) ResendEmailVerificationMail(ctx context.Context, id *UserID) (*empty.Empty, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-mAq23", "Not implemented")
|
||||
}
|
||||
|
||||
func (s *Server) ChangeMyUserPhone(ctx context.Context, request *UpdateUserPhoneRequest) (*UserPhone, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-dk45g", "Not implemented")
|
||||
}
|
||||
@ -85,7 +81,3 @@ func (s *Server) VerifyMfaOTP(ctx context.Context, request *VerifyMfaOtp) (_ *Mf
|
||||
func (s *Server) RemoveMfaOTP(ctx context.Context, _ *empty.Empty) (_ *empty.Empty, err error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-9k46d", "Not implemented")
|
||||
}
|
||||
|
||||
func (s *Server) ResendUserInitMail(ctx context.Context, request *UserID) (_ *empty.Empty, err error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-dk467", "Not implemented")
|
||||
}
|
||||
|
@ -297,6 +297,7 @@ message UserSessionView {
|
||||
UserSessionState auth_state = 3;
|
||||
string user_id = 4;
|
||||
string user_name = 5;
|
||||
uint64 sequence = 6;
|
||||
}
|
||||
|
||||
enum UserSessionState {
|
||||
@ -336,6 +337,7 @@ message User {
|
||||
string region = 22;
|
||||
string street_address = 23;
|
||||
bool password_change_required = 24;
|
||||
uint64 sequence = 25;
|
||||
}
|
||||
|
||||
enum UserState {
|
||||
@ -364,6 +366,7 @@ message UserProfile {
|
||||
string display_name = 6;
|
||||
string preferred_language = 7;
|
||||
Gender gender = 8;
|
||||
uint64 sequence = 26;
|
||||
}
|
||||
|
||||
message UpdateUserProfileRequest {
|
||||
@ -379,6 +382,7 @@ message UserEmail {
|
||||
string id = 1;
|
||||
string email = 2;
|
||||
bool isEmailVerified = 3;
|
||||
uint64 sequence = 4;
|
||||
}
|
||||
|
||||
message VerifyMyUserEmailRequest {
|
||||
@ -398,6 +402,7 @@ message UserPhone {
|
||||
string id = 1;
|
||||
string phone = 2;
|
||||
bool is_phone_verified = 3;
|
||||
uint64 sequence = 4;
|
||||
}
|
||||
|
||||
message UpdateUserPhoneRequest {
|
||||
@ -415,6 +420,7 @@ message UserAddress {
|
||||
string postal_code = 4;
|
||||
string region = 5;
|
||||
string street_address = 6;
|
||||
uint64 sequence = 7;
|
||||
}
|
||||
|
||||
message UpdateUserAddressRequest {
|
||||
|
@ -2,6 +2,8 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
"github.com/caos/zitadel/internal/management/repository"
|
||||
|
||||
grpc_util "github.com/caos/zitadel/internal/api/grpc"
|
||||
"github.com/caos/zitadel/internal/api/grpc/server"
|
||||
@ -12,8 +14,8 @@ type Config struct {
|
||||
GRPC grpc_util.Config
|
||||
}
|
||||
|
||||
func Start(ctx context.Context, conf Config) {
|
||||
grpcServer := grpc.StartServer(conf.GRPC.ToServerConfig())
|
||||
func Start(ctx context.Context, conf Config, authZ auth.Config, repo repository.Repository) {
|
||||
grpcServer := grpc.StartServer(conf.GRPC.ToServerConfig(), authZ, repo)
|
||||
grpcGateway := grpc.StartGateway(conf.GRPC.ToGatewayConfig())
|
||||
|
||||
server.StartServer(ctx, grpcServer)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3280,6 +3280,10 @@
|
||||
},
|
||||
"oidc_config": {
|
||||
"$ref": "#/definitions/v1OIDCConfig"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3832,6 +3836,10 @@
|
||||
},
|
||||
"domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3874,6 +3882,10 @@
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3994,6 +4006,10 @@
|
||||
"expire_warn_days": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4071,6 +4087,10 @@
|
||||
"has_symbol": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4160,6 +4180,10 @@
|
||||
"show_lock_out_failures": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4256,6 +4280,10 @@
|
||||
},
|
||||
"grant_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4304,6 +4332,10 @@
|
||||
},
|
||||
"project_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4366,6 +4398,10 @@
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4676,6 +4712,10 @@
|
||||
"creation_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4812,6 +4852,10 @@
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4969,7 +5013,7 @@
|
||||
"enum": [
|
||||
"PROJECTSTATE_UNSPECIFIED",
|
||||
"PROJECTSTATE_ACTIVE",
|
||||
"PROJECTSSTATE_INACTIVE"
|
||||
"PROJECTSTATE_INACTIVE"
|
||||
],
|
||||
"default": "PROJECTSTATE_UNSPECIFIED"
|
||||
},
|
||||
@ -5231,6 +5275,10 @@
|
||||
},
|
||||
"street_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5254,6 +5302,10 @@
|
||||
},
|
||||
"street_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5269,6 +5321,10 @@
|
||||
"is_email_verified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5324,6 +5380,10 @@
|
||||
},
|
||||
"project_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5470,6 +5530,10 @@
|
||||
"is_phone_verified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5502,6 +5566,10 @@
|
||||
},
|
||||
"user_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -7,16 +7,32 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) CreateProject(ctx context.Context, in *ProjectCreateRequest) (*Project, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-mo34X", "Not implemented")
|
||||
project, err := s.project.CreateProject(ctx, in.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectFromModel(project), nil
|
||||
}
|
||||
func (s *Server) UpdateProject(ctx context.Context, in *ProjectUpdateRequest) (*Project, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-0o4fB", "Not implemented")
|
||||
project, err := s.project.UpdateProject(ctx, projectUpdateToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectFromModel(project), nil
|
||||
}
|
||||
func (s *Server) DeactivateProject(ctx context.Context, in *ProjectID) (*Project, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-4Sck8", "Not implemented")
|
||||
project, err := s.project.DeactivateProject(ctx, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectFromModel(project), nil
|
||||
}
|
||||
func (s *Server) ReactivateProject(ctx context.Context, in *ProjectID) (*Project, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-0oVre", "Not implemented")
|
||||
project, err := s.project.ReactivateProject(ctx, in.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectFromModel(project), nil
|
||||
}
|
||||
|
||||
func (s *Server) SearchProjects(ctx context.Context, in *ProjectSearchRequest) (*ProjectSearchResponse, error) {
|
||||
@ -24,7 +40,11 @@ func (s *Server) SearchProjects(ctx context.Context, in *ProjectSearchRequest) (
|
||||
}
|
||||
|
||||
func (s *Server) ProjectByID(ctx context.Context, id *ProjectID) (*Project, error) {
|
||||
return nil, errors.ThrowUnimplemented(nil, "GRPC-plV5x", "Not implemented")
|
||||
project, err := s.project.ProjectByID(ctx, id.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectFromModel(project), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetGrantedProjectGrantByID(ctx context.Context, request *GrantedGrantID) (*ProjectGrant, error) {
|
||||
|
45
pkg/management/api/grpc/project_converter.go
Normal file
45
pkg/management/api/grpc/project_converter.go
Normal file
@ -0,0 +1,45 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
)
|
||||
|
||||
func projectFromModel(project *proj_model.Project) *Project {
|
||||
creationDate, err := ptypes.TimestampProto(project.CreationDate)
|
||||
logging.Log("GRPC-iejs3").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(project.ChangeDate)
|
||||
logging.Log("GRPC-di7rw").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &Project{
|
||||
Id: project.ID,
|
||||
State: projectStateFromModel(project.State),
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Name: project.Name,
|
||||
Sequence: project.Sequence,
|
||||
}
|
||||
}
|
||||
|
||||
func projectStateFromModel(state proj_model.ProjectState) ProjectState {
|
||||
switch state {
|
||||
case proj_model.Active:
|
||||
return ProjectState_PROJECTSTATE_ACTIVE
|
||||
case proj_model.Inactive:
|
||||
return ProjectState_PROJECTSTATE_INACTIVE
|
||||
default:
|
||||
return ProjectState_PROJECTSTATE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
func projectUpdateToModel(project *ProjectUpdateRequest) *proj_model.Project {
|
||||
return &proj_model.Project{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
ID: project.Id,
|
||||
},
|
||||
Name: project.Name,
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
grpc_util "github.com/caos/zitadel/internal/api/grpc"
|
||||
"github.com/caos/zitadel/internal/api/grpc/server/middleware"
|
||||
mgmt_auth "github.com/caos/zitadel/internal/management/auth"
|
||||
"github.com/caos/zitadel/internal/management/repository"
|
||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
@ -11,11 +14,17 @@ var _ ManagementServiceServer = (*Server)(nil)
|
||||
|
||||
type Server struct {
|
||||
port string
|
||||
project repository.ProjectRepository
|
||||
verifier *mgmt_auth.TokenVerifier
|
||||
authZ auth.Config
|
||||
}
|
||||
|
||||
func StartServer(conf grpc_util.ServerConfig) *Server {
|
||||
func StartServer(conf grpc_util.ServerConfig, authZ auth.Config, repo repository.Repository) *Server {
|
||||
return &Server{
|
||||
port: conf.Port,
|
||||
project: repo,
|
||||
authZ: authZ,
|
||||
verifier: mgmt_auth.Start(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,6 +38,7 @@ func (s *Server) GRPCServer() (*grpc.Server, error) {
|
||||
grpc.UnaryInterceptor(
|
||||
grpc_middleware.ChainUnaryServer(
|
||||
middleware.ErrorHandler(),
|
||||
ManagementService_Authorization_Interceptor(s.verifier, &s.authZ),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -1269,6 +1269,7 @@ message User {
|
||||
string postal_code = 20;
|
||||
string region = 21;
|
||||
string street_address = 22;
|
||||
uint64 sequence = 23;
|
||||
}
|
||||
|
||||
enum UserState {
|
||||
@ -1337,6 +1338,7 @@ message UserProfile {
|
||||
string preferred_language = 7;
|
||||
Gender gender = 8;
|
||||
string user_name = 9;
|
||||
uint64 sequence = 10;
|
||||
}
|
||||
|
||||
message UpdateUserProfileRequest {
|
||||
@ -1353,6 +1355,7 @@ message UserEmail {
|
||||
string id = 1;
|
||||
string email = 2;
|
||||
bool is_email_verified = 3;
|
||||
uint64 sequence = 4;
|
||||
}
|
||||
|
||||
message UpdateUserEmailRequest {
|
||||
@ -1365,6 +1368,7 @@ message UserPhone {
|
||||
string id = 1;
|
||||
string phone = 2;
|
||||
bool is_phone_verified = 3;
|
||||
uint64 sequence = 5;
|
||||
}
|
||||
|
||||
message UpdateUserPhoneRequest {
|
||||
@ -1380,6 +1384,7 @@ message UserAddress {
|
||||
string postal_code = 4;
|
||||
string region = 5;
|
||||
string street_address = 6;
|
||||
uint64 sequence = 7;
|
||||
}
|
||||
|
||||
message UpdateUserAddressRequest {
|
||||
@ -1451,6 +1456,7 @@ message PasswordComplexityPolicy {
|
||||
bool has_uppercase = 8;
|
||||
bool has_number = 9;
|
||||
bool has_symbol = 10;
|
||||
uint64 sequence = 11;
|
||||
}
|
||||
|
||||
message PasswordComplexityPolicyCreate {
|
||||
@ -1484,6 +1490,7 @@ message PasswordAgePolicy {
|
||||
google.protobuf.Timestamp change_date = 5;
|
||||
uint64 max_age_days = 6;
|
||||
uint64 expire_warn_days = 7;
|
||||
uint64 sequence = 8;
|
||||
}
|
||||
|
||||
message PasswordAgePolicyCreate {
|
||||
@ -1511,6 +1518,7 @@ message PasswordLockoutPolicy {
|
||||
google.protobuf.Timestamp change_date = 5;
|
||||
uint64 max_attempts = 6;
|
||||
bool show_lock_out_failures = 7;
|
||||
uint64 sequence = 8;
|
||||
}
|
||||
|
||||
message PasswordLockoutPolicyCreate {
|
||||
@ -1548,6 +1556,7 @@ message Org {
|
||||
google.protobuf.Timestamp change_date = 4;
|
||||
string name = 5;
|
||||
string domain = 6;
|
||||
uint64 sequence = 7;
|
||||
}
|
||||
|
||||
enum OrgState {
|
||||
@ -1569,6 +1578,7 @@ message OrgMember {
|
||||
repeated string roles = 6;
|
||||
google.protobuf.Timestamp change_date = 7;
|
||||
google.protobuf.Timestamp creation_date = 8;
|
||||
uint64 sequence = 9;
|
||||
}
|
||||
|
||||
message AddOrgMemberRequest {
|
||||
@ -1641,12 +1651,13 @@ message Project {
|
||||
string org_name = 9;
|
||||
string org_domain = 10;
|
||||
string grant_id = 11;
|
||||
uint64 sequence = 12;
|
||||
}
|
||||
|
||||
enum ProjectState {
|
||||
PROJECTSTATE_UNSPECIFIED = 0;
|
||||
PROJECTSTATE_ACTIVE = 1;
|
||||
PROJECTSSTATE_INACTIVE = 2;
|
||||
PROJECTSTATE_INACTIVE = 2;
|
||||
}
|
||||
|
||||
enum ProjectType {
|
||||
@ -1692,6 +1703,7 @@ message ProjectMember {
|
||||
repeated string roles = 6;
|
||||
google.protobuf.Timestamp change_date = 7;
|
||||
google.protobuf.Timestamp creation_date = 8;
|
||||
uint64 sequence = 10;
|
||||
}
|
||||
|
||||
message ProjectMemberAdd {
|
||||
@ -1724,6 +1736,7 @@ message ProjectRole {
|
||||
string display_name = 3;
|
||||
google.protobuf.Timestamp creation_date = 4;
|
||||
string group = 5;
|
||||
uint64 sequence = 6;
|
||||
}
|
||||
|
||||
message ProjectRoleRemove {
|
||||
@ -1800,6 +1813,7 @@ message Application {
|
||||
oneof app_config {
|
||||
OIDCConfig oidc_config = 8;
|
||||
}
|
||||
uint64 sequence = 9;
|
||||
}
|
||||
|
||||
message ApplicationUpdate {
|
||||
@ -1906,6 +1920,7 @@ message ProjectGrant {
|
||||
google.protobuf.Timestamp creation_date = 8;
|
||||
google.protobuf.Timestamp change_date = 9;
|
||||
string project_name = 10;
|
||||
uint64 sequence = 11;
|
||||
}
|
||||
|
||||
message ProjectGrantCreate {
|
||||
@ -1961,6 +1976,7 @@ message ProjectGrantMember {
|
||||
repeated string roles = 6;
|
||||
google.protobuf.Timestamp change_date = 7;
|
||||
google.protobuf.Timestamp creation_date = 8;
|
||||
uint64 sequence = 9;
|
||||
}
|
||||
|
||||
message ProjectGrantMemberAdd {
|
||||
@ -2028,6 +2044,7 @@ message UserGrant {
|
||||
string org_name = 13;
|
||||
string org_domain = 14;
|
||||
string project_name = 15;
|
||||
uint64 sequence = 16;
|
||||
}
|
||||
|
||||
message UserGrantCreate {
|
||||
|
@ -2,16 +2,20 @@ package management
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
app "github.com/caos/zitadel/internal/management"
|
||||
"github.com/caos/zitadel/internal/management/repository/eventsourcing"
|
||||
"github.com/caos/zitadel/pkg/management/api"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
App app.Config
|
||||
Repository eventsourcing.Config
|
||||
API api.Config
|
||||
}
|
||||
|
||||
func Start(ctx context.Context, config Config, authZ auth.Config) {
|
||||
api.Start(ctx, config.API)
|
||||
repo, err := eventsourcing.Start(config.Repository)
|
||||
logging.Log("MAIN-9uBxp").OnError(err).Panic("unable to start app")
|
||||
|
||||
api.Start(ctx, config.API, authZ, repo)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user