diff --git a/console/src/app/modules/user-grants/user-grants.component.html b/console/src/app/modules/user-grants/user-grants.component.html index efca9f74ec..82de67c8bb 100644 --- a/console/src/app/modules/user-grants/user-grants.component.html +++ b/console/src/app/modules/user-grants/user-grants.component.html @@ -154,10 +154,25 @@ + + {{ 'PROJECT.GRANT.STATE' | translate }} + + + {{ 'USER.DATA.STATE' + grant.state | translate }} + + + + - + diff --git a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html index 45b6821b4b..9e319b7bc6 100644 --- a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html +++ b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html @@ -222,7 +222,7 @@ diff --git a/internal/api/grpc/auth/user_grant.go b/internal/api/grpc/auth/user_grant.go index 242a54b044..9a1842f9a9 100644 --- a/internal/api/grpc/auth/user_grant.go +++ b/internal/api/grpc/auth/user_grant.go @@ -55,5 +55,6 @@ func UserGrantToPb(grant *query.UserGrant) *auth_pb.UserGrant { ProjectGrantId: grant.GrantID, RoleKeys: grant.Roles, UserType: user.TypeToPb(grant.UserType), + State: user.UserGrantStateToPb(grant.State), } } diff --git a/internal/api/grpc/user/user_grant.go b/internal/api/grpc/user/user_grant.go index f4dd099409..eb7f2be205 100644 --- a/internal/api/grpc/user/user_grant.go +++ b/internal/api/grpc/user/user_grant.go @@ -23,7 +23,7 @@ func UserGrantToPb(assetPrefix string, grant *query.UserGrant) *user_pb.UserGran return &user_pb.UserGrant{ Id: grant.ID, UserId: grant.UserID, - State: user_pb.UserGrantState_USER_GRANT_STATE_ACTIVE, + State: UserGrantStateToPb(grant.State), RoleKeys: grant.Roles, ProjectId: grant.ProjectID, OrgId: grant.ResourceOwner, @@ -51,6 +51,21 @@ func UserGrantToPb(assetPrefix string, grant *query.UserGrant) *user_pb.UserGran } } +func UserGrantStateToPb(state domain.UserGrantState) user_pb.UserGrantState { + switch state { + case domain.UserGrantStateActive: + return user_pb.UserGrantState_USER_GRANT_STATE_ACTIVE + case domain.UserGrantStateInactive: + return user_pb.UserGrantState_USER_GRANT_STATE_INACTIVE + case domain.UserGrantStateRemoved, + domain.UserGrantStateUnspecified: + // these states should never occur here and are mainly listed for linting purposes + fallthrough + default: + return user_pb.UserGrantState_USER_GRANT_STATE_UNSPECIFIED + } +} + func UserGrantQueriesToQuery(ctx context.Context, queries []*user_pb.UserGrantQuery) (q []query.SearchQuery, err error) { q = make([]query.SearchQuery, len(queries)) for i, query := range queries { diff --git a/internal/api/oidc/client.go b/internal/api/oidc/client.go index 6bca54c671..1e6fecda5d 100644 --- a/internal/api/oidc/client.go +++ b/internal/api/oidc/client.go @@ -799,19 +799,24 @@ func (o *OPStorage) assertRoles(ctx context.Context, userID, applicationID strin if projectID != "" { roleAudience = append(roleAudience, projectID) } - queries := make([]query.SearchQuery, 0, 2) projectQuery, err := query.NewUserGrantProjectIDsSearchQuery(roleAudience) if err != nil { return nil, nil, err } - queries = append(queries, projectQuery) userIDQuery, err := query.NewUserGrantUserIDSearchQuery(userID) if err != nil { return nil, nil, err } - queries = append(queries, userIDQuery) + activeQuery, err := query.NewUserGrantStateQuery(domain.UserGrantStateActive) + if err != nil { + return nil, nil, err + } grants, err := o.query.UserGrants(ctx, &query.UserGrantsQueries{ - Queries: queries, + Queries: []query.SearchQuery{ + projectQuery, + userIDQuery, + activeQuery, + }, }, true) if err != nil { return nil, nil, err diff --git a/internal/api/saml/storage.go b/internal/api/saml/storage.go index 8791619ba0..8f33e10893 100644 --- a/internal/api/saml/storage.go +++ b/internal/api/saml/storage.go @@ -324,10 +324,15 @@ func (p *Storage) getGrants(ctx context.Context, userID, applicationID string) ( if err != nil { return nil, err } + activeQuery, err := query.NewUserGrantStateQuery(domain.UserGrantStateActive) + if err != nil { + return nil, err + } return p.query.UserGrants(ctx, &query.UserGrantsQueries{ Queries: []query.SearchQuery{ projectQuery, userIDQuery, + activeQuery, }, }, true) } diff --git a/internal/auth/repository/eventsourcing/repository.go b/internal/auth/repository/eventsourcing/repository.go index 9d7b574320..16bee6e7a4 100644 --- a/internal/auth/repository/eventsourcing/repository.go +++ b/internal/auth/repository/eventsourcing/repository.go @@ -11,6 +11,7 @@ import ( sd "github.com/zitadel/zitadel/internal/config/systemdefaults" "github.com/zitadel/zitadel/internal/crypto" "github.com/zitadel/zitadel/internal/database" + "github.com/zitadel/zitadel/internal/domain" eventstore2 "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/id" "github.com/zitadel/zitadel/internal/query" @@ -119,7 +120,11 @@ func (q queryViewWrapper) UserGrantsByProjectAndUserID(ctx context.Context, proj if err != nil { return nil, err } - queries := &query.UserGrantsQueries{Queries: []query.SearchQuery{userGrantUserID, userGrantProjectID}} + activeQuery, err := query.NewUserGrantStateQuery(domain.UserGrantStateActive) + if err != nil { + return nil, err + } + queries := &query.UserGrantsQueries{Queries: []query.SearchQuery{userGrantUserID, userGrantProjectID, activeQuery}} grants, err := q.Queries.UserGrants(ctx, queries, true) if err != nil { return nil, err diff --git a/internal/query/user_grant.go b/internal/query/user_grant.go index c8e1dc05a7..e2bbabdc72 100644 --- a/internal/query/user_grant.go +++ b/internal/query/user_grant.go @@ -143,6 +143,10 @@ func NewUserGrantRoleQuery(value string) (SearchQuery, error) { return NewTextQuery(UserGrantRoles, value, TextListContains) } +func NewUserGrantStateQuery(value domain.UserGrantState) (SearchQuery, error) { + return NewNumberQuery(UserGrantState, value, NumberEquals) +} + func NewUserGrantWithGrantedQuery(owner string) (SearchQuery, error) { orgQuery, err := NewUserGrantResourceOwnerSearchQuery(owner) if err != nil { diff --git a/internal/query/userinfo_by_id.sql b/internal/query/userinfo_by_id.sql index 2c09215a69..93db8ab1b4 100644 --- a/internal/query/userinfo_by_id.sql +++ b/internal/query/userinfo_by_id.sql @@ -38,6 +38,7 @@ user_grants as ( where user_id = $1 and instance_id = $2 and project_id = any($3) + and state = 1 {{ if . -}} and resource_owner = any($4) {{- end }} diff --git a/proto/zitadel/auth.proto b/proto/zitadel/auth.proto index 0eae6d24e5..ed58d70569 100644 --- a/proto/zitadel/auth.proto +++ b/proto/zitadel/auth.proto @@ -1565,6 +1565,11 @@ message UserGrant { description: "type of the user (human / machine)" } ]; + zitadel.user.v1.UserGrantState state = 13 [ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "current state of the user grant"; + } + ]; } message ListMyProjectOrgsRequest {