mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-14 03:54:21 +00:00
Merge branch 'main' into next-rc
This commit is contained in:
commit
76c84d385c
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -91,7 +91,7 @@ jobs:
|
||||
pull-requests: write
|
||||
needs:
|
||||
[version, core-unit-test, core-integration-test, lint, container, e2e]
|
||||
if: ${{ needs.version.outputs.published == 'true' && github.event_name == 'workflow_dispatch' }}
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
secrets:
|
||||
GCR_JSON_KEY_BASE64: ${{ secrets.GCR_JSON_KEY_BASE64 }}
|
||||
with:
|
||||
|
2
.github/workflows/version.yml
vendored
2
.github/workflows/version.yml
vendored
@ -47,4 +47,4 @@ jobs:
|
||||
name: output
|
||||
id: output
|
||||
run:
|
||||
if [[ ! -z "${{ steps.semantic.outputs.new_release_version }}" ]]; then echo "VERSION=v${{ steps.semantic.outputs.new_release_version }}" >> "$GITHUB_OUTPUT"; else echo "VERSION=" >> "$GITHUB_OUTPUT";fi
|
||||
if [[ ! -z "${{ steps.semantic.outputs.new_release_version }}" ]]; then echo "VERSION=v${{ steps.semantic.outputs.new_release_version }}" >> "$GITHUB_OUTPUT"; else echo "VERSION=${{ github.sha }}" >> "$GITHUB_OUTPUT";fi
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -76,6 +76,7 @@ migrations/cockroach/migrate_cloud.go
|
||||
!/.artifacts/zitadel
|
||||
/zitadel
|
||||
node_modules/
|
||||
.kreya
|
||||
|
||||
go.work
|
||||
go.work.sum
|
||||
|
26
cmd/setup/19.go
Normal file
26
cmd/setup/19.go
Normal file
@ -0,0 +1,26 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed 19.sql
|
||||
addCurrentSequencesIndex string
|
||||
)
|
||||
|
||||
type AddCurrentSequencesIndex struct {
|
||||
dbClient *database.DB
|
||||
}
|
||||
|
||||
func (mig *AddCurrentSequencesIndex) Execute(ctx context.Context) error {
|
||||
_, err := mig.dbClient.ExecContext(ctx, addCurrentSequencesIndex)
|
||||
return err
|
||||
}
|
||||
|
||||
func (mig *AddCurrentSequencesIndex) String() string {
|
||||
return "19_add_current_sequences_index"
|
||||
}
|
1
cmd/setup/19.sql
Normal file
1
cmd/setup/19.sql
Normal file
@ -0,0 +1 @@
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS events2_current_sequence ON eventstore.events2 ("sequence" DESC, aggregate_id, aggregate_type, instance_id);
|
@ -76,6 +76,7 @@ type Steps struct {
|
||||
s16UniqueConstraintsLower *UniqueConstraintToLower
|
||||
s17AddOffsetToUniqueConstraints *AddOffsetToCurrentStates
|
||||
s18AddLowerFieldsToLoginNames *AddLowerFieldsToLoginNames
|
||||
s19AddCurrentStatesIndex *AddCurrentSequencesIndex
|
||||
}
|
||||
|
||||
type encryptionKeyConfig struct {
|
||||
|
@ -109,6 +109,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
|
||||
steps.s16UniqueConstraintsLower = &UniqueConstraintToLower{dbClient: queryDBClient}
|
||||
steps.s17AddOffsetToUniqueConstraints = &AddOffsetToCurrentStates{dbClient: queryDBClient}
|
||||
steps.s18AddLowerFieldsToLoginNames = &AddLowerFieldsToLoginNames{dbClient: queryDBClient}
|
||||
steps.s19AddCurrentStatesIndex = &AddCurrentSequencesIndex{dbClient: queryDBClient}
|
||||
|
||||
err = projection.Create(ctx, projectionDBClient, eventstoreClient, config.Projections, nil, nil, nil)
|
||||
logging.OnError(err).Fatal("unable to start projections")
|
||||
@ -153,6 +154,8 @@ func Setup(config *Config, steps *Steps, masterKey string) {
|
||||
logging.WithFields("name", steps.s16UniqueConstraintsLower.String()).OnError(err).Fatal("migration failed")
|
||||
err = migration.Migrate(ctx, eventstoreClient, steps.s17AddOffsetToUniqueConstraints)
|
||||
logging.WithFields("name", steps.s17AddOffsetToUniqueConstraints.String()).OnError(err).Fatal("migration failed")
|
||||
err = migration.Migrate(ctx, eventstoreClient, steps.s19AddCurrentStatesIndex)
|
||||
logging.WithFields("name", steps.s19AddCurrentStatesIndex.String()).OnError(err).Fatal("migration failed")
|
||||
|
||||
for _, repeatableStep := range repeatableSteps {
|
||||
err = migration.Migrate(ctx, eventstoreClient, repeatableStep)
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of ZITADEL Examples, Quickstarts, and SDKs
|
||||
title: Overview of ZITADEL example applications and quickstarts
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
@ -198,3 +198,12 @@ Our examples cover a range of programming languages and frameworks, so no matter
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Other example applications
|
||||
|
||||
- [B2B customer portal](https://github.com/zitadel/zitadel-nextjs-b2b): Showcase the use of personal access tokens in a B2B environment. Uses NextJS Framework.
|
||||
- [Frontend with backend API](https://github.com/zitadel/example-quote-generator-app): A simple web application using a React front-end and a Python back-end API, both secured using ZITADEL
|
||||
- [Introspection](https://github.com/zitadel/examples-api-access-and-token-introspection): Python examples for securing an API and invoking it as a service user
|
||||
- [Fine-grained authorization](https://github.com/zitadel/example-fine-grained-authorization): Leverage actions, custom metadata, and claims for attribute-based access control
|
||||
|
||||
Search for the "example" tag in our repository to [explore all examples](https://github.com/search?q=topic%3Aexamples+org%3Azitadel&type=repositories).
|
||||
|
6
go.mod
6
go.mod
@ -60,7 +60,7 @@ require (
|
||||
github.com/superseriousbusiness/exifremove v0.0.0-20210330092427-6acd27eac203
|
||||
github.com/ttacon/libphonenumber v1.2.1
|
||||
github.com/zitadel/logging v0.5.0
|
||||
github.com/zitadel/oidc/v3 v3.8.0
|
||||
github.com/zitadel/oidc/v3 v3.8.1
|
||||
github.com/zitadel/passwap v0.4.0
|
||||
github.com/zitadel/saml v0.1.3
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0
|
||||
@ -74,7 +74,7 @@ require (
|
||||
go.opentelemetry.io/otel/sdk/metric v1.20.0
|
||||
go.opentelemetry.io/otel/trace v1.21.0
|
||||
go.uber.org/mock v0.3.0
|
||||
golang.org/x/crypto v0.16.0
|
||||
golang.org/x/crypto v0.17.0
|
||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678
|
||||
golang.org/x/net v0.19.0
|
||||
golang.org/x/oauth2 v0.15.0
|
||||
@ -90,7 +90,7 @@ require (
|
||||
require (
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.44.0 // indirect
|
||||
github.com/crewjam/httperr v0.2.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.10 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.11 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||
|
12
go.sum
12
go.sum
@ -258,8 +258,8 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm
|
||||
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
|
||||
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
|
||||
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||
@ -867,8 +867,8 @@ github.com/zenazn/goji v1.0.1 h1:4lbD8Mx2h7IvloP7r2C0D6ltZP6Ufip8Hn0wmSK5LR8=
|
||||
github.com/zenazn/goji v1.0.1/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
github.com/zitadel/logging v0.5.0 h1:Kunouvqse/efXy4UDvFw5s3vP+Z4AlHo3y8wF7stXHA=
|
||||
github.com/zitadel/logging v0.5.0/go.mod h1:IzP5fzwFhzzyxHkSmfF8dsyqFsQRJLLcQmwhIBzlGsE=
|
||||
github.com/zitadel/oidc/v3 v3.8.0 h1:4Nvok+e6o3FDpqrf14JOg4EVBvwXNFOI1lFHPZU75iA=
|
||||
github.com/zitadel/oidc/v3 v3.8.0/go.mod h1:v+aHyg4lBAUuuUHINwXqHtKunPJZo8kPvMpRRBYEKHY=
|
||||
github.com/zitadel/oidc/v3 v3.8.1 h1:YsFWUpT3JFsDlF9ePwM851CymDwqfQ3UU1CoOEOMEdU=
|
||||
github.com/zitadel/oidc/v3 v3.8.1/go.mod h1:rUKTJBsamKtqurN1MpuRYxF5FgW/9RJ/1/AF3g7/2k0=
|
||||
github.com/zitadel/passwap v0.4.0 h1:cMaISx+Ve7ilgG7Q8xOli4Z6IWr8Gndss+jeBk5A3O0=
|
||||
github.com/zitadel/passwap v0.4.0/go.mod h1:yHaDM4A68yRkdic5BZ4iUNoc19hT+kYt8n1/Nz+I87g=
|
||||
github.com/zitadel/saml v0.1.3 h1:LI4DOCVyyU1qKPkzs3vrGcA5J3H4pH3+CL9zr9ShkpM=
|
||||
@ -953,8 +953,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
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=
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/org"
|
||||
user_grpc "github.com/zitadel/zitadel/internal/api/grpc/user"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
@ -275,41 +274,6 @@ func ListMyProjectOrgsRequestToQuery(req *auth_pb.ListMyProjectOrgsRequest) (*qu
|
||||
}, nil
|
||||
}
|
||||
|
||||
func membershipToDomain(memberships []*query.Membership) []*domain.UserMembership {
|
||||
result := make([]*domain.UserMembership, len(memberships))
|
||||
for i, membership := range memberships {
|
||||
typ, displayName, aggID, objID := MemberTypeToDomain(membership)
|
||||
result[i] = &domain.UserMembership{
|
||||
UserID: membership.UserID,
|
||||
MemberType: typ,
|
||||
AggregateID: aggID,
|
||||
ObjectID: objID,
|
||||
Roles: membership.Roles,
|
||||
DisplayName: displayName,
|
||||
CreationDate: membership.CreationDate,
|
||||
ChangeDate: membership.ChangeDate,
|
||||
ResourceOwner: membership.ResourceOwner,
|
||||
//TODO: implement
|
||||
// ResourceOwnerName: membership.ResourceOwnerName,
|
||||
Sequence: membership.Sequence,
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func MemberTypeToDomain(m *query.Membership) (_ domain.MemberType, displayName, aggID, objID string) {
|
||||
if m.Org != nil {
|
||||
return domain.MemberTypeOrganisation, m.Org.Name, m.Org.OrgID, ""
|
||||
} else if m.IAM != nil {
|
||||
return domain.MemberTypeIam, m.IAM.Name, m.IAM.IAMID, ""
|
||||
} else if m.Project != nil {
|
||||
return domain.MemberTypeProject, m.Project.Name, m.Project.ProjectID, ""
|
||||
} else if m.ProjectGrant != nil {
|
||||
return domain.MemberTypeProjectGrant, m.ProjectGrant.ProjectName, m.ProjectGrant.ProjectID, m.ProjectGrant.GrantID
|
||||
}
|
||||
return domain.MemberTypeUnspecified, "", "", ""
|
||||
}
|
||||
|
||||
func cascadingMemberships(memberships []*query.Membership) []*command.CascadingMembership {
|
||||
cascades := make([]*command.CascadingMembership, len(memberships))
|
||||
for i, membership := range memberships {
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
obj_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/azuread"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/repository/idp"
|
||||
@ -255,40 +254,6 @@ func IDPProviderTypeFromPb(typ idp_pb.IDPOwnerType) domain.IdentityProviderType
|
||||
}
|
||||
}
|
||||
|
||||
func IDPProviderTypeModelFromPb(typ idp_pb.IDPOwnerType) iam_model.IDPProviderType {
|
||||
switch typ {
|
||||
case idp_pb.IDPOwnerType_IDP_OWNER_TYPE_ORG:
|
||||
return iam_model.IDPProviderTypeOrg
|
||||
case idp_pb.IDPOwnerType_IDP_OWNER_TYPE_SYSTEM:
|
||||
return iam_model.IDPProviderTypeSystem
|
||||
default:
|
||||
return iam_model.IDPProviderTypeOrg
|
||||
}
|
||||
}
|
||||
|
||||
func IDPIDQueryToModel(query *idp_pb.IDPIDQuery) *iam_model.IDPConfigSearchQuery {
|
||||
return &iam_model.IDPConfigSearchQuery{
|
||||
Key: iam_model.IDPConfigSearchKeyIdpConfigID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: query.Id,
|
||||
}
|
||||
}
|
||||
|
||||
func IDPNameQueryToModel(query *idp_pb.IDPNameQuery) *iam_model.IDPConfigSearchQuery {
|
||||
return &iam_model.IDPConfigSearchQuery{
|
||||
Key: iam_model.IDPConfigSearchKeyName,
|
||||
Method: obj_grpc.TextMethodToModel(query.Method),
|
||||
Value: query.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func IDPOwnerTypeQueryToModel(query *idp_pb.IDPOwnerTypeQuery) *iam_model.IDPConfigSearchQuery {
|
||||
return &iam_model.IDPConfigSearchQuery{
|
||||
Key: iam_model.IDPConfigSearchKeyIdpProviderType,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: IDPProviderTypeModelFromPb(query.OwnerType),
|
||||
}
|
||||
}
|
||||
func ownerTypeToPB(typ domain.IdentityProviderType) idp_pb.IDPOwnerType {
|
||||
switch typ {
|
||||
case domain.IdentityProviderTypeOrg:
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
idp_pb "github.com/zitadel/zitadel/pkg/grpc/idp"
|
||||
@ -136,29 +135,6 @@ func idpQueryToModel(idpQuery *mgmt_pb.IDPQuery) (query.SearchQuery, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func idpProviderViewsToDomain(idps []*iam_model.IDPProviderView) []*domain.IDPProvider {
|
||||
idpProvider := make([]*domain.IDPProvider, len(idps))
|
||||
for i, idp := range idps {
|
||||
idpProvider[i] = &domain.IDPProvider{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: idp.AggregateID,
|
||||
},
|
||||
IDPConfigID: idp.IDPConfigID,
|
||||
Type: idpConfigTypeToDomain(idp.IDPProviderType),
|
||||
}
|
||||
}
|
||||
return idpProvider
|
||||
}
|
||||
|
||||
func idpConfigTypeToDomain(idpType iam_model.IDPProviderType) domain.IdentityProviderType {
|
||||
switch idpType {
|
||||
case iam_model.IDPProviderTypeOrg:
|
||||
return domain.IdentityProviderTypeOrg
|
||||
default:
|
||||
return domain.IdentityProviderTypeSystem
|
||||
}
|
||||
}
|
||||
|
||||
func userLinksToDomain(idps []*query.IDPUserLink) []*domain.UserIDPLink {
|
||||
links := make([]*domain.UserIDPLink, len(idps))
|
||||
for i, idp := range idps {
|
||||
|
@ -18,7 +18,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
user_model "github.com/zitadel/zitadel/internal/user/model"
|
||||
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
|
||||
)
|
||||
|
||||
@ -359,38 +358,3 @@ func ListUserMembershipsRequestToModel(ctx context.Context, req *mgmt_pb.ListUse
|
||||
Queries: queries,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func UserMembershipViewsToDomain(memberships []*user_model.UserMembershipView) []*domain.UserMembership {
|
||||
result := make([]*domain.UserMembership, len(memberships))
|
||||
for i, membership := range memberships {
|
||||
result[i] = &domain.UserMembership{
|
||||
UserID: membership.UserID,
|
||||
MemberType: MemberTypeToDomain(membership.MemberType),
|
||||
AggregateID: membership.AggregateID,
|
||||
ObjectID: membership.ObjectID,
|
||||
Roles: membership.Roles,
|
||||
DisplayName: membership.DisplayName,
|
||||
CreationDate: membership.CreationDate,
|
||||
ChangeDate: membership.ChangeDate,
|
||||
ResourceOwner: membership.ResourceOwner,
|
||||
ResourceOwnerName: membership.ResourceOwnerName,
|
||||
Sequence: membership.Sequence,
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func MemberTypeToDomain(mType user_model.MemberType) domain.MemberType {
|
||||
switch mType {
|
||||
case user_model.MemberTypeIam:
|
||||
return domain.MemberTypeIam
|
||||
case user_model.MemberTypeOrganisation:
|
||||
return domain.MemberTypeOrganisation
|
||||
case user_model.MemberTypeProject:
|
||||
return domain.MemberTypeProject
|
||||
case user_model.MemberTypeProjectGrant:
|
||||
return domain.MemberTypeProjectGrant
|
||||
default:
|
||||
return domain.MemberTypeUnspecified
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,6 @@ import (
|
||||
member_pb "github.com/zitadel/zitadel/pkg/grpc/member"
|
||||
)
|
||||
|
||||
func MemberToDomain(member *member_pb.Member) *domain.Member {
|
||||
return &domain.Member{
|
||||
UserID: member.UserId,
|
||||
Roles: member.Roles,
|
||||
}
|
||||
}
|
||||
|
||||
func MembersToPb(assetAPIPrefix string, members []*query.Member) []*member_pb.Member {
|
||||
m := make([]*member_pb.Member, len(members))
|
||||
for i, member := range members {
|
||||
|
@ -97,29 +97,6 @@ func ToListDetails(
|
||||
return details
|
||||
}
|
||||
|
||||
func TextMethodToModel(method object_pb.TextQueryMethod) domain.SearchMethod {
|
||||
switch method {
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS:
|
||||
return domain.SearchMethodEquals
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS_IGNORE_CASE:
|
||||
return domain.SearchMethodEqualsIgnoreCase
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_STARTS_WITH:
|
||||
return domain.SearchMethodStartsWith
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_STARTS_WITH_IGNORE_CASE:
|
||||
return domain.SearchMethodStartsWithIgnoreCase
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_CONTAINS:
|
||||
return domain.SearchMethodContains
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE:
|
||||
return domain.SearchMethodContainsIgnoreCase
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_ENDS_WITH:
|
||||
return domain.SearchMethodEndsWith
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_ENDS_WITH_IGNORE_CASE:
|
||||
return domain.SearchMethodEndsWithIgnoreCase
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
func TextMethodToQuery(method object_pb.TextQueryMethod) query.TextComparison {
|
||||
switch method {
|
||||
case object_pb.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS:
|
||||
|
@ -52,7 +52,7 @@ func TestMain(m *testing.M) {
|
||||
func TestServer_GetAuthRequest(t *testing.T) {
|
||||
project, err := Tester.CreateProject(CTX)
|
||||
require.NoError(t, err)
|
||||
client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
|
||||
require.NoError(t, err)
|
||||
authRequestID, err := Tester.CreateOIDCAuthRequest(CTX, client.GetClientId(), Tester.Users[integration.FirstInstanceUsersKey][integration.OrgOwner].ID, redirectURI)
|
||||
require.NoError(t, err)
|
||||
@ -96,7 +96,7 @@ func TestServer_GetAuthRequest(t *testing.T) {
|
||||
func TestServer_CreateCallback(t *testing.T) {
|
||||
project, err := Tester.CreateProject(CTX)
|
||||
require.NoError(t, err)
|
||||
client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
client, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
|
||||
require.NoError(t, err)
|
||||
sessionResp, err := Tester.Client.SessionV2.CreateSession(CTX, &session.CreateSessionRequest{
|
||||
Checks: &session.Checks{
|
||||
|
@ -3,7 +3,6 @@ package project
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
proj_model "github.com/zitadel/zitadel/internal/project/model"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
proj_pb "github.com/zitadel/zitadel/pkg/grpc/project"
|
||||
@ -112,45 +111,6 @@ func privateLabelingSettingToPb(setting domain.PrivateLabelingSetting) proj_pb.P
|
||||
}
|
||||
}
|
||||
|
||||
func grantedProjectStateToPb(state proj_model.ProjectState) proj_pb.ProjectGrantState {
|
||||
switch state {
|
||||
case proj_model.ProjectStateActive:
|
||||
return proj_pb.ProjectGrantState_PROJECT_GRANT_STATE_ACTIVE
|
||||
case proj_model.ProjectStateInactive:
|
||||
return proj_pb.ProjectGrantState_PROJECT_GRANT_STATE_INACTIVE
|
||||
default:
|
||||
return proj_pb.ProjectGrantState_PROJECT_GRANT_STATE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
func GrantedProjectQueriesToModel(queries []*proj_pb.ProjectQuery) (_ []*proj_model.ProjectGrantViewSearchQuery, err error) {
|
||||
q := make([]*proj_model.ProjectGrantViewSearchQuery, len(queries))
|
||||
for i, query := range queries {
|
||||
q[i], err = GrantedProjectQueryToModel(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func GrantedProjectQueryToModel(query *proj_pb.ProjectQuery) (*proj_model.ProjectGrantViewSearchQuery, error) {
|
||||
switch q := query.Query.(type) {
|
||||
case *proj_pb.ProjectQuery_NameQuery:
|
||||
return GrantedProjectQueryNameToModel(q.NameQuery), nil
|
||||
default:
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "ORG-Ags42", "List.Query.Invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func GrantedProjectQueryNameToModel(query *proj_pb.ProjectNameQuery) *proj_model.ProjectGrantViewSearchQuery {
|
||||
return &proj_model.ProjectGrantViewSearchQuery{
|
||||
Key: proj_model.GrantedProjectSearchKeyName,
|
||||
Method: object.TextMethodToModel(query.Method),
|
||||
Value: query.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func RoleQueriesToModel(queries []*proj_pb.RoleQuery) (_ []query.SearchQuery, err error) {
|
||||
q := make([]query.SearchQuery, len(queries))
|
||||
for i, query := range queries {
|
||||
|
@ -136,6 +136,20 @@ func (c *Client) IDTokenUserinfoClaimsAssertion() bool {
|
||||
return c.client.IDTokenUserinfoAssertion
|
||||
}
|
||||
|
||||
func (c *Client) RedirectURIGlobs() []string {
|
||||
if c.DevMode() {
|
||||
return c.RedirectURIs()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) PostLogoutRedirectURIGlobs() []string {
|
||||
if c.DevMode() {
|
||||
return c.PostLogoutRedirectURIs()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func accessTokenTypeToOIDC(tokenType domain.OIDCTokenType) op.AccessTokenType {
|
||||
switch tokenType {
|
||||
case domain.OIDCTokenTypeBearer:
|
||||
|
@ -59,48 +59,118 @@ func TestOPStorage_SetUserinfoFromToken(t *testing.T) {
|
||||
func TestServer_Introspect(t *testing.T) {
|
||||
project, err := Tester.CreateProject(CTX)
|
||||
require.NoError(t, err)
|
||||
app, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
require.NoError(t, err)
|
||||
api, err := Tester.CreateAPIClient(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
keyResp, err := Tester.Client.Mgmt.AddAppKey(CTX, &management.AddAppKeyRequest{
|
||||
ProjectId: project.GetId(),
|
||||
AppId: api.GetAppId(),
|
||||
Type: authn.KeyType_KEY_TYPE_JSON,
|
||||
ExpirationDate: nil,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServer(CTX, keyResp.GetKeyDetails())
|
||||
app, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
|
||||
require.NoError(t, err)
|
||||
|
||||
scope := []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopeOfflineAccess, oidc_api.ScopeResourceOwner}
|
||||
authRequestID := createAuthRequest(t, app.GetClientId(), redirectURI, scope...)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
SessionId: sessionID,
|
||||
SessionToken: sessionToken,
|
||||
wantAudience := []string{app.GetClientId(), project.GetId()}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
api func(*testing.T) (apiID string, resourceServer rs.ResourceServer)
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "client assertion",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientJWT(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
keyResp, err := Tester.Client.Mgmt.AddAppKey(CTX, &management.AddAppKeyRequest{
|
||||
ProjectId: project.GetId(),
|
||||
AppId: api.GetAppId(),
|
||||
Type: authn.KeyType_KEY_TYPE_JSON,
|
||||
ExpirationDate: nil,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerJWTProfile(CTX, keyResp.GetKeyDetails())
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
{
|
||||
name: "client credentials",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientBasic(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), api.GetClientSecret())
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "client invalid id, error",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientBasic(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, "xxxxx", api.GetClientSecret())
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "client invalid secret, error",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientBasic(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx")
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "client credentials on jwt client, error",
|
||||
api: func(t *testing.T) (string, rs.ResourceServer) {
|
||||
api, err := Tester.CreateAPIClientJWT(CTX, project.GetId())
|
||||
require.NoError(t, err)
|
||||
resourceServer, err := Tester.CreateResourceServerClientCredentials(CTX, api.GetClientId(), "xxxxx")
|
||||
require.NoError(t, err)
|
||||
return api.GetClientId(), resourceServer
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
apiID, resourceServer := tt.api(t)
|
||||
// wantAudience grows for every API we add to the project.
|
||||
wantAudience = append(wantAudience, apiID)
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, app.GetClientId(), code)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
|
||||
scope := []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopeOfflineAccess, oidc_api.ScopeResourceOwner}
|
||||
authRequestID := createAuthRequest(t, app.GetClientId(), redirectURI, scope...)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
SessionId: sessionID,
|
||||
SessionToken: sessionToken,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// test actual introspection
|
||||
introspection, err := rs.Introspect[*oidc.IntrospectionResponse](context.Background(), resourceServer, tokens.AccessToken)
|
||||
require.NoError(t, err)
|
||||
assertIntrospection(t, introspection,
|
||||
Tester.OIDCIssuer(), app.GetClientId(),
|
||||
scope, []string{app.GetClientId(), api.GetClientId(), project.GetId()},
|
||||
tokens.Expiry, tokens.Expiry.Add(-12*time.Hour))
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, app.GetClientId(), code)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, true)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
|
||||
|
||||
// test actual introspection
|
||||
introspection, err := rs.Introspect[*oidc.IntrospectionResponse](context.Background(), resourceServer, tokens.AccessToken)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
assertIntrospection(t, introspection,
|
||||
Tester.OIDCIssuer(), app.GetClientId(),
|
||||
scope, wantAudience,
|
||||
tokens.Expiry, tokens.Expiry.Add(-12*time.Hour))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func assertUserinfo(t *testing.T, userinfo *oidc.UserInfo) {
|
||||
@ -158,7 +228,7 @@ func TestServer_VerifyClient(t *testing.T) {
|
||||
|
||||
inactiveClient, err := Tester.CreateOIDCInactivateClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
require.NoError(t, err)
|
||||
nativeClient, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
nativeClient, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId(), false)
|
||||
require.NoError(t, err)
|
||||
basicWebClient, err := Tester.CreateOIDCWebClientBasic(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
require.NoError(t, err)
|
||||
|
@ -72,7 +72,7 @@ func (s *Server) Introspect(ctx context.Context, r *op.Request[op.IntrospectionR
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// remaining errors shoudn't be returned to the client,
|
||||
// remaining errors shouldn't be returned to the client,
|
||||
// so we catch errors here, log them and return the response
|
||||
// with active: false
|
||||
defer func() {
|
||||
@ -122,6 +122,8 @@ type introspectionClientResult struct {
|
||||
err error
|
||||
}
|
||||
|
||||
var errNoClientSecret = errors.New("client has no configured secret")
|
||||
|
||||
func (s *Server) introspectionClientAuth(ctx context.Context, cc *op.ClientCredentials, rc chan<- *introspectionClientResult) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
|
||||
@ -136,13 +138,16 @@ func (s *Server) introspectionClientAuth(ctx context.Context, cc *op.ClientCrede
|
||||
if _, err := op.VerifyJWTAssertion(ctx, cc.ClientAssertion, verifier); err != nil {
|
||||
return "", "", oidc.ErrUnauthorizedClient().WithParent(err)
|
||||
}
|
||||
} else {
|
||||
return client.ClientID, client.ProjectID, nil
|
||||
|
||||
}
|
||||
if client.ClientSecret != nil {
|
||||
if err := crypto.CompareHash(client.ClientSecret, []byte(cc.ClientSecret), s.hashAlg); err != nil {
|
||||
return "", "", oidc.ErrUnauthorizedClient().WithParent(err)
|
||||
}
|
||||
return client.ClientID, client.ProjectID, nil
|
||||
}
|
||||
|
||||
return client.ClientID, client.ProjectID, nil
|
||||
return "", "", oidc.ErrUnauthorizedClient().WithParent(errNoClientSecret)
|
||||
}()
|
||||
|
||||
span.EndWithError(err)
|
||||
|
@ -174,6 +174,40 @@ func Test_ZITADEL_API_success(t *testing.T) {
|
||||
require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId())
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_glob_redirects(t *testing.T) {
|
||||
const redirectURI = "https://my-org-1yfnjl2xj-my-app.vercel.app/api/auth/callback/zitadel"
|
||||
clientID := createClientWithOpts(t, clientOpts{
|
||||
redirectURI: "https://my-org-*-my-app.vercel.app/api/auth/callback/zitadel",
|
||||
logoutURI: "https://my-org-*-my-app.vercel.app/",
|
||||
devMode: true,
|
||||
})
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, zitadelAudienceScope)
|
||||
sessionID, sessionToken, startTime, changeTime := Tester.CreateVerifiedWebAuthNSession(t, CTXLOGIN, User.GetUserId())
|
||||
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{
|
||||
AuthRequestId: authRequestID,
|
||||
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
|
||||
Session: &oidc_pb.Session{
|
||||
SessionId: sessionID,
|
||||
SessionToken: sessionToken,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// code exchange
|
||||
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
|
||||
tokens, err := exchangeTokens(t, clientID, code)
|
||||
require.NoError(t, err)
|
||||
assertTokens(t, tokens, false)
|
||||
assertIDTokenClaims(t, tokens.IDTokenClaims, armPasskey, startTime, changeTime)
|
||||
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), "Authorization", fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken))
|
||||
|
||||
myUserResp, err := Tester.Client.Auth.GetMyUser(ctx, &auth.GetMyUserRequest{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, User.GetUserId(), myUserResp.GetUser().GetId())
|
||||
}
|
||||
|
||||
func Test_ZITADEL_API_inactive_access_token(t *testing.T) {
|
||||
clientID := createClient(t)
|
||||
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
|
||||
@ -257,9 +291,23 @@ func Test_ZITADEL_API_terminated_session(t *testing.T) {
|
||||
}
|
||||
|
||||
func createClient(t testing.TB) string {
|
||||
return createClientWithOpts(t, clientOpts{
|
||||
redirectURI: redirectURI,
|
||||
logoutURI: logoutRedirectURI,
|
||||
devMode: false,
|
||||
})
|
||||
}
|
||||
|
||||
type clientOpts struct {
|
||||
redirectURI string
|
||||
logoutURI string
|
||||
devMode bool
|
||||
}
|
||||
|
||||
func createClientWithOpts(t testing.TB, opts clientOpts) string {
|
||||
project, err := Tester.CreateProject(CTX)
|
||||
require.NoError(t, err)
|
||||
app, err := Tester.CreateOIDCNativeClient(CTX, redirectURI, logoutRedirectURI, project.GetId())
|
||||
app, err := Tester.CreateOIDCNativeClient(CTX, opts.redirectURI, opts.logoutURI, project.GetId(), opts.devMode)
|
||||
require.NoError(t, err)
|
||||
return app.GetClientId()
|
||||
}
|
||||
|
@ -20,8 +20,3 @@ func (repo *UserSessionRepo) GetMyUserSessions(ctx context.Context) ([]*usr_mode
|
||||
}
|
||||
return model.UserSessionsToModel(userSessions), nil
|
||||
}
|
||||
|
||||
func (repo *UserSessionRepo) ActiveUserSessionCount() int64 {
|
||||
userSessions, _ := repo.View.ActiveUserSessionsCount()
|
||||
return int64(userSessions)
|
||||
}
|
||||
|
@ -8,5 +8,4 @@ import (
|
||||
|
||||
type UserSessionRepository interface {
|
||||
GetMyUserSessions(ctx context.Context) ([]*model.UserSessionView, error)
|
||||
ActiveUserSessionCount() int64
|
||||
}
|
||||
|
223
internal/cache/bigcache/bigcache_test.go
vendored
223
internal/cache/bigcache/bigcache_test.go
vendored
@ -1,223 +0,0 @@
|
||||
package bigcache
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
a_cache "github.com/allegro/bigcache"
|
||||
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type TestStruct struct {
|
||||
Test string
|
||||
}
|
||||
|
||||
func getBigCacheMock() *Bigcache {
|
||||
cache, _ := a_cache.NewBigCache(a_cache.DefaultConfig(2000))
|
||||
return &Bigcache{cache: cache}
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
type args struct {
|
||||
cache *Bigcache
|
||||
key string
|
||||
value *TestStruct
|
||||
}
|
||||
type res struct {
|
||||
result *TestStruct
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "set cache no err",
|
||||
args: args{
|
||||
cache: getBigCacheMock(),
|
||||
key: "KEY",
|
||||
value: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
result: &TestStruct{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "key empty",
|
||||
args: args{
|
||||
cache: getBigCacheMock(),
|
||||
key: "",
|
||||
value: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set cache nil value",
|
||||
args: args{
|
||||
cache: getBigCacheMock(),
|
||||
key: "KEY",
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.args.cache.Set(tt.args.key, tt.args.value)
|
||||
|
||||
if tt.res.errFunc == nil && err != nil {
|
||||
t.Errorf("got wrong result should not get err: %v ", err)
|
||||
}
|
||||
|
||||
if tt.res.errFunc == nil {
|
||||
tt.args.cache.Get(tt.args.key, tt.res.result)
|
||||
if tt.res.result == nil {
|
||||
t.Errorf("got wrong result should get result: %v ", err)
|
||||
}
|
||||
}
|
||||
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
type args struct {
|
||||
event []*es_models.Event
|
||||
cache *Bigcache
|
||||
key string
|
||||
setValue *TestStruct
|
||||
getValue *TestStruct
|
||||
}
|
||||
type res struct {
|
||||
result *TestStruct
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "get cache no err",
|
||||
args: args{
|
||||
cache: getBigCacheMock(),
|
||||
key: "KEY",
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
getValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
result: &TestStruct{Test: "Test"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get cache no key",
|
||||
args: args{
|
||||
cache: getBigCacheMock(),
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
getValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get cache no value",
|
||||
args: args{
|
||||
cache: getBigCacheMock(),
|
||||
key: "KEY",
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.args.cache.Set("KEY", tt.args.setValue)
|
||||
if err != nil {
|
||||
t.Errorf("something went wrong")
|
||||
}
|
||||
|
||||
err = tt.args.cache.Get(tt.args.key, tt.args.getValue)
|
||||
|
||||
if tt.res.errFunc == nil && err != nil {
|
||||
t.Errorf("got wrong result should not get err: %v ", err)
|
||||
}
|
||||
|
||||
if tt.res.errFunc == nil && !reflect.DeepEqual(tt.args.getValue, tt.res.result) {
|
||||
t.Errorf("got wrong result expected: %v actual: %v", tt.res.result, tt.args.getValue)
|
||||
}
|
||||
|
||||
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
type args struct {
|
||||
event []*es_models.Event
|
||||
cache *Bigcache
|
||||
key string
|
||||
setValue *TestStruct
|
||||
getValue *TestStruct
|
||||
}
|
||||
type res struct {
|
||||
result *TestStruct
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "delete cache no err",
|
||||
args: args{
|
||||
cache: getBigCacheMock(),
|
||||
key: "KEY",
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{},
|
||||
},
|
||||
{
|
||||
name: "get cache no key",
|
||||
args: args{
|
||||
cache: getBigCacheMock(),
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
getValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.args.cache.Set("KEY", tt.args.setValue)
|
||||
if err != nil {
|
||||
t.Errorf("something went wrong")
|
||||
}
|
||||
|
||||
err = tt.args.cache.Delete(tt.args.key)
|
||||
|
||||
if tt.res.errFunc == nil && err != nil {
|
||||
t.Errorf("got wrong result should not get err: %v ", err)
|
||||
}
|
||||
|
||||
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
67
internal/cache/bigcache/cache.go
vendored
67
internal/cache/bigcache/cache.go
vendored
@ -1,67 +0,0 @@
|
||||
package bigcache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"reflect"
|
||||
|
||||
a_cache "github.com/allegro/bigcache"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type Bigcache struct {
|
||||
cache *a_cache.BigCache
|
||||
}
|
||||
|
||||
func NewBigcache(c *Config) (*Bigcache, error) {
|
||||
cacheConfig := a_cache.DefaultConfig(c.CacheLifetime)
|
||||
cacheConfig.HardMaxCacheSize = c.MaxCacheSizeInMB
|
||||
cache, err := a_cache.NewBigCache(cacheConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Bigcache{
|
||||
cache: cache,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Bigcache) Set(key string, object interface{}) error {
|
||||
if key == "" || reflect.ValueOf(object).IsNil() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "BIGCA-du73s", "key or value should not be empty")
|
||||
}
|
||||
var b bytes.Buffer
|
||||
enc := gob.NewEncoder(&b)
|
||||
if err := enc.Encode(object); err != nil {
|
||||
return zerrors.ThrowInvalidArgument(err, "BIGCA-RUyxI", "unable to encode object")
|
||||
}
|
||||
return c.cache.Set(key, b.Bytes())
|
||||
}
|
||||
|
||||
func (c *Bigcache) Get(key string, ptrToObject interface{}) error {
|
||||
if key == "" || reflect.ValueOf(ptrToObject).IsNil() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "BIGCA-dksoe", "key or value should not be empty")
|
||||
}
|
||||
value, err := c.cache.Get(key)
|
||||
if err == a_cache.ErrEntryNotFound {
|
||||
return zerrors.ThrowNotFound(err, "BIGCA-we32s", "not in cache")
|
||||
}
|
||||
if err != nil {
|
||||
logging.Log("BIGCA-ftofbc").WithError(err).Info("read from cache failed")
|
||||
return zerrors.ThrowInvalidArgument(err, "BIGCA-3idls", "error in reading from cache")
|
||||
}
|
||||
|
||||
b := bytes.NewBuffer(value)
|
||||
dec := gob.NewDecoder(b)
|
||||
|
||||
return dec.Decode(ptrToObject)
|
||||
}
|
||||
|
||||
func (c *Bigcache) Delete(key string) error {
|
||||
if key == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "BIGCA-clsi2", "key should not be empty")
|
||||
}
|
||||
return c.cache.Delete(key)
|
||||
}
|
17
internal/cache/bigcache/config.go
vendored
17
internal/cache/bigcache/config.go
vendored
@ -1,17 +0,0 @@
|
||||
package bigcache
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/cache"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
MaxCacheSizeInMB int
|
||||
//CacheLifetime if set, entries older than the lifetime will be deleted on cleanup (every minute)
|
||||
CacheLifetime time.Duration
|
||||
}
|
||||
|
||||
func (c *Config) NewCache() (cache.Cache, error) {
|
||||
return NewBigcache(c)
|
||||
}
|
7
internal/cache/cache.go
vendored
7
internal/cache/cache.go
vendored
@ -1,7 +0,0 @@
|
||||
package cache
|
||||
|
||||
type Cache interface {
|
||||
Set(key string, object interface{}) error
|
||||
Get(key string, ptrToObject interface{}) error
|
||||
Delete(key string) error
|
||||
}
|
5
internal/cache/config.go
vendored
5
internal/cache/config.go
vendored
@ -1,5 +0,0 @@
|
||||
package cache
|
||||
|
||||
type Config interface {
|
||||
NewCache() (Cache, error)
|
||||
}
|
59
internal/cache/config/config.go
vendored
59
internal/cache/config/config.go
vendored
@ -1,59 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/cache"
|
||||
"github.com/zitadel/zitadel/internal/cache/bigcache"
|
||||
"github.com/zitadel/zitadel/internal/cache/fastcache"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type CacheConfig struct {
|
||||
Type string
|
||||
Config cache.Config
|
||||
}
|
||||
|
||||
var caches = map[string]func() cache.Config{
|
||||
"bigcache": func() cache.Config { return &bigcache.Config{} },
|
||||
"fastcache": func() cache.Config { return &fastcache.Config{} },
|
||||
}
|
||||
|
||||
func (c *CacheConfig) UnmarshalJSON(data []byte) error {
|
||||
var rc struct {
|
||||
Type string
|
||||
Config json.RawMessage
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &rc); err != nil {
|
||||
return zerrors.ThrowInternal(err, "CONFI-98ejs", "unable to unmarshal config")
|
||||
}
|
||||
|
||||
c.Type = rc.Type
|
||||
|
||||
var err error
|
||||
c.Config, err = newCacheConfig(c.Type, rc.Config)
|
||||
if err != nil {
|
||||
return zerrors.ThrowInternal(err, "CONFI-do9es", "unable create config")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newCacheConfig(cacheType string, configData []byte) (cache.Config, error) {
|
||||
t, ok := caches[cacheType]
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInternal(nil, "CONFI-di328s", "no config")
|
||||
}
|
||||
|
||||
cacheConfig := t()
|
||||
if len(configData) == 0 {
|
||||
return cacheConfig, nil
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(configData, cacheConfig); err != nil {
|
||||
return nil, zerrors.ThrowInternal(nil, "CONFI-skei3", "could not read config")
|
||||
}
|
||||
|
||||
return cacheConfig, nil
|
||||
}
|
11
internal/cache/fastcache/config.go
vendored
11
internal/cache/fastcache/config.go
vendored
@ -1,11 +0,0 @@
|
||||
package fastcache
|
||||
|
||||
import "github.com/zitadel/zitadel/internal/cache"
|
||||
|
||||
type Config struct {
|
||||
MaxCacheSizeInByte int
|
||||
}
|
||||
|
||||
func (c *Config) NewCache() (cache.Cache, error) {
|
||||
return NewFastcache(c)
|
||||
}
|
57
internal/cache/fastcache/fastcache.go
vendored
57
internal/cache/fastcache/fastcache.go
vendored
@ -1,57 +0,0 @@
|
||||
package fastcache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"reflect"
|
||||
|
||||
"github.com/VictoriaMetrics/fastcache"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type Fastcache struct {
|
||||
cache *fastcache.Cache
|
||||
}
|
||||
|
||||
func NewFastcache(config *Config) (*Fastcache, error) {
|
||||
return &Fastcache{
|
||||
cache: fastcache.New(config.MaxCacheSizeInByte),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (fc *Fastcache) Set(key string, object interface{}) error {
|
||||
if key == "" || reflect.ValueOf(object).IsNil() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "FASTC-87dj3", "key or value should not be empty")
|
||||
}
|
||||
var b bytes.Buffer
|
||||
enc := gob.NewEncoder(&b)
|
||||
if err := enc.Encode(object); err != nil {
|
||||
return zerrors.ThrowInvalidArgument(err, "FASTC-RUyxI", "unable to encode object")
|
||||
}
|
||||
fc.cache.Set([]byte(key), b.Bytes())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fc *Fastcache) Get(key string, ptrToObject interface{}) error {
|
||||
if key == "" || reflect.ValueOf(ptrToObject).IsNil() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "FASTC-di8es", "key or value should not be empty")
|
||||
}
|
||||
data := fc.cache.Get(nil, []byte(key))
|
||||
if len(data) == 0 {
|
||||
return zerrors.ThrowNotFound(nil, "FASTC-xYzSm", "key not found")
|
||||
}
|
||||
|
||||
b := bytes.NewBuffer(data)
|
||||
dec := gob.NewDecoder(b)
|
||||
|
||||
return dec.Decode(ptrToObject)
|
||||
}
|
||||
|
||||
func (fc *Fastcache) Delete(key string) error {
|
||||
if key == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "FASTC-lod92", "key should not be empty")
|
||||
}
|
||||
fc.cache.Del([]byte(key))
|
||||
return nil
|
||||
}
|
218
internal/cache/fastcache/fastcache_test.go
vendored
218
internal/cache/fastcache/fastcache_test.go
vendored
@ -1,218 +0,0 @@
|
||||
package fastcache
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/VictoriaMetrics/fastcache"
|
||||
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type TestStruct struct {
|
||||
Test string
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
type args struct {
|
||||
cache *Fastcache
|
||||
key string
|
||||
value *TestStruct
|
||||
}
|
||||
type res struct {
|
||||
result *TestStruct
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "set cache no err",
|
||||
args: args{
|
||||
cache: &Fastcache{cache: fastcache.New(2000)},
|
||||
key: "KEY",
|
||||
value: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
result: &TestStruct{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "key empty",
|
||||
args: args{
|
||||
cache: &Fastcache{cache: fastcache.New(2000)},
|
||||
key: "",
|
||||
value: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set cache nil value",
|
||||
args: args{
|
||||
cache: &Fastcache{cache: fastcache.New(2000)},
|
||||
key: "KEY",
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.args.cache.Set(tt.args.key, tt.args.value)
|
||||
|
||||
if tt.res.errFunc == nil && err != nil {
|
||||
t.Errorf("got wrong result should not get err: %v ", err)
|
||||
}
|
||||
|
||||
if tt.res.errFunc == nil {
|
||||
tt.args.cache.Get(tt.args.key, tt.res.result)
|
||||
if tt.res.result == nil {
|
||||
t.Errorf("got wrong result should get result: %v ", err)
|
||||
}
|
||||
}
|
||||
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
type args struct {
|
||||
event []*es_models.Event
|
||||
cache *Fastcache
|
||||
key string
|
||||
setValue *TestStruct
|
||||
getValue *TestStruct
|
||||
}
|
||||
type res struct {
|
||||
result *TestStruct
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "get cache no err",
|
||||
args: args{
|
||||
cache: &Fastcache{cache: fastcache.New(2000)},
|
||||
key: "KEY",
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
getValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
result: &TestStruct{Test: "Test"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get cache no key",
|
||||
args: args{
|
||||
cache: &Fastcache{cache: fastcache.New(2000)},
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
getValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get cache no value",
|
||||
args: args{
|
||||
cache: &Fastcache{cache: fastcache.New(2000)},
|
||||
key: "KEY",
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.args.cache.Set("KEY", tt.args.setValue)
|
||||
if err != nil {
|
||||
t.Errorf("something went wrong")
|
||||
}
|
||||
|
||||
err = tt.args.cache.Get(tt.args.key, tt.args.getValue)
|
||||
|
||||
if tt.res.errFunc == nil && err != nil {
|
||||
t.Errorf("got wrong result should not get err: %v ", err)
|
||||
}
|
||||
|
||||
if tt.res.errFunc == nil && !reflect.DeepEqual(tt.args.getValue, tt.res.result) {
|
||||
t.Errorf("got wrong result expected: %v actual: %v", tt.res.result, tt.args.getValue)
|
||||
}
|
||||
|
||||
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
type args struct {
|
||||
event []*es_models.Event
|
||||
cache *Fastcache
|
||||
key string
|
||||
setValue *TestStruct
|
||||
getValue *TestStruct
|
||||
}
|
||||
type res struct {
|
||||
result *TestStruct
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "delete cache no err",
|
||||
args: args{
|
||||
cache: &Fastcache{cache: fastcache.New(2000)},
|
||||
key: "KEY",
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{},
|
||||
},
|
||||
{
|
||||
name: "get cache no key",
|
||||
args: args{
|
||||
cache: &Fastcache{cache: fastcache.New(2000)},
|
||||
setValue: &TestStruct{Test: "Test"},
|
||||
getValue: &TestStruct{Test: "Test"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: zerrors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.args.cache.Set("KEY", tt.args.setValue)
|
||||
if err != nil {
|
||||
t.Errorf("something went wrong")
|
||||
}
|
||||
|
||||
err = tt.args.cache.Delete(tt.args.key)
|
||||
|
||||
if tt.res.errFunc == nil && err != nil {
|
||||
t.Errorf("got wrong result should not get err: %v ", err)
|
||||
}
|
||||
|
||||
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
3
internal/cache/generate.go
vendored
3
internal/cache/generate.go
vendored
@ -1,3 +0,0 @@
|
||||
package cache
|
||||
|
||||
//go:generate mockgen -package mock -destination ./mock/cache.mock.go github.com/zitadel/zitadel/internal/cache Cache
|
80
internal/cache/mock/cache.mock.go
vendored
80
internal/cache/mock/cache.mock.go
vendored
@ -1,80 +0,0 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/zitadel/zitadel/internal/cache (interfaces: Cache)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -package mock -destination ./mock/cache.mock.go github.com/zitadel/zitadel/internal/cache Cache
|
||||
//
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockCache is a mock of Cache interface.
|
||||
type MockCache struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockCacheMockRecorder
|
||||
}
|
||||
|
||||
// MockCacheMockRecorder is the mock recorder for MockCache.
|
||||
type MockCacheMockRecorder struct {
|
||||
mock *MockCache
|
||||
}
|
||||
|
||||
// NewMockCache creates a new mock instance.
|
||||
func NewMockCache(ctrl *gomock.Controller) *MockCache {
|
||||
mock := &MockCache{ctrl: ctrl}
|
||||
mock.recorder = &MockCacheMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockCache) EXPECT() *MockCacheMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Delete mocks base method.
|
||||
func (m *MockCache) Delete(arg0 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delete", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete.
|
||||
func (mr *MockCacheMockRecorder) Delete(arg0 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockCache)(nil).Delete), arg0)
|
||||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockCache) Get(arg0 string, arg1 any) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockCacheMockRecorder) Get(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCache)(nil).Get), arg0, arg1)
|
||||
}
|
||||
|
||||
// Set mocks base method.
|
||||
func (m *MockCache) Set(arg0 string, arg1 any) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Set", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Set indicates an expected call of Set.
|
||||
func (mr *MockCacheMockRecorder) Set(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockCache)(nil).Set), arg0, arg1)
|
||||
}
|
@ -2,303 +2,8 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/idpconfig"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/member"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/repository/policy"
|
||||
"github.com/zitadel/zitadel/internal/repository/project"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
"github.com/zitadel/zitadel/internal/repository/usergrant"
|
||||
)
|
||||
|
||||
type UniqueConstraintReadModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
UniqueConstraints []*domain.UniqueConstraintMigration
|
||||
commandProvider commandProvider
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
type commandProvider interface {
|
||||
domainPolicyWriteModel(ctx context.Context, orgID string) (*PolicyDomainWriteModel, error)
|
||||
}
|
||||
|
||||
func NewUniqueConstraintReadModel(ctx context.Context, provider commandProvider) *UniqueConstraintReadModel {
|
||||
return &UniqueConstraintReadModel{
|
||||
ctx: ctx,
|
||||
commandProvider: provider,
|
||||
}
|
||||
}
|
||||
|
||||
func (rm *UniqueConstraintReadModel) AppendEvents(events ...eventstore.Event) {
|
||||
rm.WriteModel.AppendEvents(events...)
|
||||
}
|
||||
|
||||
func (rm *UniqueConstraintReadModel) Reduce() error {
|
||||
for _, event := range rm.Events {
|
||||
switch e := event.(type) {
|
||||
case *org.OrgAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, org.NewAddOrgNameUniqueConstraint(e.Name))
|
||||
case *org.OrgChangedEvent:
|
||||
rm.changeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, org.NewAddOrgNameUniqueConstraint(e.Name))
|
||||
case *org.DomainVerifiedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, org.NewAddOrgDomainUniqueConstraint(e.Domain))
|
||||
case *org.DomainRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, org.UniqueOrgDomain)
|
||||
case *instance.IDPConfigAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.ConfigID, idpconfig.NewAddIDPConfigNameUniqueConstraint(e.Name, e.Aggregate().ResourceOwner))
|
||||
case *instance.IDPConfigChangedEvent:
|
||||
if e.Name == nil {
|
||||
continue
|
||||
}
|
||||
rm.changeUniqueConstraint(e.Aggregate().ID, e.ConfigID, idpconfig.NewAddIDPConfigNameUniqueConstraint(*e.Name, e.Aggregate().ResourceOwner))
|
||||
case *instance.IDPConfigRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.ConfigID, idpconfig.UniqueIDPConfigNameType)
|
||||
case *org.IDPConfigAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.ConfigID, idpconfig.NewAddIDPConfigNameUniqueConstraint(e.Name, e.Aggregate().ResourceOwner))
|
||||
case *org.IDPConfigChangedEvent:
|
||||
if e.Name == nil {
|
||||
continue
|
||||
}
|
||||
rm.changeUniqueConstraint(e.Aggregate().ID, e.ConfigID, idpconfig.NewAddIDPConfigNameUniqueConstraint(*e.Name, e.Aggregate().ResourceOwner))
|
||||
case *org.IDPConfigRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.ConfigID, idpconfig.UniqueIDPConfigNameType)
|
||||
case *instance.MailTextAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.MailTextType+e.Language, policy.NewAddMailTextUniqueConstraint(e.Aggregate().ID, e.MailTextType, e.Language))
|
||||
case *org.MailTextAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.MailTextType+e.Language, policy.NewAddMailTextUniqueConstraint(e.Aggregate().ID, e.MailTextType, e.Language))
|
||||
case *org.MailTextRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.MailTextType+e.Language, policy.UniqueMailText)
|
||||
case *project.ProjectAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, project.NewAddProjectNameUniqueConstraint(e.Name, e.Aggregate().ResourceOwner))
|
||||
case *project.ProjectChangeEvent:
|
||||
if e.Name == nil {
|
||||
continue
|
||||
}
|
||||
rm.changeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, project.NewAddProjectNameUniqueConstraint(*e.Name, e.Aggregate().ResourceOwner))
|
||||
case *project.ProjectRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, project.UniqueProjectnameType)
|
||||
rm.listRemoveUniqueConstraint(e.Aggregate().ID, project.UniqueAppNameType)
|
||||
rm.listRemoveUniqueConstraint(e.Aggregate().ID, member.UniqueMember)
|
||||
rm.listRemoveUniqueConstraint(e.Aggregate().ID, project.UniqueRoleType)
|
||||
rm.listRemoveUniqueConstraint(e.Aggregate().ID, project.UniqueGrantType)
|
||||
rm.listRemoveUniqueConstraint(e.Aggregate().ID, project.UniqueProjectGrantMemberType)
|
||||
case *project.ApplicationAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.AppID, project.NewAddApplicationUniqueConstraint(e.Name, e.Aggregate().ID))
|
||||
case *project.ApplicationChangedEvent:
|
||||
rm.changeUniqueConstraint(e.Aggregate().ID, e.AppID, project.NewAddApplicationUniqueConstraint(e.Name, e.Aggregate().ID))
|
||||
case *project.SAMLConfigAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.AppID, project.NewAddSAMLConfigEntityIDUniqueConstraint(e.EntityID))
|
||||
case *project.SAMLConfigChangedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.AppID, project.NewRemoveSAMLConfigEntityIDUniqueConstraint(e.EntityID))
|
||||
case *project.ApplicationRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.AppID, project.UniqueAppNameType)
|
||||
case *project.GrantAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.GrantID, project.NewAddProjectGrantUniqueConstraint(e.GrantedOrgID, e.Aggregate().ID))
|
||||
case *project.GrantRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.GrantID, project.UniqueGrantType)
|
||||
case *project.GrantMemberAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.GrantID+e.UserID, project.NewAddProjectGrantMemberUniqueConstraint(e.Aggregate().ID, e.UserID, e.GrantID))
|
||||
case *project.GrantMemberRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.GrantID+e.UserID, project.UniqueProjectGrantMemberType)
|
||||
case *project.GrantMemberCascadeRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.GrantID+e.UserID, project.UniqueProjectGrantMemberType)
|
||||
case *project.RoleAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.Key, project.NewAddProjectRoleUniqueConstraint(e.Key, e.Aggregate().ID))
|
||||
case *project.RoleRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.Key, project.UniqueRoleType)
|
||||
case *user.HumanAddedEvent:
|
||||
policy, err := rm.commandProvider.domainPolicyWriteModel(rm.ctx, e.Aggregate().ResourceOwner)
|
||||
if err != nil {
|
||||
logging.Log("COMMAND-0k9Gs").WithError(err).Error("could not read policy for human added event unique constraint")
|
||||
continue
|
||||
}
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, user.NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, policy.UserLoginMustBeDomain))
|
||||
case *user.HumanRegisteredEvent:
|
||||
policy, err := rm.commandProvider.domainPolicyWriteModel(rm.ctx, e.Aggregate().ResourceOwner)
|
||||
if err != nil {
|
||||
logging.Log("COMMAND-m9fod").WithError(err).Error("could not read policy for human registered event unique constraint")
|
||||
continue
|
||||
}
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, user.NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, policy.UserLoginMustBeDomain))
|
||||
case *user.MachineAddedEvent:
|
||||
policy, err := rm.commandProvider.domainPolicyWriteModel(rm.ctx, e.Aggregate().ResourceOwner)
|
||||
if err != nil {
|
||||
logging.Log("COMMAND-2n8vs").WithError(err).Error("could not read policy for machine added event unique constraint")
|
||||
continue
|
||||
}
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, user.NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, policy.UserLoginMustBeDomain))
|
||||
case *user.UserRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, user.UniqueUsername)
|
||||
rm.listRemoveUniqueConstraint(e.Aggregate().ID, user.UniqueUserIDPLinkType)
|
||||
case *user.UsernameChangedEvent:
|
||||
policy, err := rm.commandProvider.domainPolicyWriteModel(rm.ctx, e.Aggregate().ResourceOwner)
|
||||
if err != nil {
|
||||
logging.Log("COMMAND-5n8gk").WithError(err).Error("could not read policy for username changed event unique constraint")
|
||||
continue
|
||||
}
|
||||
rm.changeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, user.NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, policy.UserLoginMustBeDomain))
|
||||
case *user.DomainClaimedEvent:
|
||||
policy, err := rm.commandProvider.domainPolicyWriteModel(rm.ctx, e.Aggregate().ResourceOwner)
|
||||
if err != nil {
|
||||
logging.Log("COMMAND-xb8uf").WithError(err).Error("could not read policy for domain claimed event unique constraint")
|
||||
continue
|
||||
}
|
||||
rm.changeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, user.NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, policy.UserLoginMustBeDomain))
|
||||
case *user.UserIDPLinkAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.IDPConfigID+e.ExternalUserID, user.NewAddUserIDPLinkUniqueConstraint(e.IDPConfigID, e.ExternalUserID))
|
||||
case *user.UserIDPLinkRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.IDPConfigID+e.ExternalUserID, user.UniqueUserIDPLinkType)
|
||||
case *user.UserIDPLinkCascadeRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.IDPConfigID+e.ExternalUserID, user.UniqueUserIDPLinkType)
|
||||
case *usergrant.UserGrantAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, usergrant.NewAddUserGrantUniqueConstraint(e.Aggregate().ResourceOwner, e.UserID, e.ProjectID, e.ProjectGrantID))
|
||||
case *usergrant.UserGrantRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, usergrant.UniqueUserGrant)
|
||||
case *usergrant.UserGrantCascadeRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.Aggregate().ID, usergrant.UniqueUserGrant)
|
||||
case *instance.MemberAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.UserID, member.NewAddMemberUniqueConstraint(e.Aggregate().ID, e.UserID))
|
||||
case *instance.MemberRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.UserID, member.UniqueMember)
|
||||
case *instance.MemberCascadeRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.UserID, member.UniqueMember)
|
||||
case *org.MemberAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.UserID, member.NewAddMemberUniqueConstraint(e.Aggregate().ID, e.UserID))
|
||||
case *org.MemberRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.UserID, member.UniqueMember)
|
||||
case *org.MemberCascadeRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.UserID, member.UniqueMember)
|
||||
case *project.MemberAddedEvent:
|
||||
rm.addUniqueConstraint(e.Aggregate().ID, e.UserID, member.NewAddMemberUniqueConstraint(e.Aggregate().ID, e.UserID))
|
||||
case *project.MemberRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.UserID, member.UniqueMember)
|
||||
case *project.MemberCascadeRemovedEvent:
|
||||
rm.removeUniqueConstraint(e.Aggregate().ID, e.UserID, member.UniqueMember)
|
||||
}
|
||||
}
|
||||
return rm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (rm *UniqueConstraintReadModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
AddQuery().AggregateTypes(
|
||||
instance.AggregateType,
|
||||
org.AggregateType,
|
||||
project.AggregateType,
|
||||
user.AggregateType,
|
||||
usergrant.AggregateType).
|
||||
EventTypes(
|
||||
org.OrgAddedEventType,
|
||||
org.OrgChangedEventType,
|
||||
org.OrgDomainVerifiedEventType,
|
||||
org.OrgDomainRemovedEventType,
|
||||
instance.IDPConfigAddedEventType,
|
||||
instance.IDPConfigChangedEventType,
|
||||
instance.IDPConfigRemovedEventType,
|
||||
org.IDPConfigAddedEventType,
|
||||
org.IDPConfigChangedEventType,
|
||||
org.IDPConfigRemovedEventType,
|
||||
instance.MailTextAddedEventType,
|
||||
org.MailTextAddedEventType,
|
||||
org.MailTextRemovedEventType,
|
||||
project.ProjectAddedType,
|
||||
project.ProjectChangedType,
|
||||
project.ProjectRemovedType,
|
||||
project.ApplicationAddedType,
|
||||
project.ApplicationChangedType,
|
||||
project.ApplicationRemovedType,
|
||||
project.GrantAddedType,
|
||||
project.GrantRemovedType,
|
||||
project.GrantMemberAddedType,
|
||||
project.GrantMemberRemovedType,
|
||||
project.GrantMemberCascadeRemovedType,
|
||||
project.RoleAddedType,
|
||||
project.RoleRemovedType,
|
||||
user.UserV1AddedType,
|
||||
user.UserV1RegisteredType,
|
||||
user.HumanAddedType,
|
||||
user.HumanRegisteredType,
|
||||
user.MachineAddedEventType,
|
||||
user.UserUserNameChangedType,
|
||||
user.UserDomainClaimedType,
|
||||
user.UserRemovedType,
|
||||
user.UserIDPLinkAddedType,
|
||||
user.UserIDPLinkRemovedType,
|
||||
user.UserIDPLinkCascadeRemovedType,
|
||||
usergrant.UserGrantAddedType,
|
||||
usergrant.UserGrantRemovedType,
|
||||
usergrant.UserGrantCascadeRemovedType,
|
||||
instance.MemberAddedEventType,
|
||||
instance.MemberRemovedEventType,
|
||||
instance.MemberCascadeRemovedEventType,
|
||||
org.MemberAddedEventType,
|
||||
org.MemberRemovedEventType,
|
||||
org.MemberCascadeRemovedEventType,
|
||||
project.MemberAddedType,
|
||||
project.MemberRemovedType,
|
||||
project.MemberCascadeRemovedType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (rm *UniqueConstraintReadModel) getUniqueConstraint(aggregateID, objectID, constraintType string) *domain.UniqueConstraintMigration {
|
||||
for _, uniqueConstraint := range rm.UniqueConstraints {
|
||||
if uniqueConstraint.AggregateID == aggregateID && uniqueConstraint.ObjectID == objectID && uniqueConstraint.UniqueType == constraintType {
|
||||
return uniqueConstraint
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rm *UniqueConstraintReadModel) addUniqueConstraint(aggregateID, objectID string, constraint *eventstore.UniqueConstraint) {
|
||||
migrateUniqueConstraint := &domain.UniqueConstraintMigration{
|
||||
AggregateID: aggregateID,
|
||||
ObjectID: objectID,
|
||||
UniqueType: constraint.UniqueType,
|
||||
UniqueField: constraint.UniqueField,
|
||||
ErrorMessage: constraint.ErrorMessage,
|
||||
}
|
||||
rm.UniqueConstraints = append(rm.UniqueConstraints, migrateUniqueConstraint)
|
||||
}
|
||||
|
||||
func (rm *UniqueConstraintReadModel) changeUniqueConstraint(aggregateID, objectID string, constraint *eventstore.UniqueConstraint) {
|
||||
for i, uniqueConstraint := range rm.UniqueConstraints {
|
||||
if uniqueConstraint.AggregateID == aggregateID && uniqueConstraint.ObjectID == objectID && uniqueConstraint.UniqueType == constraint.UniqueType {
|
||||
rm.UniqueConstraints[i] = &domain.UniqueConstraintMigration{
|
||||
AggregateID: aggregateID,
|
||||
ObjectID: objectID,
|
||||
UniqueType: constraint.UniqueType,
|
||||
UniqueField: constraint.UniqueField,
|
||||
ErrorMessage: constraint.ErrorMessage,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rm *UniqueConstraintReadModel) removeUniqueConstraint(aggregateID, objectID, constraintType string) {
|
||||
for i, uniqueConstraint := range rm.UniqueConstraints {
|
||||
if uniqueConstraint.AggregateID == aggregateID && uniqueConstraint.ObjectID == objectID && uniqueConstraint.UniqueType == constraintType {
|
||||
copy(rm.UniqueConstraints[i:], rm.UniqueConstraints[i+1:])
|
||||
rm.UniqueConstraints[len(rm.UniqueConstraints)-1] = nil
|
||||
rm.UniqueConstraints = rm.UniqueConstraints[:len(rm.UniqueConstraints)-1]
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rm *UniqueConstraintReadModel) listRemoveUniqueConstraint(aggregateID, constraintType string) {
|
||||
for i := len(rm.UniqueConstraints) - 1; i >= 0; i-- {
|
||||
if rm.UniqueConstraints[i].AggregateID == aggregateID && rm.UniqueConstraints[i].UniqueType == constraintType {
|
||||
copy(rm.UniqueConstraints[i:], rm.UniqueConstraints[i+1:])
|
||||
rm.UniqueConstraints[len(rm.UniqueConstraints)-1] = nil
|
||||
rm.UniqueConstraints = rm.UniqueConstraints[:len(rm.UniqueConstraints)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/zitadel/logging"
|
||||
@ -84,6 +85,7 @@ func (db *DB) QueryRowContext(ctx context.Context, scan func(row *sql.Row) error
|
||||
}()
|
||||
|
||||
row := tx.QueryRowContext(ctx, query, args...)
|
||||
logging.OnError(row.Err()).Error("unexpected query error")
|
||||
|
||||
err = scan(row)
|
||||
if err != nil {
|
||||
@ -170,3 +172,9 @@ func (c Config) Password() string {
|
||||
func (c Config) Type() string {
|
||||
return c.connector.Type()
|
||||
}
|
||||
|
||||
func EscapeLikeWildcards(value string) string {
|
||||
value = strings.ReplaceAll(value, "%", "\\%")
|
||||
value = strings.ReplaceAll(value, "_", "\\_")
|
||||
return value
|
||||
}
|
||||
|
@ -13,10 +13,6 @@ const (
|
||||
stateCount
|
||||
)
|
||||
|
||||
func (f MFAState) Valid() bool {
|
||||
return f >= 0 && f < stateCount
|
||||
}
|
||||
|
||||
type MultifactorConfigs struct {
|
||||
OTP OTPConfig
|
||||
}
|
||||
|
@ -9,10 +9,6 @@ const (
|
||||
notificationCount
|
||||
)
|
||||
|
||||
func (f NotificationType) Valid() bool {
|
||||
return f >= 0 && f < notificationCount
|
||||
}
|
||||
|
||||
type NotificationProviderState int32
|
||||
|
||||
const (
|
||||
|
@ -10,10 +10,6 @@ const (
|
||||
policyStateCount
|
||||
)
|
||||
|
||||
func (f PolicyState) Valid() bool {
|
||||
return f >= 0 && f < policyStateCount
|
||||
}
|
||||
|
||||
func (s PolicyState) Exists() bool {
|
||||
return s != PolicyStateUnspecified && s != PolicyStateRemoved
|
||||
}
|
||||
|
@ -83,11 +83,3 @@ func (f LabelPolicy) IsValid() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f LabelPolicyState) Valid() bool {
|
||||
return f >= 0 && f < labelPolicyStateCount
|
||||
}
|
||||
|
||||
func (s LabelPolicyState) Exists() bool {
|
||||
return s != LabelPolicyStateUnspecified && s != LabelPolicyStateRemoved
|
||||
}
|
||||
|
@ -66,12 +66,6 @@ func (p IDPProvider) IsValid() bool {
|
||||
return p.IDPConfigID != ""
|
||||
}
|
||||
|
||||
// DisplayName returns the name or a default
|
||||
// to be used when always a name must be displayed (e.g. login)
|
||||
func (p IDPProvider) DisplayName() string {
|
||||
return IDPName(p.Name, p.IDPType)
|
||||
}
|
||||
|
||||
type PasswordlessType int32
|
||||
|
||||
const (
|
||||
@ -88,7 +82,3 @@ func (f PasswordlessType) Valid() bool {
|
||||
func (p *LoginPolicy) HasSecondFactors() bool {
|
||||
return len(p.SecondFactors) > 0
|
||||
}
|
||||
|
||||
func (p *LoginPolicy) HasMultiFactors() bool {
|
||||
return len(p.MultiFactors) > 0
|
||||
}
|
||||
|
@ -11,11 +11,6 @@ type ProjectGrant struct {
|
||||
RoleKeys []string
|
||||
}
|
||||
|
||||
type ProjectGrantIDs struct {
|
||||
ProjectID string
|
||||
GrantID string
|
||||
}
|
||||
|
||||
type ProjectGrantState int32
|
||||
|
||||
const (
|
||||
|
@ -12,17 +12,6 @@ type ProjectGrantMember struct {
|
||||
Roles []string
|
||||
}
|
||||
|
||||
func NewProjectGrantMember(aggregateID, userID, grantID string, roles ...string) *ProjectGrantMember {
|
||||
return &ProjectGrantMember{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
AggregateID: aggregateID,
|
||||
},
|
||||
GrantID: grantID,
|
||||
UserID: userID,
|
||||
Roles: roles,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *ProjectGrantMember) IsValid() bool {
|
||||
return i.AggregateID != "" && i.GrantID != "" && i.UserID != "" && len(i.Roles) != 0
|
||||
}
|
||||
|
@ -9,10 +9,6 @@ const (
|
||||
identityProviderCount
|
||||
)
|
||||
|
||||
func (f IdentityProviderType) Valid() bool {
|
||||
return f >= 0 && f < identityProviderCount
|
||||
}
|
||||
|
||||
type IdentityProviderState int32
|
||||
|
||||
const (
|
||||
@ -22,7 +18,3 @@ const (
|
||||
|
||||
idpProviderState
|
||||
)
|
||||
|
||||
func (s IdentityProviderState) Valid() bool {
|
||||
return s >= 0 && s < idpProviderState
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
package domain
|
||||
|
||||
type Step int
|
||||
|
||||
const (
|
||||
Step1 Step = iota + 1
|
||||
Step2
|
||||
Step3
|
||||
Step4
|
||||
Step5
|
||||
Step6
|
||||
Step7
|
||||
Step8
|
||||
Step9
|
||||
Step10
|
||||
Step11
|
||||
Step12
|
||||
Step13
|
||||
Step14
|
||||
Step15
|
||||
Step16
|
||||
Step17
|
||||
Step18
|
||||
Step19
|
||||
Step20
|
||||
Step21
|
||||
//StepCount marks the the length of possible steps (StepCount-1 == last possible step)
|
||||
StepCount
|
||||
)
|
@ -1,9 +0,0 @@
|
||||
package domain
|
||||
|
||||
type UniqueConstraintMigration struct {
|
||||
AggregateID string
|
||||
ObjectID string
|
||||
UniqueType string
|
||||
UniqueField string
|
||||
ErrorMessage string
|
||||
}
|
@ -1,10 +1,5 @@
|
||||
package domain
|
||||
|
||||
type User interface {
|
||||
GetUsername() string
|
||||
GetState() UserState
|
||||
}
|
||||
|
||||
type UserState int32
|
||||
|
||||
const (
|
||||
@ -19,10 +14,6 @@ const (
|
||||
userStateCount
|
||||
)
|
||||
|
||||
func (f UserState) Valid() bool {
|
||||
return f >= 0 && f < userStateCount
|
||||
}
|
||||
|
||||
func (s UserState) Exists() bool {
|
||||
return s != UserStateUnspecified && s != UserStateDeleted
|
||||
}
|
||||
@ -40,10 +31,6 @@ const (
|
||||
userTypeCount
|
||||
)
|
||||
|
||||
func (f UserType) Valid() bool {
|
||||
return f >= 0 && f < userTypeCount
|
||||
}
|
||||
|
||||
type UserAuthMethodType int32
|
||||
|
||||
const (
|
||||
@ -58,10 +45,6 @@ const (
|
||||
userAuthMethodTypeCount
|
||||
)
|
||||
|
||||
func (f UserAuthMethodType) Valid() bool {
|
||||
return f >= 0 && f < userAuthMethodTypeCount
|
||||
}
|
||||
|
||||
// HasMFA checks whether the user authenticated with multiple auth factors.
|
||||
// This can either be true if the list contains a [UserAuthMethodType] which by itself is MFA (e.g. [UserAuthMethodTypePasswordless])
|
||||
// or if multiple factors were used (e.g. [UserAuthMethodTypePassword] and [UserAuthMethodTypeU2F])
|
||||
|
@ -1,29 +0,0 @@
|
||||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type UserMembership struct {
|
||||
UserID string
|
||||
MemberType MemberType
|
||||
AggregateID string
|
||||
//ObjectID differs from aggregate id if obejct is sub of an aggregate
|
||||
ObjectID string
|
||||
|
||||
Roles []string
|
||||
DisplayName string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
ResourceOwnerName string
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type MemberType int32
|
||||
|
||||
const (
|
||||
MemberTypeUnspecified MemberType = iota
|
||||
MemberTypeOrganisation
|
||||
MemberTypeProject
|
||||
MemberTypeProjectGrant
|
||||
MemberTypeIam
|
||||
)
|
@ -26,7 +26,7 @@ func latestSequences(ctx context.Context, tx *sql.Tx, commands []eventstore.Comm
|
||||
sequences := commandsToSequences(ctx, commands)
|
||||
|
||||
conditions, args := sequencesToSql(sequences)
|
||||
rows, err := tx.QueryContext(ctx, fmt.Sprintf(latestSequencesStmt, strings.Join(conditions, " OR ")), args...)
|
||||
rows, err := tx.QueryContext(ctx, fmt.Sprintf(latestSequencesStmt, strings.Join(conditions, " UNION ALL ")), args...)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "V3-5jU5z", "Errors.Internal")
|
||||
}
|
||||
@ -92,7 +92,7 @@ func sequencesToSql(sequences []*latestSequence) (conditions []string, args []an
|
||||
conditions = make([]string, len(sequences))
|
||||
|
||||
for i, sequence := range sequences {
|
||||
conditions[i] = fmt.Sprintf("(instance_id = $%d AND aggregate_type = $%d AND aggregate_id = $%d)",
|
||||
conditions[i] = fmt.Sprintf(`(SELECT instance_id, aggregate_type, aggregate_id, "sequence" FROM eventstore.events2 WHERE instance_id = $%d AND aggregate_type = $%d AND aggregate_id = $%d ORDER BY "sequence" DESC LIMIT 1)`,
|
||||
i*argsPerCondition+1,
|
||||
i*argsPerCondition+2,
|
||||
i*argsPerCondition+3,
|
||||
|
@ -247,7 +247,7 @@ func Test_sequencesToSql(t *testing.T) {
|
||||
},
|
||||
},
|
||||
wantConditions: []string{
|
||||
"(instance_id = $1 AND aggregate_type = $2 AND aggregate_id = $3)",
|
||||
`(SELECT instance_id, aggregate_type, aggregate_id, "sequence" FROM eventstore.events2 WHERE instance_id = $1 AND aggregate_type = $2 AND aggregate_id = $3 ORDER BY "sequence" DESC LIMIT 1)`,
|
||||
},
|
||||
wantArgs: []any{
|
||||
"instance",
|
||||
@ -266,8 +266,8 @@ func Test_sequencesToSql(t *testing.T) {
|
||||
},
|
||||
},
|
||||
wantConditions: []string{
|
||||
"(instance_id = $1 AND aggregate_type = $2 AND aggregate_id = $3)",
|
||||
"(instance_id = $4 AND aggregate_type = $5 AND aggregate_id = $6)",
|
||||
`(SELECT instance_id, aggregate_type, aggregate_id, "sequence" FROM eventstore.events2 WHERE instance_id = $1 AND aggregate_type = $2 AND aggregate_id = $3 ORDER BY "sequence" DESC LIMIT 1)`,
|
||||
`(SELECT instance_id, aggregate_type, aggregate_id, "sequence" FROM eventstore.events2 WHERE instance_id = $4 AND aggregate_type = $5 AND aggregate_id = $6 ORDER BY "sequence" DESC LIMIT 1)`,
|
||||
},
|
||||
wantArgs: []any{
|
||||
"instance",
|
||||
|
@ -1,17 +1,5 @@
|
||||
with existing as (
|
||||
SELECT
|
||||
instance_id
|
||||
, aggregate_type
|
||||
, aggregate_id
|
||||
, MAX("sequence") "sequence"
|
||||
FROM
|
||||
eventstore.events2 existing
|
||||
WHERE
|
||||
%s
|
||||
GROUP BY
|
||||
instance_id
|
||||
, aggregate_type
|
||||
, aggregate_id
|
||||
WITH existing AS (
|
||||
%s
|
||||
) SELECT
|
||||
e.instance_id
|
||||
, e.owner
|
||||
@ -23,8 +11,8 @@ FROM
|
||||
JOIN
|
||||
existing
|
||||
ON
|
||||
e.instance_id = existing.instance_id
|
||||
AND e.aggregate_type = existing.aggregate_type
|
||||
AND e.aggregate_id = existing.aggregate_id
|
||||
AND e.sequence = existing.sequence
|
||||
e.instance_id = existing.instance_id
|
||||
AND e.aggregate_type = existing.aggregate_type
|
||||
AND e.aggregate_id = existing.aggregate_id
|
||||
AND e.sequence = existing.sequence
|
||||
FOR UPDATE;
|
@ -1,32 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type Step int
|
||||
|
||||
const (
|
||||
Step1 Step = iota + 1
|
||||
Step2
|
||||
Step3
|
||||
Step4
|
||||
Step5
|
||||
Step6
|
||||
Step7
|
||||
Step8
|
||||
Step9
|
||||
Step10
|
||||
//StepCount marks the the length of possible steps (StepCount-1 == last possible step)
|
||||
StepCount
|
||||
)
|
||||
|
||||
type IAM struct {
|
||||
es_models.ObjectRoot
|
||||
DefaultOrgID string
|
||||
IAMProjectID string
|
||||
SetUpDone domain.Step
|
||||
SetUpStarted domain.Step
|
||||
Members []*IAMMember
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package model
|
||||
|
||||
import es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
|
||||
type IAMMember struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
UserID string
|
||||
Roles []string
|
||||
}
|
||||
|
||||
func NewIAMMember(iamID, userID string) *IAMMember {
|
||||
return &IAMMember{ObjectRoot: es_models.ObjectRoot{AggregateID: iamID}, UserID: userID}
|
||||
}
|
||||
|
||||
func (i *IAMMember) IsValid() bool {
|
||||
return i.AggregateID != "" && i.UserID != "" && len(i.Roles) != 0
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type IDPConfig struct {
|
||||
es_models.ObjectRoot
|
||||
IDPConfigID string
|
||||
Type IdpConfigType
|
||||
Name string
|
||||
StylingType IDPStylingType
|
||||
State IDPConfigState
|
||||
OIDCConfig *OIDCIDPConfig
|
||||
JWTIDPConfig *JWTIDPConfig
|
||||
}
|
||||
|
||||
type OIDCIDPConfig struct {
|
||||
es_models.ObjectRoot
|
||||
IDPConfigID string
|
||||
ClientID string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
ClientSecretString string
|
||||
Issuer string
|
||||
Scopes []string
|
||||
IDPDisplayNameMapping OIDCMappingField
|
||||
UsernameMapping OIDCMappingField
|
||||
}
|
||||
|
||||
type JWTIDPConfig struct {
|
||||
es_models.ObjectRoot
|
||||
IDPConfigID string
|
||||
JWTEndpoint string
|
||||
Issuer string
|
||||
KeysEndpoint string
|
||||
}
|
||||
|
||||
type IdpConfigType int32
|
||||
|
||||
const (
|
||||
IDPConfigTypeOIDC IdpConfigType = iota
|
||||
IDPConfigTypeSAML
|
||||
IDPConfigTypeJWT
|
||||
)
|
||||
|
||||
type IDPConfigState int32
|
||||
|
||||
const (
|
||||
IDPConfigStateActive IDPConfigState = iota
|
||||
IDPConfigStateInactive
|
||||
IDPConfigStateRemoved
|
||||
)
|
||||
|
||||
type IDPStylingType int32
|
||||
|
||||
const (
|
||||
IDPStylingTypeUnspecified IDPStylingType = iota
|
||||
IDPStylingTypeGoogle
|
||||
)
|
||||
|
||||
type OIDCMappingField int32
|
||||
|
||||
const (
|
||||
OIDCMappingFieldUnspecified OIDCMappingField = iota
|
||||
OIDCMappingFieldPreferredLoginName
|
||||
OIDCMappingFieldEmail
|
||||
)
|
||||
|
||||
func NewIDPConfig(iamID, idpID string) *IDPConfig {
|
||||
return &IDPConfig{ObjectRoot: es_models.ObjectRoot{AggregateID: iamID}, IDPConfigID: idpID}
|
||||
}
|
||||
|
||||
func (idp *IDPConfig) IsValid(includeConfig bool) bool {
|
||||
if idp.Name == "" || idp.AggregateID == "" {
|
||||
return false
|
||||
}
|
||||
if !includeConfig {
|
||||
return true
|
||||
}
|
||||
if idp.Type == IDPConfigTypeOIDC && !idp.OIDCConfig.IsValid(true) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (oi *OIDCIDPConfig) IsValid(withSecret bool) bool {
|
||||
if withSecret {
|
||||
return oi.ClientID != "" && oi.Issuer != "" && oi.ClientSecretString != ""
|
||||
}
|
||||
return oi.ClientID != "" && oi.Issuer != ""
|
||||
}
|
||||
|
||||
func (oi *OIDCIDPConfig) CryptSecret(crypt crypto.Crypto) error {
|
||||
cryptedSecret, err := crypto.Crypt([]byte(oi.ClientSecretString), crypt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oi.ClientSecret = cryptedSecret
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st IDPStylingType) GetCSSClass() string {
|
||||
switch st {
|
||||
case IDPStylingTypeGoogle:
|
||||
return "google"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type IDPConfigView struct {
|
||||
AggregateID string
|
||||
IDPConfigID string
|
||||
Name string
|
||||
StylingType IDPStylingType
|
||||
AutoRegister bool
|
||||
State IDPConfigState
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
IDPProviderType IDPProviderType
|
||||
|
||||
IsOIDC bool
|
||||
OIDCClientID string
|
||||
OIDCClientSecret *crypto.CryptoValue
|
||||
OIDCIssuer string
|
||||
OIDCScopes []string
|
||||
OIDCIDPDisplayNameMapping OIDCMappingField
|
||||
OIDCUsernameMapping OIDCMappingField
|
||||
OAuthAuthorizationEndpoint string
|
||||
OAuthTokenEndpoint string
|
||||
JWTEndpoint string
|
||||
JWTIssuer string
|
||||
JWTKeysEndpoint string
|
||||
JWTHeaderName string
|
||||
}
|
||||
|
||||
type IDPConfigSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn IDPConfigSearchKey
|
||||
Asc bool
|
||||
Queries []*IDPConfigSearchQuery
|
||||
}
|
||||
|
||||
type IDPConfigSearchKey int32
|
||||
|
||||
const (
|
||||
IDPConfigSearchKeyUnspecified IDPConfigSearchKey = iota
|
||||
IDPConfigSearchKeyName
|
||||
IDPConfigSearchKeyAggregateID
|
||||
IDPConfigSearchKeyIdpConfigID
|
||||
IDPConfigSearchKeyIdpProviderType
|
||||
IDPConfigSearchKeyInstanceID
|
||||
IDPConfigSearchKeyOwnerRemoved
|
||||
)
|
||||
|
||||
type IDPConfigSearchQuery struct {
|
||||
Key IDPConfigSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type IDPConfigSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*IDPConfigView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (r *IDPConfigSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-Mv9sd", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *IDPConfigSearchRequest) AppendMyOrgQuery(orgID, iamID string) {
|
||||
r.Queries = append(r.Queries, &IDPConfigSearchQuery{Key: IDPConfigSearchKeyAggregateID, Method: domain.SearchMethodIsOneOf, Value: []string{orgID, iamID}})
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type IDPProviderView struct {
|
||||
AggregateID string
|
||||
IDPConfigID string
|
||||
IDPProviderType IDPProviderType
|
||||
Name string
|
||||
StylingType IDPStylingType
|
||||
IDPConfigType IdpConfigType
|
||||
IDPState IDPConfigState
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type IDPProviderSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn IDPProviderSearchKey
|
||||
Asc bool
|
||||
Queries []*IDPProviderSearchQuery
|
||||
}
|
||||
|
||||
type IDPProviderSearchKey int32
|
||||
|
||||
const (
|
||||
IDPProviderSearchKeyUnspecified IDPProviderSearchKey = iota
|
||||
IDPProviderSearchKeyAggregateID
|
||||
IDPProviderSearchKeyIdpConfigID
|
||||
IDPProviderSearchKeyState
|
||||
IDPProviderSearchKeyInstanceID
|
||||
IDPProviderSearchKeyOwnerRemoved
|
||||
)
|
||||
|
||||
type IDPProviderSearchQuery struct {
|
||||
Key IDPProviderSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type IDPProviderSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*IDPProviderView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (r *IDPProviderSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-3n8fs", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *IDPProviderSearchRequest) AppendAggregateIDQuery(aggregateID string) {
|
||||
r.Queries = append(r.Queries, &IDPProviderSearchQuery{Key: IDPProviderSearchKeyAggregateID, Method: domain.SearchMethodEquals, Value: aggregateID})
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type LabelPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
Default bool
|
||||
PrimaryColor string
|
||||
BackgroundColor string
|
||||
FontColor string
|
||||
WarnColor string
|
||||
PrimaryColorDark string
|
||||
BackgroundColorDark string
|
||||
FontColorDark string
|
||||
WarnColorDark string
|
||||
HideLoginNameSuffix bool
|
||||
}
|
||||
|
||||
func (p *LabelPolicy) IsValid() bool {
|
||||
return p.ObjectRoot.AggregateID != ""
|
||||
}
|
@ -1,47 +1,9 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
type LabelPolicyView struct {
|
||||
AggregateID string
|
||||
PrimaryColor string
|
||||
BackgroundColor string
|
||||
WarnColor string
|
||||
FontColor string
|
||||
LogoURL string
|
||||
IconURL string
|
||||
|
||||
PrimaryColorDark string
|
||||
BackgroundColorDark string
|
||||
WarnColorDark string
|
||||
FontColorDark string
|
||||
LogoDarkURL string
|
||||
IconDarkURL string
|
||||
FontURL string
|
||||
|
||||
HideLoginNameSuffix bool
|
||||
ErrorMsgPopup bool
|
||||
DisableWatermark bool
|
||||
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type LabelPolicySearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn LabelPolicySearchKey
|
||||
Asc bool
|
||||
Queries []*LabelPolicySearchQuery
|
||||
}
|
||||
|
||||
type LabelPolicySearchKey int32
|
||||
|
||||
const (
|
||||
@ -57,12 +19,3 @@ type LabelPolicySearchQuery struct {
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type LabelPolicySearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*LabelPolicyView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
@ -1,90 +1,8 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type LoginPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
Default bool
|
||||
AllowUsernamePassword bool
|
||||
AllowRegister bool
|
||||
AllowExternalIdp bool
|
||||
IDPProviders []*IDPProvider
|
||||
ForceMFA bool
|
||||
SecondFactors []domain.SecondFactorType
|
||||
MultiFactors []domain.MultiFactorType
|
||||
PasswordlessType PasswordlessType
|
||||
}
|
||||
|
||||
type IDPProvider struct {
|
||||
models.ObjectRoot
|
||||
Type IDPProviderType
|
||||
IDPConfigID string
|
||||
}
|
||||
|
||||
type PolicyState int32
|
||||
|
||||
const (
|
||||
PolicyStateActive PolicyState = iota
|
||||
PolicyStateRemoved
|
||||
)
|
||||
|
||||
type IDPProviderType int32
|
||||
|
||||
const (
|
||||
IDPProviderTypeSystem IDPProviderType = iota
|
||||
IDPProviderTypeOrg
|
||||
)
|
||||
|
||||
type MultiFactorType int32
|
||||
|
||||
const (
|
||||
MultiFactorTypeUnspecified MultiFactorType = iota
|
||||
MultiFactorTypeU2FWithPIN
|
||||
)
|
||||
|
||||
type PasswordlessType int32
|
||||
|
||||
const (
|
||||
PasswordlessTypeNotAllowed PasswordlessType = iota
|
||||
PasswordlessTypeAllowed
|
||||
)
|
||||
|
||||
func (p *LoginPolicy) IsValid() bool {
|
||||
return p.ObjectRoot.AggregateID != ""
|
||||
}
|
||||
|
||||
func (p *IDPProvider) IsValid() bool {
|
||||
return p.ObjectRoot.AggregateID != "" && p.IDPConfigID != ""
|
||||
}
|
||||
|
||||
func (p *LoginPolicy) GetIdpProvider(id string) (int, *IDPProvider) {
|
||||
for i, m := range p.IDPProviders {
|
||||
if m.IDPConfigID == id {
|
||||
return i, m
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (p *LoginPolicy) GetSecondFactor(mfaType domain.SecondFactorType) (int, domain.SecondFactorType) {
|
||||
for i, m := range p.SecondFactors {
|
||||
if m == mfaType {
|
||||
return i, m
|
||||
}
|
||||
}
|
||||
return -1, 0
|
||||
}
|
||||
|
||||
func (p *LoginPolicy) GetMultiFactor(mfaType domain.MultiFactorType) (int, domain.MultiFactorType) {
|
||||
for i, m := range p.MultiFactors {
|
||||
if m == mfaType {
|
||||
return i, m
|
||||
}
|
||||
}
|
||||
return -1, 0
|
||||
}
|
||||
|
@ -1,129 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type LoginPolicyView struct {
|
||||
AggregateID string
|
||||
AllowUsernamePassword bool
|
||||
AllowRegister bool
|
||||
AllowExternalIDP bool
|
||||
ForceMFA bool
|
||||
HidePasswordReset bool
|
||||
PasswordlessType PasswordlessType
|
||||
SecondFactors []domain.SecondFactorType
|
||||
MultiFactors []domain.MultiFactorType
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type LoginPolicySearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn LoginPolicySearchKey
|
||||
Asc bool
|
||||
Queries []*LoginPolicySearchQuery
|
||||
}
|
||||
|
||||
type LoginPolicySearchKey int32
|
||||
|
||||
const (
|
||||
LoginPolicySearchKeyUnspecified LoginPolicySearchKey = iota
|
||||
LoginPolicySearchKeyAggregateID
|
||||
LoginPolicySearchKeyDefault
|
||||
)
|
||||
|
||||
type LoginPolicySearchQuery struct {
|
||||
Key LoginPolicySearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type LoginPolicySearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*LoginPolicyView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (p *LoginPolicyView) HasSecondFactors() bool {
|
||||
if p.SecondFactors == nil || len(p.SecondFactors) == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *LoginPolicyView) HasMultiFactors() bool {
|
||||
if p.MultiFactors == nil || len(p.MultiFactors) == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *LoginPolicyView) ToLoginPolicyDomain() *domain.LoginPolicy {
|
||||
return &domain.LoginPolicy{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: p.AggregateID,
|
||||
CreationDate: p.CreationDate,
|
||||
ChangeDate: p.ChangeDate,
|
||||
Sequence: p.Sequence,
|
||||
},
|
||||
Default: p.Default,
|
||||
AllowUsernamePassword: p.AllowUsernamePassword,
|
||||
AllowRegister: p.AllowRegister,
|
||||
AllowExternalIDP: p.AllowExternalIDP,
|
||||
ForceMFA: p.ForceMFA,
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
PasswordlessType: passwordLessTypeToDomain(p.PasswordlessType),
|
||||
SecondFactors: secondFactorsToDomain(p.SecondFactors),
|
||||
MultiFactors: multiFactorsToDomain(p.MultiFactors),
|
||||
}
|
||||
}
|
||||
|
||||
func passwordLessTypeToDomain(passwordless PasswordlessType) domain.PasswordlessType {
|
||||
switch passwordless {
|
||||
case PasswordlessTypeNotAllowed:
|
||||
return domain.PasswordlessTypeNotAllowed
|
||||
case PasswordlessTypeAllowed:
|
||||
return domain.PasswordlessTypeAllowed
|
||||
default:
|
||||
return domain.PasswordlessTypeNotAllowed
|
||||
}
|
||||
}
|
||||
|
||||
func secondFactorsToDomain(types []domain.SecondFactorType) []domain.SecondFactorType {
|
||||
secondfactors := make([]domain.SecondFactorType, len(types))
|
||||
for i, secondfactorType := range types {
|
||||
switch secondfactorType {
|
||||
case domain.SecondFactorTypeU2F:
|
||||
secondfactors[i] = domain.SecondFactorTypeU2F
|
||||
case domain.SecondFactorTypeTOTP:
|
||||
secondfactors[i] = domain.SecondFactorTypeTOTP
|
||||
case domain.SecondFactorTypeOTPEmail:
|
||||
secondfactors[i] = domain.SecondFactorTypeOTPEmail
|
||||
case domain.SecondFactorTypeOTPSMS:
|
||||
secondfactors[i] = domain.SecondFactorTypeOTPSMS
|
||||
}
|
||||
}
|
||||
return secondfactors
|
||||
}
|
||||
|
||||
func multiFactorsToDomain(types []domain.MultiFactorType) []domain.MultiFactorType {
|
||||
multifactors := make([]domain.MultiFactorType, len(types))
|
||||
for i, multifactorType := range types {
|
||||
switch multifactorType {
|
||||
case domain.MultiFactorTypeU2FWithPIN:
|
||||
multifactors[i] = domain.MultiFactorTypeU2FWithPIN
|
||||
}
|
||||
}
|
||||
return multifactors
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type MailTemplate struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
Default bool
|
||||
Template []byte
|
||||
}
|
||||
|
||||
func (p *MailTemplate) IsValid() bool {
|
||||
return p.ObjectRoot.AggregateID != ""
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type MailTexts struct {
|
||||
Texts []*MailText
|
||||
Default bool
|
||||
}
|
||||
type MailText struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
Default bool
|
||||
MailTextType string
|
||||
Language string
|
||||
Title string
|
||||
PreHeader string
|
||||
Subject string
|
||||
Greeting string
|
||||
Text string
|
||||
ButtonText string
|
||||
FooterText string
|
||||
}
|
||||
|
||||
func (p *MailText) IsValid() bool {
|
||||
return p.ObjectRoot.AggregateID != ""
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
type MessageTextView struct {
|
||||
AggregateID string
|
||||
MessageTextType string
|
||||
Language language.Tag
|
||||
Title string
|
||||
PreHeader string
|
||||
Subject string
|
||||
Greeting string
|
||||
Text string
|
||||
ButtonText string
|
||||
FooterText string
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type MessageTextSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn MessageTextSearchKey
|
||||
Asc bool
|
||||
Queries []*MessageTextSearchQuery
|
||||
}
|
||||
|
||||
type MessageTextSearchKey int32
|
||||
|
||||
const (
|
||||
MessageTextSearchKeyUnspecified MessageTextSearchKey = iota
|
||||
MessageTextSearchKeyAggregateID
|
||||
MessageTextSearchKeyMessageTextType
|
||||
MessageTextSearchKeyLanguage
|
||||
)
|
||||
|
||||
type MessageTextSearchQuery struct {
|
||||
Key MessageTextSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type MessageTextSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*MessageTextView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
type SecondFactorsSearchRequest struct {
|
||||
Queries []*MFASearchQuery
|
||||
}
|
||||
|
||||
type MultiFactorsSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
Asc bool
|
||||
Queries []*MFASearchQuery
|
||||
}
|
||||
|
||||
type MFASearchQuery struct {
|
||||
Key MFASearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type MFASearchKey int32
|
||||
|
||||
const (
|
||||
MFASearchKeyUnspecified MFASearchKey = iota
|
||||
MFASearchKeyAggregateID
|
||||
)
|
||||
|
||||
type SecondFactorsSearchResponse struct {
|
||||
TotalResult uint64
|
||||
Result []domain.SecondFactorType
|
||||
}
|
||||
|
||||
type MultiFactorsSearchResponse struct {
|
||||
TotalResult uint64
|
||||
Result []domain.MultiFactorType
|
||||
}
|
||||
|
||||
func (r *SecondFactorsSearchRequest) AppendAggregateIDQuery(aggregateID string) {
|
||||
r.Queries = append(r.Queries, &MFASearchQuery{Key: MFASearchKeyAggregateID, Method: domain.SearchMethodEquals, Value: aggregateID})
|
||||
}
|
||||
|
||||
func (r *MultiFactorsSearchRequest) AppendAggregateIDQuery(aggregateID string) {
|
||||
r.Queries = append(r.Queries, &MFASearchQuery{Key: MFASearchKeyAggregateID, Method: domain.SearchMethodEquals, Value: aggregateID})
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type PasswordAgePolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
MaxAgeDays uint64
|
||||
ExpireWarnDays uint64
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
type PasswordAgePolicyView struct {
|
||||
AggregateID string
|
||||
MaxAgeDays uint64
|
||||
ExpireWarnDays uint64
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type PasswordAgePolicySearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn PasswordAgePolicySearchKey
|
||||
Asc bool
|
||||
Queries []*PasswordAgePolicySearchQuery
|
||||
}
|
||||
|
||||
type PasswordAgePolicySearchKey int32
|
||||
|
||||
const (
|
||||
PasswordAgePolicySearchKeyUnspecified PasswordAgePolicySearchKey = iota
|
||||
PasswordAgePolicySearchKeyAggregateID
|
||||
)
|
||||
|
||||
type PasswordAgePolicySearchQuery struct {
|
||||
Key PasswordAgePolicySearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type PasswordAgePolicySearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*PasswordAgePolicyView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
var (
|
||||
hasStringLowerCase = regexp.MustCompile(`[a-z]`).MatchString
|
||||
hasStringUpperCase = regexp.MustCompile(`[A-Z]`).MatchString
|
||||
hasNumber = regexp.MustCompile(`[0-9]`).MatchString
|
||||
hasSymbol = regexp.MustCompile(`[^A-Za-z0-9]`).MatchString
|
||||
)
|
||||
|
||||
type PasswordComplexityPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
MinLength uint64
|
||||
HasLowercase bool
|
||||
HasUppercase bool
|
||||
HasNumber bool
|
||||
HasSymbol bool
|
||||
|
||||
Default bool
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) IsValid() error {
|
||||
if p.MinLength == 0 || p.MinLength > 72 {
|
||||
return zerrors.ThrowInvalidArgument(nil, "MODEL-Lsp0e", "Errors.User.PasswordComplexityPolicy.MinLengthNotAllowed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) Check(password string) error {
|
||||
if p.MinLength != 0 && uint64(len(password)) < p.MinLength {
|
||||
return zerrors.ThrowInvalidArgument(nil, "MODEL-HuJf6", "Errors.User.PasswordComplexityPolicy.MinLength")
|
||||
}
|
||||
|
||||
if p.HasLowercase && !hasStringLowerCase(password) {
|
||||
return zerrors.ThrowInvalidArgument(nil, "MODEL-co3Xw", "Errors.User.PasswordComplexityPolicy.HasLower")
|
||||
}
|
||||
|
||||
if p.HasUppercase && !hasStringUpperCase(password) {
|
||||
return zerrors.ThrowInvalidArgument(nil, "MODEL-VoaRj", "Errors.User.PasswordComplexityPolicy.HasUpper")
|
||||
}
|
||||
|
||||
if p.HasNumber && !hasNumber(password) {
|
||||
return zerrors.ThrowInvalidArgument(nil, "MODEL-ZBv4H", "Errors.User.PasswordComplexityPolicy.HasNumber")
|
||||
}
|
||||
|
||||
if p.HasSymbol && !hasSymbol(password) {
|
||||
return zerrors.ThrowInvalidArgument(nil, "MODEL-ZDLwA", "Errors.User.PasswordComplexityPolicy.HasSymbol")
|
||||
}
|
||||
return nil
|
||||
}
|
@ -2,8 +2,6 @@ package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
type PasswordComplexityPolicyView struct {
|
||||
@ -19,33 +17,3 @@ type PasswordComplexityPolicyView struct {
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type PasswordComplexityPolicySearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn PasswordComplexityPolicySearchKey
|
||||
Asc bool
|
||||
Queries []*PasswordComplexityPolicySearchQuery
|
||||
}
|
||||
|
||||
type PasswordComplexityPolicySearchKey int32
|
||||
|
||||
const (
|
||||
PasswordComplexityPolicySearchKeyUnspecified PasswordComplexityPolicySearchKey = iota
|
||||
PasswordComplexityPolicySearchKeyAggregateID
|
||||
)
|
||||
|
||||
type PasswordComplexityPolicySearchQuery struct {
|
||||
Key PasswordComplexityPolicySearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type PasswordComplexityPolicySearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*PasswordComplexityPolicyView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type LockoutPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
MaxPasswordAttempts uint64
|
||||
ShowLockOutFailures bool
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
type LockoutPolicyView struct {
|
||||
AggregateID string
|
||||
MaxPasswordAttempts uint64
|
||||
ShowLockOutFailures bool
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type LockoutPolicySearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn LockoutPolicySearchKey
|
||||
Asc bool
|
||||
Queries []*LockoutPolicySearchQuery
|
||||
}
|
||||
|
||||
type LockoutPolicySearchKey int32
|
||||
|
||||
const (
|
||||
LockoutPolicySearchKeyUnspecified LockoutPolicySearchKey = iota
|
||||
LockoutPolicySearchKeyAggregateID
|
||||
)
|
||||
|
||||
type LockoutPolicySearchQuery struct {
|
||||
Key LockoutPolicySearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type LockoutPolicySearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*LockoutPolicyView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
type PrivacyPolicyView struct {
|
||||
AggregateID string
|
||||
TOSLink string
|
||||
PrivacyLink string
|
||||
SupportEmail string
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type PrivacyPolicySearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn PrivacyPolicySearchKey
|
||||
Asc bool
|
||||
Queries []*PrivacyPolicySearchQuery
|
||||
}
|
||||
|
||||
type PrivacyPolicySearchKey int32
|
||||
|
||||
const (
|
||||
PrivacyPolicySearchKeyUnspecified PrivacyPolicySearchKey = iota
|
||||
PrivacyPolicySearchKeyAggregateID
|
||||
)
|
||||
|
||||
type PrivacyPolicySearchQuery struct {
|
||||
Key PrivacyPolicySearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type PrivacyPolicySearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*PrivacyPolicyView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type IAMMember struct {
|
||||
es_models.ObjectRoot
|
||||
UserID string `json:"userId,omitempty"`
|
||||
Roles []string `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
func (m *IAMMember) SetData(event *es_models.Event) error {
|
||||
m.ObjectRoot.AppendEvent(event)
|
||||
if err := json.Unmarshal(event.Data, m); err != nil {
|
||||
logging.Log("EVEN-e4dkp").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -22,15 +22,6 @@ func DomainPolicyToModel(policy *DomainPolicy) *iam_model.DomainPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *DomainPolicy) Changes(changed *DomainPolicy) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 1)
|
||||
|
||||
if p.UserLoginMustBeDomain != changed.UserLoginMustBeDomain {
|
||||
changes["userLoginMustBeDomain"] = changed.UserLoginMustBeDomain
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func (p *DomainPolicy) SetData(event eventstore.Event) error {
|
||||
err := event.Unmarshal(p)
|
||||
if err != nil {
|
||||
|
@ -1,49 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOrgIAMPolicyChanges(t *testing.T) {
|
||||
type args struct {
|
||||
existing *DomainPolicy
|
||||
new *DomainPolicy
|
||||
}
|
||||
type res struct {
|
||||
changesLen int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "org iam policy all attributes change",
|
||||
args: args{
|
||||
existing: &DomainPolicy{UserLoginMustBeDomain: true},
|
||||
new: &DomainPolicy{UserLoginMustBeDomain: false},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes",
|
||||
args: args{
|
||||
existing: &DomainPolicy{UserLoginMustBeDomain: true},
|
||||
new: &DomainPolicy{UserLoginMustBeDomain: true},
|
||||
},
|
||||
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))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/iam/repository/view/model"
|
||||
"github.com/zitadel/zitadel/internal/view/repository"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func GetIDPProviderByAggregateIDAndConfigID(db *gorm.DB, table, aggregateID, idpConfigID, instanceID string) (*model.IDPProviderView, error) {
|
||||
policy := new(model.IDPProviderView)
|
||||
aggIDQuery := &model.IDPProviderSearchQuery{Key: iam_model.IDPProviderSearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals}
|
||||
idpConfigIDQuery := &model.IDPProviderSearchQuery{Key: iam_model.IDPProviderSearchKeyIdpConfigID, Value: idpConfigID, Method: domain.SearchMethodEquals}
|
||||
instanceIDQuery := &model.IDPProviderSearchQuery{Key: iam_model.IDPProviderSearchKeyInstanceID, Value: instanceID, Method: domain.SearchMethodEquals}
|
||||
ownerRemovedQuery := &model.IDPProviderSearchQuery{Key: iam_model.IDPProviderSearchKeyOwnerRemoved, Value: false, Method: domain.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggIDQuery, idpConfigIDQuery, instanceIDQuery, ownerRemovedQuery)
|
||||
err := query(db, policy)
|
||||
if zerrors.IsNotFound(err) {
|
||||
return nil, zerrors.ThrowNotFound(nil, "VIEW-Skvi8", "Errors.IAM.LoginPolicy.IDP.NotExisting")
|
||||
}
|
||||
return policy, err
|
||||
}
|
||||
|
||||
func IDPProvidersByIdpConfigID(db *gorm.DB, table, idpConfigID, instanceID string) ([]*model.IDPProviderView, error) {
|
||||
providers := make([]*model.IDPProviderView, 0)
|
||||
queries := []*iam_model.IDPProviderSearchQuery{
|
||||
{
|
||||
Key: iam_model.IDPProviderSearchKeyIdpConfigID,
|
||||
Value: idpConfigID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
{
|
||||
Key: iam_model.IDPProviderSearchKeyInstanceID,
|
||||
Value: instanceID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
{
|
||||
Key: iam_model.IDPProviderSearchKeyOwnerRemoved,
|
||||
Value: false,
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
}
|
||||
query := repository.PrepareSearchQuery(table, model.IDPProviderSearchRequest{Queries: queries})
|
||||
_, err := query(db, &providers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return providers, nil
|
||||
}
|
||||
|
||||
func IDPProvidersByAggregateIDAndState(db *gorm.DB, table string, aggregateID, instanceID string, idpConfigState iam_model.IDPConfigState) ([]*model.IDPProviderView, error) {
|
||||
providers := make([]*model.IDPProviderView, 0)
|
||||
queries := []*iam_model.IDPProviderSearchQuery{
|
||||
{
|
||||
Key: iam_model.IDPProviderSearchKeyAggregateID,
|
||||
Value: aggregateID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
{
|
||||
Key: iam_model.IDPProviderSearchKeyState,
|
||||
Value: int(idpConfigState),
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
{
|
||||
Key: iam_model.IDPProviderSearchKeyInstanceID,
|
||||
Value: instanceID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
{
|
||||
Key: iam_model.IDPProviderSearchKeyOwnerRemoved,
|
||||
Value: false,
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
}
|
||||
query := repository.PrepareSearchQuery(table, model.IDPProviderSearchRequest{Queries: queries})
|
||||
_, err := query(db, &providers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return providers, nil
|
||||
}
|
||||
|
||||
func SearchIDPProviders(db *gorm.DB, table string, req *iam_model.IDPProviderSearchRequest) ([]*model.IDPProviderView, uint64, error) {
|
||||
providers := make([]*model.IDPProviderView, 0)
|
||||
query := repository.PrepareSearchQuery(table, model.IDPProviderSearchRequest{Limit: req.Limit, Offset: req.Offset, Queries: req.Queries})
|
||||
count, err := query(db, &providers)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return providers, count, nil
|
||||
}
|
||||
|
||||
func PutIDPProvider(db *gorm.DB, table string, provider *model.IDPProviderView) error {
|
||||
save := repository.PrepareSave(table)
|
||||
return save(db, provider)
|
||||
}
|
||||
|
||||
func PutIDPProviders(db *gorm.DB, table string, providers ...*model.IDPProviderView) error {
|
||||
save := repository.PrepareBulkSave(table)
|
||||
p := make([]interface{}, len(providers))
|
||||
for i, provider := range providers {
|
||||
p[i] = provider
|
||||
}
|
||||
return save(db, p...)
|
||||
}
|
||||
|
||||
func DeleteIDPProvider(db *gorm.DB, table, aggregateID, idpConfigID, instanceID string) error {
|
||||
delete := repository.PrepareDeleteByKeys(table,
|
||||
repository.Key{Key: model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyAggregateID), Value: aggregateID},
|
||||
repository.Key{Key: model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyIdpConfigID), Value: idpConfigID},
|
||||
repository.Key{Key: model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyInstanceID), Value: instanceID},
|
||||
)
|
||||
return delete(db)
|
||||
}
|
||||
|
||||
func DeleteIDPProvidersByAggregateID(db *gorm.DB, table, aggregateID, instanceID string) error {
|
||||
delete := repository.PrepareDeleteByKeys(table,
|
||||
repository.Key{Key: model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyAggregateID), Value: aggregateID},
|
||||
repository.Key{Key: model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyInstanceID), Value: instanceID},
|
||||
)
|
||||
return delete(db)
|
||||
}
|
||||
|
||||
func DeleteInstanceIDPProviders(db *gorm.DB, table, instanceID string) error {
|
||||
delete := repository.PrepareDeleteByKey(table,
|
||||
model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyInstanceID),
|
||||
instanceID,
|
||||
)
|
||||
return delete(db)
|
||||
}
|
||||
|
||||
func UpdateOrgOwnerRemovedIDPProviders(db *gorm.DB, table, instanceID, aggID string) error {
|
||||
update := repository.PrepareUpdateByKeys(table,
|
||||
model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyOwnerRemoved),
|
||||
true,
|
||||
repository.Key{Key: model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyInstanceID), Value: instanceID},
|
||||
repository.Key{Key: model.IDPProviderSearchKey(iam_model.IDPProviderSearchKeyAggregateID), Value: aggID},
|
||||
)
|
||||
return update(db)
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/iam/repository/view/model"
|
||||
"github.com/zitadel/zitadel/internal/view/repository"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func IDPByID(db *gorm.DB, table, idpID, instanceID string) (*model.IDPConfigView, error) {
|
||||
idp := new(model.IDPConfigView)
|
||||
idpIDQuery := &model.IDPConfigSearchQuery{Key: iam_model.IDPConfigSearchKeyIdpConfigID, Value: idpID, Method: domain.SearchMethodEquals}
|
||||
instanceIDQuery := &model.IDPConfigSearchQuery{Key: iam_model.IDPConfigSearchKeyInstanceID, Value: instanceID, Method: domain.SearchMethodEquals}
|
||||
ownerRemovedQuery := &model.IDPConfigSearchQuery{Key: iam_model.IDPConfigSearchKeyOwnerRemoved, Value: false, Method: domain.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, idpIDQuery, instanceIDQuery, ownerRemovedQuery)
|
||||
err := query(db, idp)
|
||||
if zerrors.IsNotFound(err) {
|
||||
return nil, zerrors.ThrowNotFound(nil, "VIEW-Ahq2s", "Errors.IDP.NotExisting")
|
||||
}
|
||||
return idp, err
|
||||
}
|
||||
|
||||
func GetIDPConfigsByAggregateID(db *gorm.DB, table string, aggregateID, instanceID string) ([]*model.IDPConfigView, error) {
|
||||
idps := make([]*model.IDPConfigView, 0)
|
||||
queries := []*iam_model.IDPConfigSearchQuery{
|
||||
{
|
||||
Key: iam_model.IDPConfigSearchKeyAggregateID,
|
||||
Value: aggregateID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
}, {
|
||||
Key: iam_model.IDPConfigSearchKeyInstanceID,
|
||||
Value: instanceID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
{
|
||||
Key: iam_model.IDPConfigSearchKeyOwnerRemoved,
|
||||
Value: false,
|
||||
Method: domain.SearchMethodEquals,
|
||||
},
|
||||
}
|
||||
query := repository.PrepareSearchQuery(table, model.IDPConfigSearchRequest{Queries: queries})
|
||||
_, err := query(db, &idps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return idps, nil
|
||||
}
|
||||
|
||||
func SearchIDPs(db *gorm.DB, table string, req *iam_model.IDPConfigSearchRequest) ([]*model.IDPConfigView, uint64, error) {
|
||||
idps := make([]*model.IDPConfigView, 0)
|
||||
query := repository.PrepareSearchQuery(table, model.IDPConfigSearchRequest{Limit: req.Limit, Offset: req.Offset, Queries: req.Queries})
|
||||
count, err := query(db, &idps)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return idps, count, nil
|
||||
}
|
||||
|
||||
func PutIDP(db *gorm.DB, table string, idp *model.IDPConfigView) error {
|
||||
save := repository.PrepareSave(table)
|
||||
return save(db, idp)
|
||||
}
|
||||
|
||||
func DeleteIDP(db *gorm.DB, table, idpID, instanceID string) error {
|
||||
delete := repository.PrepareDeleteByKeys(table,
|
||||
repository.Key{model.IDPConfigSearchKey(iam_model.IDPConfigSearchKeyIdpConfigID), idpID},
|
||||
repository.Key{model.IDPConfigSearchKey(iam_model.IDPConfigSearchKeyInstanceID), instanceID},
|
||||
)
|
||||
return delete(db)
|
||||
}
|
||||
|
||||
func UpdateOrgOwnerRemovedIDPs(db *gorm.DB, table, instanceID, aggID string) error {
|
||||
update := repository.PrepareUpdateByKeys(table,
|
||||
model.IDPConfigSearchKey(iam_model.IDPConfigSearchKeyOwnerRemoved),
|
||||
true,
|
||||
repository.Key{Key: model.IDPConfigSearchKey(iam_model.IDPConfigSearchKeyInstanceID), Value: instanceID},
|
||||
repository.Key{Key: model.IDPConfigSearchKey(iam_model.IDPConfigSearchKeyAggregateID), Value: aggID},
|
||||
)
|
||||
return update(db)
|
||||
}
|
||||
|
||||
func DeleteInstanceIDPs(db *gorm.DB, table, instanceID string) error {
|
||||
delete := repository.PrepareDeleteByKey(table, model.IDPConfigSearchKey(iam_model.IDPConfigSearchKeyInstanceID), instanceID)
|
||||
return delete(db)
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
IDPConfigKeyIdpConfigID = "idp_config_id"
|
||||
IDPConfigKeyAggregateID = "aggregate_id"
|
||||
IDPConfigKeyName = "name"
|
||||
IDPConfigKeyProviderType = "idp_provider_type"
|
||||
IDPConfigKeyInstanceID = "instance_id"
|
||||
IDPConfigKeyOwnerRemoved = "owner_removed"
|
||||
)
|
||||
|
||||
type IDPConfigView struct {
|
||||
IDPConfigID string `json:"idpConfigId" gorm:"column:idp_config_id;primary_key"`
|
||||
AggregateID string `json:"-" gorm:"column:aggregate_id"`
|
||||
Name string `json:"name" gorm:"column:name"`
|
||||
StylingType int32 `json:"stylingType" gorm:"column:styling_type"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
IDPState int32 `json:"-" gorm:"column:idp_state"`
|
||||
IDPProviderType int32 `json:"-" gorm:"column:idp_provider_type"`
|
||||
AutoRegister bool `json:"autoRegister" gorm:"column:auto_register"`
|
||||
|
||||
IsOIDC bool `json:"-" gorm:"column:is_oidc"`
|
||||
OIDCClientID string `json:"clientId" gorm:"column:oidc_client_id"`
|
||||
OIDCClientSecret *crypto.CryptoValue `json:"clientSecret" gorm:"column:oidc_client_secret"`
|
||||
OIDCIssuer string `json:"issuer" gorm:"column:oidc_issuer"`
|
||||
OIDCScopes database.TextArray[string] `json:"scopes" gorm:"column:oidc_scopes"`
|
||||
OIDCIDPDisplayNameMapping int32 `json:"idpDisplayNameMapping" gorm:"column:oidc_idp_display_name_mapping"`
|
||||
OIDCUsernameMapping int32 `json:"usernameMapping" gorm:"column:oidc_idp_username_mapping"`
|
||||
OAuthAuthorizationEndpoint string `json:"authorizationEndpoint" gorm:"column:oauth_authorization_endpoint"`
|
||||
OAuthTokenEndpoint string `json:"tokenEndpoint" gorm:"column:oauth_token_endpoint"`
|
||||
JWTEndpoint string `json:"jwtEndpoint" gorm:"jwt_endpoint"`
|
||||
JWTKeysEndpoint string `json:"keysEndpoint" gorm:"jwt_keys_endpoint"`
|
||||
JWTHeaderName string `json:"headerName" gorm:"jwt_header_name"`
|
||||
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"`
|
||||
}
|
||||
|
||||
func IDPConfigViewToModel(idp *IDPConfigView) *model.IDPConfigView {
|
||||
view := &model.IDPConfigView{
|
||||
IDPConfigID: idp.IDPConfigID,
|
||||
AggregateID: idp.AggregateID,
|
||||
State: model.IDPConfigState(idp.IDPState),
|
||||
Name: idp.Name,
|
||||
StylingType: model.IDPStylingType(idp.StylingType),
|
||||
AutoRegister: idp.AutoRegister,
|
||||
Sequence: idp.Sequence,
|
||||
CreationDate: idp.CreationDate,
|
||||
ChangeDate: idp.ChangeDate,
|
||||
IDPProviderType: model.IDPProviderType(idp.IDPProviderType),
|
||||
IsOIDC: idp.IsOIDC,
|
||||
OIDCClientID: idp.OIDCClientID,
|
||||
OIDCClientSecret: idp.OIDCClientSecret,
|
||||
OIDCScopes: idp.OIDCScopes,
|
||||
OIDCIDPDisplayNameMapping: model.OIDCMappingField(idp.OIDCIDPDisplayNameMapping),
|
||||
OIDCUsernameMapping: model.OIDCMappingField(idp.OIDCUsernameMapping),
|
||||
OAuthAuthorizationEndpoint: idp.OAuthAuthorizationEndpoint,
|
||||
OAuthTokenEndpoint: idp.OAuthTokenEndpoint,
|
||||
}
|
||||
if idp.IsOIDC {
|
||||
view.OIDCIssuer = idp.OIDCIssuer
|
||||
return view
|
||||
}
|
||||
view.JWTEndpoint = idp.JWTEndpoint
|
||||
view.JWTIssuer = idp.OIDCIssuer
|
||||
view.JWTKeysEndpoint = idp.JWTKeysEndpoint
|
||||
view.JWTHeaderName = idp.JWTHeaderName
|
||||
return view
|
||||
}
|
||||
|
||||
func (i *IDPConfigView) AppendEvent(providerType model.IDPProviderType, event eventstore.Event) (err error) {
|
||||
i.Sequence = event.Sequence()
|
||||
i.ChangeDate = event.CreatedAt()
|
||||
switch event.Type() {
|
||||
case instance.IDPConfigAddedEventType, org.IDPConfigAddedEventType:
|
||||
i.setRootData(event)
|
||||
i.CreationDate = event.CreatedAt()
|
||||
i.IDPProviderType = int32(providerType)
|
||||
err = i.SetData(event)
|
||||
case instance.IDPOIDCConfigAddedEventType, org.IDPOIDCConfigAddedEventType:
|
||||
i.IsOIDC = true
|
||||
err = i.SetData(event)
|
||||
case instance.IDPOIDCConfigChangedEventType, org.IDPOIDCConfigChangedEventType,
|
||||
instance.IDPConfigChangedEventType, org.IDPConfigChangedEventType,
|
||||
org.IDPJWTConfigAddedEventType, instance.IDPJWTConfigAddedEventType,
|
||||
org.IDPJWTConfigChangedEventType, instance.IDPJWTConfigChangedEventType:
|
||||
err = i.SetData(event)
|
||||
case instance.IDPConfigDeactivatedEventType, org.IDPConfigDeactivatedEventType:
|
||||
i.IDPState = int32(model.IDPConfigStateInactive)
|
||||
case instance.IDPConfigReactivatedEventType, org.IDPConfigReactivatedEventType:
|
||||
i.IDPState = int32(model.IDPConfigStateActive)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *IDPConfigView) setRootData(event eventstore.Event) {
|
||||
r.AggregateID = event.Aggregate().ID
|
||||
r.InstanceID = event.Aggregate().InstanceID
|
||||
}
|
||||
|
||||
func (r *IDPConfigView) SetData(event eventstore.Event) error {
|
||||
err := event.Unmarshal(r)
|
||||
if err != nil {
|
||||
logging.New().WithError(err).Error("could not unmarshal event data")
|
||||
return zerrors.ThrowInternal(err, "MODEL-lub6s", "Could not unmarshal data")
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
type IDPConfigSearchRequest iam_model.IDPConfigSearchRequest
|
||||
type IDPConfigSearchQuery iam_model.IDPConfigSearchQuery
|
||||
type IDPConfigSearchKey iam_model.IDPConfigSearchKey
|
||||
|
||||
func (req IDPConfigSearchRequest) GetLimit() uint64 {
|
||||
return req.Limit
|
||||
}
|
||||
|
||||
func (req IDPConfigSearchRequest) GetOffset() uint64 {
|
||||
return req.Offset
|
||||
}
|
||||
|
||||
func (req IDPConfigSearchRequest) GetSortingColumn() repository.ColumnKey {
|
||||
if req.SortingColumn == iam_model.IDPConfigSearchKeyUnspecified {
|
||||
return nil
|
||||
}
|
||||
return IDPConfigSearchKey(req.SortingColumn)
|
||||
}
|
||||
|
||||
func (req IDPConfigSearchRequest) GetAsc() bool {
|
||||
return req.Asc
|
||||
}
|
||||
|
||||
func (req IDPConfigSearchRequest) GetQueries() []repository.SearchQuery {
|
||||
result := make([]repository.SearchQuery, len(req.Queries))
|
||||
for i, q := range req.Queries {
|
||||
result[i] = IDPConfigSearchQuery{Key: q.Key, Value: q.Value, Method: q.Method}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (req IDPConfigSearchQuery) GetKey() repository.ColumnKey {
|
||||
return IDPConfigSearchKey(req.Key)
|
||||
}
|
||||
|
||||
func (req IDPConfigSearchQuery) GetMethod() domain.SearchMethod {
|
||||
return req.Method
|
||||
}
|
||||
|
||||
func (req IDPConfigSearchQuery) GetValue() interface{} {
|
||||
return req.Value
|
||||
}
|
||||
|
||||
func (key IDPConfigSearchKey) ToColumnName() string {
|
||||
switch iam_model.IDPConfigSearchKey(key) {
|
||||
case iam_model.IDPConfigSearchKeyAggregateID:
|
||||
return IDPConfigKeyAggregateID
|
||||
case iam_model.IDPConfigSearchKeyIdpConfigID:
|
||||
return IDPConfigKeyIdpConfigID
|
||||
case iam_model.IDPConfigSearchKeyName:
|
||||
return IDPConfigKeyName
|
||||
case iam_model.IDPConfigSearchKeyIdpProviderType:
|
||||
return IDPConfigKeyProviderType
|
||||
case iam_model.IDPConfigSearchKeyInstanceID:
|
||||
return IDPConfigKeyInstanceID
|
||||
case iam_model.IDPConfigSearchKeyOwnerRemoved:
|
||||
return IDPConfigKeyOwnerRemoved
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
IDPProviderKeyAggregateID = "aggregate_id"
|
||||
IDPProviderKeyIdpConfigID = "idp_config_id"
|
||||
IDPProviderKeyState = "idp_state"
|
||||
IDPProviderKeyInstanceID = "instance_id"
|
||||
IDPProviderKeyOwnerRemoved = "owner_removed"
|
||||
)
|
||||
|
||||
type IDPProviderView struct {
|
||||
AggregateID string `json:"-" gorm:"column:aggregate_id;primary_key"`
|
||||
IDPConfigID string `json:"idpConfigID" gorm:"column:idp_config_id;primary_key"`
|
||||
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
|
||||
Name string `json:"-" gorm:"column:name"`
|
||||
StylingType int32 `json:"-" gorm:"column:styling_type"`
|
||||
IDPConfigType int32 `json:"-" gorm:"column:idp_config_type"`
|
||||
IDPProviderType int32 `json:"idpProviderType" gorm:"column:idp_provider_type"`
|
||||
IDPState int32 `json:"-" gorm:"column:idp_state"`
|
||||
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"`
|
||||
}
|
||||
|
||||
func IDPProviderViewToModel(provider *IDPProviderView) *model.IDPProviderView {
|
||||
return &model.IDPProviderView{
|
||||
AggregateID: provider.AggregateID,
|
||||
Sequence: provider.Sequence,
|
||||
CreationDate: provider.CreationDate,
|
||||
ChangeDate: provider.ChangeDate,
|
||||
Name: provider.Name,
|
||||
StylingType: model.IDPStylingType(provider.StylingType),
|
||||
IDPConfigID: provider.IDPConfigID,
|
||||
IDPConfigType: model.IdpConfigType(provider.IDPConfigType),
|
||||
IDPProviderType: model.IDPProviderType(provider.IDPProviderType),
|
||||
IDPState: model.IDPConfigState(provider.IDPState),
|
||||
}
|
||||
}
|
||||
|
||||
func IDPProviderViewsToModel(providers []*IDPProviderView) []*model.IDPProviderView {
|
||||
result := make([]*model.IDPProviderView, len(providers))
|
||||
for i, r := range providers {
|
||||
result[i] = IDPProviderViewToModel(r)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (i *IDPProviderView) AppendEvent(event eventstore.Event) (err error) {
|
||||
i.Sequence = event.Sequence()
|
||||
i.ChangeDate = event.CreatedAt()
|
||||
switch event.Type() {
|
||||
case instance.LoginPolicyIDPProviderAddedEventType,
|
||||
org.LoginPolicyIDPProviderAddedEventType:
|
||||
i.setRootData(event)
|
||||
i.CreationDate = event.CreatedAt()
|
||||
err = i.SetData(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *IDPProviderView) setRootData(event eventstore.Event) {
|
||||
r.AggregateID = event.Aggregate().ID
|
||||
r.InstanceID = event.Aggregate().InstanceID
|
||||
}
|
||||
|
||||
func (r *IDPProviderView) SetData(event eventstore.Event) error {
|
||||
if err := event.Unmarshal(r); err != nil {
|
||||
logging.New().WithError(err).Error("could not unmarshal event data")
|
||||
return zerrors.ThrowInternal(err, "MODEL-Hs8uf", "Could not unmarshal data")
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
type IDPProviderSearchRequest iam_model.IDPProviderSearchRequest
|
||||
type IDPProviderSearchQuery iam_model.IDPProviderSearchQuery
|
||||
type IDPProviderSearchKey iam_model.IDPProviderSearchKey
|
||||
|
||||
func (req IDPProviderSearchRequest) GetLimit() uint64 {
|
||||
return req.Limit
|
||||
}
|
||||
|
||||
func (req IDPProviderSearchRequest) GetOffset() uint64 {
|
||||
return req.Offset
|
||||
}
|
||||
|
||||
func (req IDPProviderSearchRequest) GetSortingColumn() repository.ColumnKey {
|
||||
if req.SortingColumn == iam_model.IDPProviderSearchKeyUnspecified {
|
||||
return nil
|
||||
}
|
||||
return IDPProviderSearchKey(req.SortingColumn)
|
||||
}
|
||||
|
||||
func (req IDPProviderSearchRequest) GetAsc() bool {
|
||||
return req.Asc
|
||||
}
|
||||
|
||||
func (req IDPProviderSearchRequest) GetQueries() []repository.SearchQuery {
|
||||
result := make([]repository.SearchQuery, len(req.Queries))
|
||||
for i, q := range req.Queries {
|
||||
result[i] = IDPProviderSearchQuery{Key: q.Key, Value: q.Value, Method: q.Method}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (req IDPProviderSearchQuery) GetKey() repository.ColumnKey {
|
||||
return IDPProviderSearchKey(req.Key)
|
||||
}
|
||||
|
||||
func (req IDPProviderSearchQuery) GetMethod() domain.SearchMethod {
|
||||
return req.Method
|
||||
}
|
||||
|
||||
func (req IDPProviderSearchQuery) GetValue() interface{} {
|
||||
return req.Value
|
||||
}
|
||||
|
||||
func (key IDPProviderSearchKey) ToColumnName() string {
|
||||
switch iam_model.IDPProviderSearchKey(key) {
|
||||
case iam_model.IDPProviderSearchKeyAggregateID:
|
||||
return IDPProviderKeyAggregateID
|
||||
case iam_model.IDPProviderSearchKeyIdpConfigID:
|
||||
return IDPProviderKeyIdpConfigID
|
||||
case iam_model.IDPProviderSearchKeyState:
|
||||
return IDPProviderKeyState
|
||||
case iam_model.IDPProviderSearchKeyInstanceID:
|
||||
return IDPProviderKeyInstanceID
|
||||
case iam_model.IDPProviderSearchKeyOwnerRemoved:
|
||||
return IDPProviderKeyOwnerRemoved
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
@ -6,37 +6,9 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
type LabelPolicySearchRequest iam_model.LabelPolicySearchRequest
|
||||
type LabelPolicySearchQuery iam_model.LabelPolicySearchQuery
|
||||
type LabelPolicySearchKey iam_model.LabelPolicySearchKey
|
||||
|
||||
func (req LabelPolicySearchRequest) GetLimit() uint64 {
|
||||
return req.Limit
|
||||
}
|
||||
|
||||
func (req LabelPolicySearchRequest) GetOffset() uint64 {
|
||||
return req.Offset
|
||||
}
|
||||
|
||||
func (req LabelPolicySearchRequest) GetSortingColumn() repository.ColumnKey {
|
||||
if req.SortingColumn == iam_model.LabelPolicySearchKeyUnspecified {
|
||||
return nil
|
||||
}
|
||||
return LabelPolicySearchKey(req.SortingColumn)
|
||||
}
|
||||
|
||||
func (req LabelPolicySearchRequest) GetAsc() bool {
|
||||
return req.Asc
|
||||
}
|
||||
|
||||
func (req LabelPolicySearchRequest) GetQueries() []repository.SearchQuery {
|
||||
result := make([]repository.SearchQuery, len(req.Queries))
|
||||
for i, q := range req.Queries {
|
||||
result[i] = LabelPolicySearchQuery{Key: q.Key, Value: q.Value, Method: q.Method}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (req LabelPolicySearchQuery) GetKey() repository.ColumnKey {
|
||||
return LabelPolicySearchKey(req.Key)
|
||||
}
|
||||
|
@ -1,38 +1,10 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/iam/model"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
PasswordComplexityKeyAggregateID = "aggregate_id"
|
||||
)
|
||||
|
||||
type PasswordComplexityPolicyView struct {
|
||||
AggregateID string `json:"-" gorm:"column:aggregate_id;primary_key"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
State int32 `json:"-" gorm:"column:complexity_policy_state"`
|
||||
|
||||
MinLength uint64 `json:"minLength" gorm:"column:min_length"`
|
||||
HasLowercase bool `json:"hasLowercase" gorm:"column:has_lowercase"`
|
||||
HasUppercase bool `json:"hasUppercase" gorm:"column:has_uppercase"`
|
||||
HasSymbol bool `json:"hasSymbol" gorm:"column:has_symbol"`
|
||||
HasNumber bool `json:"hasNumber" gorm:"column:has_number"`
|
||||
Default bool `json:"-" gorm:"-"`
|
||||
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
}
|
||||
|
||||
func PasswordComplexityViewToModel(policy *query.PasswordComplexityPolicy) *model.PasswordComplexityPolicyView {
|
||||
return &model.PasswordComplexityPolicyView{
|
||||
AggregateID: policy.ID,
|
||||
@ -47,31 +19,3 @@ func PasswordComplexityViewToModel(policy *query.PasswordComplexityPolicy) *mode
|
||||
Default: policy.IsDefault,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *PasswordComplexityPolicyView) AppendEvent(event eventstore.Event) (err error) {
|
||||
i.Sequence = event.Sequence()
|
||||
i.ChangeDate = event.CreatedAt()
|
||||
switch event.Type() {
|
||||
case instance.PasswordComplexityPolicyAddedEventType,
|
||||
org.PasswordComplexityPolicyAddedEventType:
|
||||
i.setRootData(event)
|
||||
i.CreationDate = event.CreatedAt()
|
||||
err = i.SetData(event)
|
||||
case instance.PasswordComplexityPolicyChangedEventType,
|
||||
org.PasswordComplexityPolicyChangedEventType:
|
||||
err = i.SetData(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PasswordComplexityPolicyView) setRootData(event eventstore.Event) {
|
||||
r.AggregateID = event.Aggregate().ID
|
||||
}
|
||||
|
||||
func (r *PasswordComplexityPolicyView) SetData(event eventstore.Event) error {
|
||||
if err := event.Unmarshal(r); err != nil {
|
||||
logging.Log("EVEN-Dmi9g").WithError(err).Error("could not unmarshal event data")
|
||||
return zerrors.ThrowInternal(err, "MODEL-Hs8uf", "Could not unmarshal data")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"github.com/zitadel/zitadel/pkg/grpc/user"
|
||||
)
|
||||
|
||||
func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, appType app.OIDCAppType, authMethod app.OIDCAuthMethodType) (*management.AddOIDCAppResponse, error) {
|
||||
func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, appType app.OIDCAppType, authMethod app.OIDCAuthMethodType, devMode bool) (*management.AddOIDCAppResponse, error) {
|
||||
return s.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{
|
||||
ProjectId: projectID,
|
||||
Name: fmt.Sprintf("app-%d", time.Now().UnixNano()),
|
||||
@ -34,7 +34,7 @@ func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedire
|
||||
AuthMethodType: authMethod,
|
||||
PostLogoutRedirectUris: []string{logoutRedirectURI},
|
||||
Version: app.OIDCVersion_OIDC_VERSION_1_0,
|
||||
DevMode: false,
|
||||
DevMode: devMode,
|
||||
AccessTokenType: app.OIDCTokenType_OIDC_TOKEN_TYPE_JWT,
|
||||
AccessTokenRoleAssertion: false,
|
||||
IdTokenRoleAssertion: false,
|
||||
@ -45,16 +45,16 @@ func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedire
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Tester) CreateOIDCNativeClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
|
||||
return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_NATIVE, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_NONE)
|
||||
func (s *Tester) CreateOIDCNativeClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, devMode bool) (*management.AddOIDCAppResponse, error) {
|
||||
return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_NATIVE, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_NONE, devMode)
|
||||
}
|
||||
|
||||
func (s *Tester) CreateOIDCWebClientBasic(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
|
||||
return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_BASIC)
|
||||
return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_BASIC, false)
|
||||
}
|
||||
|
||||
func (s *Tester) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (client *management.AddOIDCAppResponse, keyData []byte, err error) {
|
||||
client, err = s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT)
|
||||
client, err = s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -71,7 +71,7 @@ func (s *Tester) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logout
|
||||
}
|
||||
|
||||
func (s *Tester) CreateOIDCInactivateClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
|
||||
client, err := s.CreateOIDCNativeClient(ctx, redirectURI, logoutRedirectURI, projectID)
|
||||
client, err := s.CreateOIDCNativeClient(ctx, redirectURI, logoutRedirectURI, projectID, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -119,7 +119,7 @@ func (s *Tester) CreateProject(ctx context.Context) (*management.AddProjectRespo
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Tester) CreateAPIClient(ctx context.Context, projectID string) (*management.AddAPIAppResponse, error) {
|
||||
func (s *Tester) CreateAPIClientJWT(ctx context.Context, projectID string) (*management.AddAPIAppResponse, error) {
|
||||
return s.Client.Mgmt.AddAPIApp(ctx, &management.AddAPIAppRequest{
|
||||
ProjectId: projectID,
|
||||
Name: fmt.Sprintf("api-%d", time.Now().UnixNano()),
|
||||
@ -127,6 +127,14 @@ func (s *Tester) CreateAPIClient(ctx context.Context, projectID string) (*manage
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Tester) CreateAPIClientBasic(ctx context.Context, projectID string) (*management.AddAPIAppResponse, error) {
|
||||
return s.Client.Mgmt.AddAPIApp(ctx, &management.AddAPIAppRequest{
|
||||
ProjectId: projectID,
|
||||
Name: fmt.Sprintf("api-%d", time.Now().UnixNano()),
|
||||
AuthMethodType: app.APIAuthMethodType_API_AUTH_METHOD_TYPE_BASIC,
|
||||
})
|
||||
}
|
||||
|
||||
const CodeVerifier = "codeVerifier"
|
||||
|
||||
func (s *Tester) CreateOIDCAuthRequest(ctx context.Context, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) {
|
||||
@ -207,7 +215,7 @@ func (c *loginRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
|
||||
return c.RoundTripper.RoundTrip(req)
|
||||
}
|
||||
|
||||
func (s *Tester) CreateResourceServer(ctx context.Context, keyFileData []byte) (rs.ResourceServer, error) {
|
||||
func (s *Tester) CreateResourceServerJWTProfile(ctx context.Context, keyFileData []byte) (rs.ResourceServer, error) {
|
||||
keyFile, err := client.ConfigFromKeyFileData(keyFileData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -215,6 +223,10 @@ func (s *Tester) CreateResourceServer(ctx context.Context, keyFileData []byte) (
|
||||
return rs.NewResourceServerJWTProfile(ctx, s.OIDCIssuer(), keyFile.ClientID, keyFile.KeyID, []byte(keyFile.Key))
|
||||
}
|
||||
|
||||
func (s *Tester) CreateResourceServerClientCredentials(ctx context.Context, clientID, clientSecret string) (rs.ResourceServer, error) {
|
||||
return rs.NewResourceServerClientCredentials(ctx, s.OIDCIssuer(), clientID, clientSecret)
|
||||
}
|
||||
|
||||
func GetRequest(url string, headers map[string]string) (*http.Request, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
http_util "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
@ -22,35 +21,3 @@ const (
|
||||
OrgDomainValidationTypeHTTP
|
||||
OrgDomainValidationTypeDNS
|
||||
)
|
||||
|
||||
func (t OrgDomainValidationType) CheckType() (http_util.CheckType, bool) {
|
||||
switch t {
|
||||
case OrgDomainValidationTypeHTTP:
|
||||
return http_util.CheckTypeHTTP, true
|
||||
case OrgDomainValidationTypeDNS:
|
||||
return http_util.CheckTypeDNS, true
|
||||
default:
|
||||
return -1, false
|
||||
}
|
||||
}
|
||||
|
||||
func (t OrgDomainValidationType) IsDNS() bool {
|
||||
return t == OrgDomainValidationTypeDNS
|
||||
}
|
||||
|
||||
func NewOrgDomain(orgID, domain string) *OrgDomain {
|
||||
return &OrgDomain{ObjectRoot: es_models.ObjectRoot{AggregateID: orgID}, Domain: domain}
|
||||
}
|
||||
|
||||
func (domain *OrgDomain) IsValid() bool {
|
||||
return domain.AggregateID != "" && domain.Domain != ""
|
||||
}
|
||||
|
||||
func (domain *OrgDomain) GenerateVerificationCode(codeGenerator crypto.Generator) (string, error) {
|
||||
validationCodeCrypto, validationCode, err := crypto.NewCode(codeGenerator)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
domain.ValidationCode = validationCodeCrypto
|
||||
return validationCode, nil
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type OrgMember struct {
|
||||
es_models.ObjectRoot `json:"-"`
|
||||
|
||||
UserID string `json:"userId,omitempty"`
|
||||
Roles []string `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
func (m *OrgMember) AppendEvents(events ...*es_models.Event) error {
|
||||
for _, event := range events {
|
||||
err := m.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *OrgMember) AppendEvent(event *es_models.Event) error {
|
||||
m.ObjectRoot.AppendEvent(event)
|
||||
|
||||
return m.SetData(event)
|
||||
}
|
||||
|
||||
func (m *OrgMember) SetData(event *es_models.Event) error {
|
||||
err := json.Unmarshal(event.Data, m)
|
||||
if err != nil {
|
||||
return zerrors.ThrowInternal(err, "EVENT-Hz7Mb", "unable to unmarshal data")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *OrgMember) Changes(updatedMember *OrgMember) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 2)
|
||||
|
||||
if !reflect.DeepEqual(m.Roles, updatedMember.Roles) {
|
||||
changes["roles"] = updatedMember.Roles
|
||||
changes["userId"] = m.UserID
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
@ -97,13 +97,3 @@ func (o *Org) SetData(event eventstore.Event) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Org) Changes(changed *Org) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 2)
|
||||
|
||||
if changed.Name != "" && changed.Name != o.Name {
|
||||
changes["name"] = changed.Name
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
@ -116,47 +116,3 @@ func TestAppendEvent(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChanges(t *testing.T) {
|
||||
type args struct {
|
||||
existingOrg *Org
|
||||
newOrg *Org
|
||||
}
|
||||
type res struct {
|
||||
changesLen int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "org name changes",
|
||||
args: args{
|
||||
existingOrg: &Org{Name: "Name"},
|
||||
newOrg: &Org{Name: "NameChanged"},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes",
|
||||
args: args{
|
||||
existingOrg: &Org{Name: "Name"},
|
||||
newOrg: &Org{Name: "Name"},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
changes := tt.args.existingOrg.Changes(tt.args.newOrg)
|
||||
if len(changes) != tt.res.changesLen {
|
||||
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,8 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/id"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type APIConfig struct {
|
||||
@ -27,35 +20,3 @@ const (
|
||||
APIAuthMethodTypeBasic APIAuthMethodType = iota
|
||||
APIAuthMethodTypePrivateKeyJWT
|
||||
)
|
||||
|
||||
func (c *APIConfig) IsValid() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ClientID random_number@projectname (eg. 495894098234@zitadel)
|
||||
func (c *APIConfig) GenerateNewClientID(idGenerator id.Generator, project *Project) error {
|
||||
rndID, err := idGenerator.Next()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.ClientID = fmt.Sprintf("%v@%v", rndID, strings.ReplaceAll(strings.ToLower(project.Name), " ", "_"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *APIConfig) GenerateClientSecretIfNeeded(generator crypto.Generator) (string, error) {
|
||||
if c.AuthMethodType == APIAuthMethodTypeBasic {
|
||||
return c.GenerateNewClientSecret(generator)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (c *APIConfig) GenerateNewClientSecret(generator crypto.Generator) (string, error) {
|
||||
cryptoValue, stringSecret, err := crypto.NewCode(generator)
|
||||
if err != nil {
|
||||
logging.Log("MODEL-ADvd2").OnError(err).Error("unable to create client secret")
|
||||
return "", zerrors.ThrowInternal(err, "MODEL-dsvr43", "Errors.Project.CouldNotGenerateClientSecret")
|
||||
}
|
||||
c.ClientSecret = cryptoValue
|
||||
return stringSecret, nil
|
||||
}
|
||||
|
@ -32,22 +32,3 @@ const (
|
||||
AppTypeSAML
|
||||
AppTypeAPI
|
||||
)
|
||||
|
||||
func (a *Application) IsValid(includeConfig bool) bool {
|
||||
if a.Name == "" || a.AggregateID == "" {
|
||||
return false
|
||||
}
|
||||
if !includeConfig {
|
||||
return true
|
||||
}
|
||||
if a.Type == AppTypeOIDC && !a.OIDCConfig.IsValid() {
|
||||
return false
|
||||
}
|
||||
if a.Type == AppTypeAPI && !a.APIConfig.IsValid() {
|
||||
return false
|
||||
}
|
||||
if a.Type == AppTypeSAML && !a.SAMLConfig.IsValid() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -1,171 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
func TestApplicationValid(t *testing.T) {
|
||||
type args struct {
|
||||
app *Application
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result bool
|
||||
}{
|
||||
{
|
||||
name: "valid oidc application: responsetype code",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeCode},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeAuthorizationCode},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "invalid oidc application: responsetype code",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeCode},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeImplicit},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeIDToken},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeImplicit},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "invalid oidc application: responsetype id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeIDToken},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeAuthorizationCode},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype token_id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeIDTokenToken},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeImplicit},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "invalid oidc application: responsetype token_id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeIDTokenToken},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeAuthorizationCode},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype code & id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeCode, OIDCResponseTypeIDToken},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeAuthorizationCode, OIDCGrantTypeImplicit},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype code & token_id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeCode, OIDCResponseTypeIDTokenToken},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeAuthorizationCode, OIDCGrantTypeImplicit},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
name: "valid oidc application: responsetype code & id_token & token_id_token",
|
||||
args: args{
|
||||
app: &Application{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
AppID: "AppID",
|
||||
Name: "Name",
|
||||
Type: AppTypeOIDC,
|
||||
OIDCConfig: &OIDCConfig{
|
||||
ResponseTypes: []OIDCResponseType{OIDCResponseTypeCode, OIDCResponseTypeIDToken, OIDCResponseTypeIDTokenToken},
|
||||
GrantTypes: []OIDCGrantType{OIDCGrantTypeAuthorizationCode, OIDCGrantTypeImplicit},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.args.app.IsValid(true)
|
||||
if result != tt.result {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,17 +1,11 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/id"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type OIDCConfig struct {
|
||||
@ -97,49 +91,6 @@ type Token struct {
|
||||
Scopes []string
|
||||
}
|
||||
|
||||
func (c *OIDCConfig) IsValid() bool {
|
||||
grantTypes := c.getRequiredGrantTypes()
|
||||
for _, grantType := range grantTypes {
|
||||
ok := containsOIDCGrantType(c.GrantTypes, grantType)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ClientID random_number@projectname (eg. 495894098234@zitadel)
|
||||
func (c *OIDCConfig) GenerateNewClientID(idGenerator id.Generator, project *Project) error {
|
||||
rndID, err := idGenerator.Next()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.ClientID = fmt.Sprintf("%v@%v", rndID, strings.ReplaceAll(strings.ToLower(project.Name), " ", "_"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *OIDCConfig) GenerateClientSecretIfNeeded(generator crypto.Generator) (string, error) {
|
||||
if c.AuthMethodType == OIDCAuthMethodTypeBasic || c.AuthMethodType == OIDCAuthMethodTypePost {
|
||||
return c.GenerateNewClientSecret(generator)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (c *OIDCConfig) GenerateNewClientSecret(generator crypto.Generator) (string, error) {
|
||||
cryptoValue, stringSecret, err := crypto.NewCode(generator)
|
||||
if err != nil {
|
||||
logging.Log("MODEL-UpnTI").OnError(err).Error("unable to create client secret")
|
||||
return "", zerrors.ThrowInternal(err, "MODEL-gH2Wl", "Errors.Project.CouldNotGenerateClientSecret")
|
||||
}
|
||||
c.ClientSecret = cryptoValue
|
||||
return stringSecret, nil
|
||||
}
|
||||
|
||||
func (c *OIDCConfig) FillCompliance() {
|
||||
c.Compliance = GetOIDCCompliance(c.OIDCVersion, c.ApplicationType, c.GrantTypes, c.ResponseTypes, c.AuthMethodType, c.RedirectUris)
|
||||
}
|
||||
|
||||
func GetOIDCCompliance(version OIDCVersion, appType OIDCApplicationType, grantTypes []OIDCGrantType, responseTypes []OIDCResponseType, authMethod OIDCAuthMethodType, redirectUris []string) *Compliance {
|
||||
switch version {
|
||||
case OIDCVersionV1:
|
||||
@ -155,29 +106,3 @@ func GetOIDCCompliance(version OIDCVersion, appType OIDCApplicationType, grantTy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *OIDCConfig) getRequiredGrantTypes() []OIDCGrantType {
|
||||
grantTypes := make([]OIDCGrantType, 0)
|
||||
implicit := false
|
||||
for _, r := range c.ResponseTypes {
|
||||
switch r {
|
||||
case OIDCResponseTypeCode:
|
||||
grantTypes = append(grantTypes, OIDCGrantTypeAuthorizationCode)
|
||||
case OIDCResponseTypeIDToken, OIDCResponseTypeIDTokenToken:
|
||||
if !implicit {
|
||||
implicit = true
|
||||
grantTypes = append(grantTypes, OIDCGrantTypeImplicit)
|
||||
}
|
||||
}
|
||||
}
|
||||
return grantTypes
|
||||
}
|
||||
|
||||
func containsOIDCGrantType(grantTypes []OIDCGrantType, grantType OIDCGrantType) bool {
|
||||
for _, gt := range grantTypes {
|
||||
if gt == grantType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
type OrgProjectMapping struct {
|
||||
OrgID string
|
||||
ProjectID string
|
||||
}
|
||||
|
||||
type OrgProjectMappingViewSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn OrgProjectMappingViewSearchKey
|
||||
Asc bool
|
||||
Queries []*OrgProjectMappingViewSearchQuery
|
||||
}
|
||||
|
||||
type OrgProjectMappingViewSearchKey int32
|
||||
|
||||
const (
|
||||
OrgProjectMappingSearchKeyUnspecified OrgProjectMappingViewSearchKey = iota
|
||||
OrgProjectMappingSearchKeyProjectID
|
||||
OrgProjectMappingSearchKeyOrgID
|
||||
OrgProjectMappingSearchKeyProjectGrantID
|
||||
OrgProjectMappingSearchKeyInstanceID
|
||||
OrgProjectMappingSearchKeyOwnerRemoved
|
||||
)
|
||||
|
||||
type OrgProjectMappingViewSearchQuery struct {
|
||||
Key OrgProjectMappingViewSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type OrgProjectMappingViewSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*OrgProjectMapping
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (r *OrgProjectMappingViewSearchRequest) GetSearchQuery(key OrgProjectMappingViewSearchKey) (int, *OrgProjectMappingViewSearchQuery) {
|
||||
for i, q := range r.Queries {
|
||||
if q.Key == key {
|
||||
return i, q
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
@ -27,68 +27,3 @@ const (
|
||||
ProjectStateInactive
|
||||
ProjectStateRemoved
|
||||
)
|
||||
|
||||
func (p *Project) IsActive() bool {
|
||||
return p.State == ProjectStateActive
|
||||
}
|
||||
|
||||
func (p *Project) IsValid() bool {
|
||||
return p.Name != ""
|
||||
}
|
||||
|
||||
func (p *Project) ContainsRole(role *ProjectRole) bool {
|
||||
for _, r := range p.Roles {
|
||||
if r.Key == role.Key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Project) GetApp(appID string) (int, *Application) {
|
||||
for i, a := range p.Applications {
|
||||
if a.AppID == appID {
|
||||
return i, a
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (p *Project) GetGrant(grantID string) (int, *ProjectGrant) {
|
||||
for i, g := range p.Grants {
|
||||
if g.GrantID == grantID {
|
||||
return i, g
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (p *Project) ContainsGrantForOrg(orgID string) bool {
|
||||
for _, g := range p.Grants {
|
||||
if g.GrantedOrgID == orgID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Project) ContainsRoles(roleKeys []string) bool {
|
||||
for _, r := range roleKeys {
|
||||
if !p.ContainsRole(&ProjectRole{Key: r}) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *Project) ContainsGrantMember(member *ProjectGrantMember) bool {
|
||||
for _, g := range p.Grants {
|
||||
if g.GrantID != member.GrantID {
|
||||
continue
|
||||
}
|
||||
if _, m := g.GetMember(member.UserID); m != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -14,54 +14,9 @@ type ProjectGrant struct {
|
||||
Members []*ProjectGrantMember
|
||||
}
|
||||
|
||||
type ProjectGrantIDs struct {
|
||||
ProjectID string
|
||||
GrantID string
|
||||
}
|
||||
|
||||
type ProjectGrantState int32
|
||||
|
||||
const (
|
||||
ProjectGrantStateActive ProjectGrantState = iota
|
||||
ProjectGrantStateInactive
|
||||
)
|
||||
|
||||
func NewProjectGrant(projectID, grantID string) *ProjectGrant {
|
||||
return &ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: projectID}, GrantID: grantID, State: ProjectGrantStateActive}
|
||||
}
|
||||
|
||||
func (p *ProjectGrant) IsActive() bool {
|
||||
return p.State == ProjectGrantStateActive
|
||||
}
|
||||
|
||||
func (p *ProjectGrant) IsValid() bool {
|
||||
return p.GrantedOrgID != ""
|
||||
}
|
||||
|
||||
func (p *ProjectGrant) GetMember(userID string) (int, *ProjectGrantMember) {
|
||||
for i, m := range p.Members {
|
||||
if m.UserID == userID {
|
||||
return i, m
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (p *ProjectGrant) GetRemovedRoles(roleKeys []string) []string {
|
||||
removed := make([]string, 0)
|
||||
for _, role := range p.RoleKeys {
|
||||
if !containsKey(roleKeys, role) {
|
||||
removed = append(removed, role)
|
||||
}
|
||||
}
|
||||
return removed
|
||||
}
|
||||
|
||||
func containsKey(roles []string, key string) bool {
|
||||
for _, role := range roles {
|
||||
if role == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -8,11 +8,3 @@ type ProjectGrantMember struct {
|
||||
UserID string
|
||||
Roles []string
|
||||
}
|
||||
|
||||
func NewProjectGrantMember(projectID, grantID, userID string) *ProjectGrantMember {
|
||||
return &ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: projectID}, GrantID: grantID, UserID: userID}
|
||||
}
|
||||
|
||||
func (p *ProjectGrantMember) IsValid() bool {
|
||||
return p.AggregateID != "" && p.UserID != "" && len(p.Roles) != 0
|
||||
}
|
||||
|
@ -1,72 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type ProjectGrantMemberView struct {
|
||||
UserID string
|
||||
GrantID string
|
||||
ProjectID string
|
||||
UserName string
|
||||
Email string
|
||||
FirstName string
|
||||
LastName string
|
||||
DisplayName string
|
||||
PreferredLoginName string
|
||||
AvatarURL string
|
||||
UserResourceOwner string
|
||||
Roles []string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type ProjectGrantMemberSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn ProjectGrantMemberSearchKey
|
||||
Asc bool
|
||||
Queries []*ProjectGrantMemberSearchQuery
|
||||
}
|
||||
|
||||
type ProjectGrantMemberSearchKey int32
|
||||
|
||||
const (
|
||||
ProjectGrantMemberSearchKeyUnspecified ProjectGrantMemberSearchKey = iota
|
||||
ProjectGrantMemberSearchKeyUserName
|
||||
ProjectGrantMemberSearchKeyEmail
|
||||
ProjectGrantMemberSearchKeyFirstName
|
||||
ProjectGrantMemberSearchKeyLastName
|
||||
ProjectGrantMemberSearchKeyGrantID
|
||||
ProjectGrantMemberSearchKeyUserID
|
||||
ProjectGrantMemberSearchKeyProjectID
|
||||
)
|
||||
|
||||
type ProjectGrantMemberSearchQuery struct {
|
||||
Key ProjectGrantMemberSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type ProjectGrantMemberSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*ProjectGrantMemberView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (r *ProjectGrantMemberSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-ZT8df", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
type ProjectGrantView struct {
|
||||
ProjectID string
|
||||
Name string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
State ProjectState
|
||||
ResourceOwner string
|
||||
ResourceOwnerName string
|
||||
OrgID string
|
||||
OrgName string
|
||||
OrgDomain string
|
||||
Sequence uint64
|
||||
GrantID string
|
||||
GrantedRoleKeys []string
|
||||
}
|
||||
|
||||
type ProjectGrantViewSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn ProjectGrantViewSearchKey
|
||||
Asc bool
|
||||
Queries []*ProjectGrantViewSearchQuery
|
||||
}
|
||||
|
||||
type ProjectGrantViewSearchKey int32
|
||||
|
||||
const (
|
||||
GrantedProjectSearchKeyUnspecified ProjectGrantViewSearchKey = iota
|
||||
GrantedProjectSearchKeyName
|
||||
GrantedProjectSearchKeyProjectID
|
||||
GrantedProjectSearchKeyGrantID
|
||||
GrantedProjectSearchKeyOrgID
|
||||
GrantedProjectSearchKeyResourceOwner
|
||||
GrantedProjectSearchKeyRoleKeys
|
||||
)
|
||||
|
||||
type ProjectGrantViewSearchQuery struct {
|
||||
Key ProjectGrantViewSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type ProjectGrantViewSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*ProjectGrantView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (r *ProjectGrantViewSearchRequest) GetSearchQuery(key ProjectGrantViewSearchKey) (int, *ProjectGrantViewSearchQuery) {
|
||||
for i, q := range r.Queries {
|
||||
if q.Key == key {
|
||||
return i, q
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (r *ProjectGrantViewSearchRequest) AppendMyOrgQuery(orgID string) {
|
||||
r.Queries = append(r.Queries, &ProjectGrantViewSearchQuery{Key: GrantedProjectSearchKeyOrgID, Method: domain.SearchMethodEquals, Value: orgID})
|
||||
}
|
||||
|
||||
func (r *ProjectGrantViewSearchRequest) AppendNotMyOrgQuery(orgID string) {
|
||||
r.Queries = append(r.Queries, &ProjectGrantViewSearchQuery{Key: GrantedProjectSearchKeyOrgID, Method: domain.SearchMethodNotEquals, Value: orgID})
|
||||
}
|
||||
|
||||
func (r *ProjectGrantViewSearchRequest) AppendMyResourceOwnerQuery(orgID string) {
|
||||
r.Queries = append(r.Queries, &ProjectGrantViewSearchQuery{Key: GrantedProjectSearchKeyResourceOwner, Method: domain.SearchMethodEquals, Value: orgID})
|
||||
}
|
||||
|
||||
func (r *ProjectGrantViewSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-0fj3s", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
@ -8,11 +8,3 @@ type ProjectMember struct {
|
||||
UserID string
|
||||
Roles []string
|
||||
}
|
||||
|
||||
func NewProjectMember(projectID, userID string) *ProjectMember {
|
||||
return &ProjectMember{ObjectRoot: es_models.ObjectRoot{AggregateID: projectID}, UserID: userID}
|
||||
}
|
||||
|
||||
func (p *ProjectMember) IsValid() bool {
|
||||
return p.AggregateID != "" && p.UserID != "" && len(p.Roles) != 0
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
type ProjectMemberView struct {
|
||||
UserID string
|
||||
ProjectID string
|
||||
UserName string
|
||||
Email string
|
||||
FirstName string
|
||||
LastName string
|
||||
DisplayName string
|
||||
PreferredLoginName string
|
||||
AvatarURL string
|
||||
UserResourceOwner string
|
||||
Roles []string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type ProjectMemberSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn ProjectMemberSearchKey
|
||||
Asc bool
|
||||
Queries []*ProjectMemberSearchQuery
|
||||
}
|
||||
|
||||
type ProjectMemberSearchKey int32
|
||||
|
||||
const (
|
||||
ProjectMemberSearchKeyUnspecified ProjectMemberSearchKey = iota
|
||||
ProjectMemberSearchKeyUserName
|
||||
ProjectMemberSearchKeyEmail
|
||||
ProjectMemberSearchKeyFirstName
|
||||
ProjectMemberSearchKeyLastName
|
||||
ProjectMemberSearchKeyProjectID
|
||||
ProjectMemberSearchKeyUserID
|
||||
)
|
||||
|
||||
type ProjectMemberSearchQuery struct {
|
||||
Key ProjectMemberSearchKey
|
||||
Method domain.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type ProjectMemberSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*ProjectMemberView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (r *ProjectMemberSearchRequest) EnsureLimit(limit uint64) error {
|
||||
if r.Limit > limit {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SEARCH-389Nd", "Errors.Limit.ExceedsDefault")
|
||||
}
|
||||
if r.Limit == 0 {
|
||||
r.Limit = limit
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (r *ProjectMemberSearchRequest) AppendProjectQuery(projectID string) {
|
||||
r.Queries = append(r.Queries, &ProjectMemberSearchQuery{Key: ProjectMemberSearchKeyProjectID, Method: domain.SearchMethodEquals, Value: projectID})
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user