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:
Fabi 2020-04-07 13:23:04 +02:00 committed by GitHub
parent 007fc9e9bd
commit c07ed83c41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 5259 additions and 3481 deletions

View File

@ -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
View 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
View File

@ -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
View File

@ -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=

View File

@ -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
}

View File

@ -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
}

View 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})
}

View File

@ -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) {

View File

@ -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)

View File

@ -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"
)

View File

@ -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)
}

View File

@ -1,9 +0,0 @@
package eventstore
import (
"context"
)
func (app *eventstore) Health(ctx context.Context) error {
return app.repo.Health(ctx)
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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).

View File

@ -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 ""
}

View File

@ -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 {

View File

@ -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, &currentSequence, &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

View 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
}

View File

@ -7,6 +7,6 @@ const (
Field_AggregateID
Field_LatestSequence
Field_ResourceOwner
Field_ModifierService
Field_ModifierUser
Field_EditorService
Field_EditorUser
)

View File

@ -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))
}

View 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
}

View File

@ -1,3 +0,0 @@
package management
type Config struct{}

View 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
}

View 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())
}

View 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)
}

View File

@ -0,0 +1,6 @@
package repository
type Repository interface {
Health() error
ProjectRepository
}

View 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
}

View 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)
}

View 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"
)

View 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
}

View 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)
}
})
}
}

View 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
}

View 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}
}

View 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)
}
})
}
}

View 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)
}

View 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)
}
})
}
}

View File

@ -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, "/")...)...)
}

View 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;

View 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;

View 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

View File

@ -0,0 +1,5 @@
//+build ignore
package migrations
//go:generate flyway -url=jdbc:postgresql://localhost:26257/defaultdb -user=root -password= -locations=filesystem:./ clean

View 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

View File

@ -0,0 +1,5 @@
//+build ignore
package migrations
//go:generate flyway -url=jdbc:postgresql://localhost:26257/defaultdb -user=root -password= -locations=filesystem:./ migrate

View File

@ -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}
}

View File

@ -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 (

View File

@ -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": {

View File

@ -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

View File

@ -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"
}
}
},

View File

@ -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")
}

View File

@ -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 {

View File

@ -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

View File

@ -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"
}
}
},

View File

@ -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) {

View 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,
}
}

View File

@ -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),
),
),
)

View File

@ -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 {

View File

@ -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)
}