diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml index cc350f8e76..418465409d 100644 --- a/.github/workflows/issues.yml +++ b/.github/workflows/issues.yml @@ -4,17 +4,39 @@ on: issues: types: - opened + pull_request_target: + types: + - opened jobs: add-to-project: - name: Add issue to project + name: Add issue and community pr to project runs-on: ubuntu-latest steps: - - uses: actions/add-to-project@v0.3.0 + - name: add issue + uses: actions/add-to-project@v0.5.0 + if: ${{ github.event_name == 'issues' }} with: # You can target a repository in a different organization # to the issue project-url: https://github.com/orgs/zitadel/projects/2 github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} - labeled: OKR - label-operator: NOT + - uses: tspascoal/get-user-teams-membership@v3 + id: checkUserMember + with: + username: ${{ github.actor }} + GITHUB_TOKEN: ${{ secrets.ADD_TO_PROJECT_PAT }} + - name: add pr + uses: actions/add-to-project@v0.5.0 + if: ${{ github.event_name == 'pull_request_target' && !contains(steps.checkUserMember.outputs.teams, 'engineers') && github.actor != 'app/dependabot'}} + with: + # You can target a repository in a different organization + # to the issue + project-url: https://github.com/orgs/zitadel/projects/2 + github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} + - uses: actions-ecosystem/action-add-labels@v1.1.0 + if: ${{ github.event_name == 'pull_request_target' && !contains(steps.checkUserMember.outputs.teams, 'staff') && github.actor != 'app/dependabot'}} + with: + github_token: ${{ secrets.ADD_TO_PROJECT_PAT }} + labels: | + os-contribution diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 60651d424d..239546acf9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -219,7 +219,7 @@ docker compose --file ./e2e/config/host.docker.internal/docker-compose.yaml down In order to run the integrations tests for the gRPC API, PostgreSQL and CockroachDB must be started and initialized: ```bash -export INTEGRATION_DB_FLAVOR="cockroach" ZITADEL_MASTERKEY="MasterkeyNeedsToHave32Characters" +export INTEGRATION_DB_FLAVOR="postgres" ZITADEL_MASTERKEY="MasterkeyNeedsToHave32Characters" docker compose -f internal/integration/config/docker-compose.yaml up --pull always --wait ${INTEGRATION_DB_FLAVOR} make core_integration_test docker compose -f internal/integration/config/docker-compose.yaml down diff --git a/README.md b/README.md index f13f41af1d..ea4a57d5c2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ GitHub Workflow Status (with event) - + Dynamic YAML Badge @@ -39,26 +39,16 @@ Look no further — ZITADEL is the identity infrastructure, simplified for you. We provide you with a wide range of out-of-the-box features to accelerate your project, including: -:white_check_mark: Multi-tenancy with branding customization - -:white_check_mark: Secure login - -:white_check_mark: Self-service - -:white_check_mark: OpenID Connect - -:white_check_mark: OAuth2.x - -:white_check_mark: SAML2 - -:white_check_mark: LDAP - -:white_check_mark: Passkeys / FIDO2 - -:white_check_mark: OTP - -:white_check_mark: U2F, and an unlimited audit trail is there for you, ready to use. - +:white_check_mark: Multi-tenancy with team management +:white_check_mark: Secure login +:white_check_mark: Self-service +:white_check_mark: OpenID Connect +:white_check_mark: OAuth2.x +:white_check_mark: SAML2 +:white_check_mark: LDAP +:white_check_mark: Passkeys / FIDO2 +:white_check_mark: OTP +and an unlimited audit trail is there for you, ready to use. With ZITADEL, you are assured of a robust and customizable turnkey solution for all your authentication and authorization needs. @@ -86,18 +76,18 @@ See all guides [here](https://zitadel.com/docs/self-hosting/deploy/overview) ### Setup ZITADEL Cloud (SaaS) -If you want to experience a hands-free ZITADEL, you should use [ZITADEL Cloud](https://zitadel.cloud). +If you want to experience a hands-free ZITADEL, you should use [ZITADEL Cloud](https://zitadel.com). ZITADEL Cloud comes with a free tier, providing you with all the same features as the open-source version. Learn more about the [pay-as-you-go pricing](https://zitadel.com/pricing). ### Example applications -Clone one of our [example applications](https://zitadel.com/docs/examples/introduction#clone-a-sample-project) or deploy them directly to Vercel. +Clone one of our [example applications](https://zitadel.com/docs/sdk-examples/introduction) or deploy them directly to Vercel. ### SDKs -Use our [SDKs](https://zitadel.com/docs/examples/sdks) for your favorite language and framework. +Use our [SDKs](https://zitadel.com/docs/sdk-examples/introduction) for your favorite language and framework. ## Why choose ZITADEL @@ -115,6 +105,7 @@ Yet it offers everything you need for a customer identity ([CIAM](https://zitade ## Features Authentication + - Single Sign On (SSO) - Passkeys support (FIDO2 / WebAuthN) - Username / Password @@ -128,12 +119,15 @@ Authentication - [Machine-to-machine](https://zitadel.com/docs/guides/integrate/serviceusers) with JWT profile, Personal Access Tokens (PAT), and Client Credentials Multi-Tenancy + - [Identity Brokering](https://zitadel.com/docs/guides/integrate/identity-brokering) with templates for popular identity providers +- [Customizable onboaring](https://zitadel.com/docs/guides/solution-scenarios/onboarding) for B2B and their users - [Delegate role management to third-parties](https://zitadel.com/docs/guides/manage/console/projects) - [Domain discovery](https://zitadel.com/docs/guides/solution-scenarios/domain-discovery) Integration -- [GRPC and REST APIs](https://zitadel.com/docs/apis/introduction) + +- [GRPC and REST APIs](https://zitadel.com/docs/apis/introduction) for every functionality and resource - [Actions](https://zitadel.com/docs/apis/actions/introduction) to call any API, send webhooks, adjust workflows, or customize tokens - [Role Based Access Control (RBAC)](https://zitadel.com/docs/guides/integrate/retrieve-user-roles) @@ -145,6 +139,7 @@ Self-Service Deployment - [Postgres](https://zitadel.com/docs/self-hosting/manage/database#postgres) (version >= 14) or [CockroachDB](https://zitadel.com/docs/self-hosting/manage/database#cockroach) (version latest stable) - [Zero Downtime Updates](https://zitadel.com/docs/concepts/architecture/solution#zero-downtime-updates) +- [High scalability](https://zitadel.com/docs/self-hosting/manage/production) Track upcoming features on our [roadmap](https://zitadel.com/roadmap). diff --git a/cmd/defaults.yaml b/cmd/defaults.yaml index 432566205f..c28de428cf 100644 --- a/cmd/defaults.yaml +++ b/cmd/defaults.yaml @@ -337,6 +337,7 @@ OIDC: TriggerIntrospectionProjections: false # Allows fallback to the Legacy Introspection implementation LegacyIntrospection: false + PublicKeyCacheMaxAge: 24h # ZITADEL_OIDC_PUBLICKEYCACHEMAXAGE SAML: ProviderConfig: diff --git a/console/src/app/app-routing.module.ts b/console/src/app/app-routing.module.ts index 624c32a819..4900c8e424 100644 --- a/console/src/app/app-routing.module.ts +++ b/console/src/app/app-routing.module.ts @@ -125,39 +125,6 @@ const routes: Routes = [ }, ], }, - { - path: 'failed-events', - loadChildren: () => import('./pages/failed-events/failed-events.module'), - canActivate: [AuthGuard, RoleGuard], - data: { - roles: ['iam.read'], - }, - }, - { - path: 'views', - loadChildren: () => import('./pages/iam-views/iam-views.module'), - canActivate: [AuthGuard, RoleGuard], - data: { - roles: ['iam.read'], - }, - }, - { - path: 'events', - loadChildren: () => import('./pages/events/events.module'), - canActivate: [AuthGuard, RoleGuard], - data: { - roles: ['iam.read'], - }, - }, - { - path: 'settings', - loadChildren: () => import('./pages/instance-settings/instance-settings.module'), - canActivate: [AuthGuard, RoleGuard], - data: { - roles: ['iam.read', 'iam.policy.read'], - requiresAll: true, - }, - }, { path: 'org-settings', loadChildren: () => import('./pages/org-settings/org-settings.module'), diff --git a/console/src/app/modules/events/events.component.html b/console/src/app/modules/events/events.component.html new file mode 100644 index 0000000000..71696cdc17 --- /dev/null +++ b/console/src/app/modules/events/events.component.html @@ -0,0 +1,129 @@ +

{{ 'IAM.EVENTS.TITLE' | translate }}

+

{{ 'IAM.EVENTS.DESCRIPTION' | translate }}

+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'IAM.EVENTS.EDITOR' | translate }} + +
+ + {{ editor.displayName }} + {{ editor.service }} +
+
+
{{ 'IAM.EVENTS.AGGREGATE' | translate }} + +
+ {{ event.aggregate.id }}{{ + event.aggregate.type.localized.localizedMessage + }} +
+
+
{{ 'IAM.EVENTS.RESOURCEOWNER' | translate }} + + {{ event.aggregate.resourceOwner }} + + + {{ 'IAM.EVENTS.SEQUENCE' | translate }} + + + {{ event.sequence }} + + + {{ 'IAM.EVENTS.CREATIONDATE' | translate }} + + + {{ event?.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm:ss' }} + + {{ 'IAM.EVENTS.TYPE' | translate }} + + {{ event.type.localized.localizedMessage }} + + {{ 'IAM.EVENTS.PAYLOAD' | translate }} + + {{ payload | json }} +
+ +
+
+
+ + +
diff --git a/console/src/app/pages/events/events.component.scss b/console/src/app/modules/events/events.component.scss similarity index 97% rename from console/src/app/pages/events/events.component.scss rename to console/src/app/modules/events/events.component.scss index 5a9ac466c7..1b53b96fcd 100644 --- a/console/src/app/pages/events/events.component.scss +++ b/console/src/app/modules/events/events.component.scss @@ -61,10 +61,6 @@ } } -.events-title { - margin: 2rem 0 0 0; -} - .events-desc { font-size: 14px; } diff --git a/console/src/app/pages/events/events.component.spec.ts b/console/src/app/modules/events/events.component.spec.ts similarity index 100% rename from console/src/app/pages/events/events.component.spec.ts rename to console/src/app/modules/events/events.component.spec.ts diff --git a/console/src/app/pages/events/events.component.ts b/console/src/app/modules/events/events.component.ts similarity index 100% rename from console/src/app/pages/events/events.component.ts rename to console/src/app/modules/events/events.component.ts diff --git a/console/src/app/pages/events/events.module.ts b/console/src/app/modules/events/events.module.ts similarity index 95% rename from console/src/app/pages/events/events.module.ts rename to console/src/app/modules/events/events.module.ts index b1ba802f39..fcd3444b31 100644 --- a/console/src/app/pages/events/events.module.ts +++ b/console/src/app/modules/events/events.module.ts @@ -26,13 +26,11 @@ import { DisplayJsonDialogModule } from 'src/app/modules/display-json-dialog/dis import { FilterEventsModule } from 'src/app/modules/filter-events/filter-events.module'; import { ToObjectPipeModule } from 'src/app/pipes/to-object/to-object.module'; import { ToPayloadPipeModule } from 'src/app/pipes/to-payload/to-payload.module'; -import { EventsRoutingModule } from './events-routing.module'; import { EventsComponent } from './events.component'; @NgModule({ declarations: [EventsComponent], imports: [ - EventsRoutingModule, CommonModule, TableActionsModule, MatIconModule, @@ -60,6 +58,6 @@ import { EventsComponent } from './events.component'; MatSortModule, OverlayModule, ], - exports: [], + exports: [EventsComponent], }) -export default class IamViewsModule {} +export default class EventsModule {} diff --git a/console/src/app/modules/failed-events/failed-events.component.html b/console/src/app/modules/failed-events/failed-events.component.html new file mode 100644 index 0000000000..1c31a66bcc --- /dev/null +++ b/console/src/app/modules/failed-events/failed-events.component.html @@ -0,0 +1,68 @@ +

{{ 'IAM.FAILEDEVENTS.TITLE' | translate }}

+

{{ 'IAM.FAILEDEVENTS.DESCRIPTION' | translate }}

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'IAM.FAILEDEVENTS.VIEWNAME' | translate }}{{ event.viewName }}{{ 'IAM.FAILEDEVENTS.DATABASE' | translate }}{{ event.database }}{{ 'IAM.FAILEDEVENTS.FAILEDSEQUENCE' | translate }} + {{ event?.failedSequence }} + {{ 'IAM.FAILEDEVENTS.FAILURECOUNT' | translate }} + {{ event?.failureCount }} + {{ 'IAM.FAILEDEVENTS.LASTFAILED' | translate }} + {{ event?.lastFailed | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} + {{ 'IAM.FAILEDEVENTS.ERRORMESSAGE' | translate }} + {{ event?.errorMessage }} + + + + +
+ + +
+
diff --git a/console/src/app/pages/failed-events/failed-events.component.scss b/console/src/app/modules/failed-events/failed-events.component.scss similarity index 70% rename from console/src/app/pages/failed-events/failed-events.component.scss rename to console/src/app/modules/failed-events/failed-events.component.scss index 6695953216..a873809044 100644 --- a/console/src/app/pages/failed-events/failed-events.component.scss +++ b/console/src/app/modules/failed-events/failed-events.component.scss @@ -1,7 +1,3 @@ -.failed-events-title { - margin: 2rem 0 0 0; -} - .failed-events-desc { font-size: 14px; } diff --git a/console/src/app/pages/failed-events/failed-events.component.spec.ts b/console/src/app/modules/failed-events/failed-events.component.spec.ts similarity index 100% rename from console/src/app/pages/failed-events/failed-events.component.spec.ts rename to console/src/app/modules/failed-events/failed-events.component.spec.ts diff --git a/console/src/app/pages/failed-events/failed-events.component.ts b/console/src/app/modules/failed-events/failed-events.component.ts similarity index 100% rename from console/src/app/pages/failed-events/failed-events.component.ts rename to console/src/app/modules/failed-events/failed-events.component.ts diff --git a/console/src/app/pages/failed-events/failed-events.module.ts b/console/src/app/modules/failed-events/failed-events.module.ts similarity index 94% rename from console/src/app/pages/failed-events/failed-events.module.ts rename to console/src/app/modules/failed-events/failed-events.module.ts index 39954791e6..d891127fd4 100644 --- a/console/src/app/pages/failed-events/failed-events.module.ts +++ b/console/src/app/modules/failed-events/failed-events.module.ts @@ -18,13 +18,11 @@ import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.mod import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module'; import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module'; -import { FailedEventsRoutingModule } from './failed-events-routing.module'; import { FailedEventsComponent } from './failed-events.component'; @NgModule({ declarations: [FailedEventsComponent], imports: [ - FailedEventsRoutingModule, CommonModule, TableActionsModule, MatIconModule, @@ -44,5 +42,6 @@ import { FailedEventsComponent } from './failed-events.component'; MatTableModule, MatSortModule, ], + exports: [FailedEventsComponent], }) export default class FailedEventsModule {} diff --git a/console/src/app/modules/filter-org/filter-org.component.html b/console/src/app/modules/filter-org/filter-org.component.html index 510ca0fcd1..4e8535fe76 100644 --- a/console/src/app/modules/filter-org/filter-org.component.html +++ b/console/src/app/modules/filter-org/filter-org.component.html @@ -46,4 +46,27 @@ + +
+ {{ 'FILTER.PRIMARYDOMAIN' | translate }} + +
+ + + + {{ 'FILTER.METHODS.' + method | translate }} + + + + + + + +
+
diff --git a/console/src/app/modules/filter-org/filter-org.component.ts b/console/src/app/modules/filter-org/filter-org.component.ts index 3a43b74195..8e100971d0 100644 --- a/console/src/app/modules/filter-org/filter-org.component.ts +++ b/console/src/app/modules/filter-org/filter-org.component.ts @@ -3,7 +3,7 @@ import { MatCheckboxChange } from '@angular/material/checkbox'; import { ActivatedRoute, Router } from '@angular/router'; import { take } from 'rxjs'; import { TextQueryMethod } from 'src/app/proto/generated/zitadel/object_pb'; -import { OrgNameQuery, OrgQuery, OrgState, OrgStateQuery } from 'src/app/proto/generated/zitadel/org_pb'; +import { OrgDomainQuery, OrgNameQuery, OrgQuery, OrgState, OrgStateQuery } from 'src/app/proto/generated/zitadel/org_pb'; import { UserNameQuery } from 'src/app/proto/generated/zitadel/user_pb'; import { FilterComponent } from '../filter/filter.component'; @@ -11,6 +11,7 @@ import { FilterComponent } from '../filter/filter.component'; enum SubQuery { NAME, STATE, + DOMAIN, } @Component({ @@ -52,6 +53,13 @@ export class FilterOrgComponent extends FilterComponent implements OnInit { orgStateQuery.setState(filter.stateQuery.state); orgQuery.setStateQuery(orgStateQuery); return orgQuery; + } else if (filter.domainQuery) { + const orgQuery = new OrgQuery(); + const orgDomainQuery = new OrgDomainQuery(); + orgDomainQuery.setDomain(filter.domainQuery.domain); + orgDomainQuery.setMethod(filter.domainQuery.method); + orgQuery.setDomainQuery(orgDomainQuery); + return orgQuery; } else { return undefined; } @@ -83,6 +91,14 @@ export class FilterOrgComponent extends FilterComponent implements OnInit { osq.setStateQuery(sq); this.searchQueries.push(osq); break; + case SubQuery.DOMAIN: + const dq = new OrgDomainQuery(); + dq.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); + dq.setDomain(''); + const odq = new OrgQuery(); + odq.setDomainQuery(dq); + this.searchQueries.push(odq); + break; } } else { switch (subquery) { @@ -98,6 +114,12 @@ export class FilterOrgComponent extends FilterComponent implements OnInit { this.searchQueries.splice(index_sn, 1); } break; + case SubQuery.DOMAIN: + const index_pdn = this.searchQueries.findIndex((q) => (q as OrgQuery).toObject().domainQuery !== undefined); + if (index_pdn > -1) { + this.searchQueries.splice(index_pdn, 1); + } + break; } } } @@ -113,6 +135,10 @@ export class FilterOrgComponent extends FilterComponent implements OnInit { (query as OrgStateQuery).setState(value); this.filterChanged.emit(this.searchQueries ? this.searchQueries : []); break; + case SubQuery.DOMAIN: + (query as OrgDomainQuery).setDomain(value); + this.filterChanged.emit(this.searchQueries ? this.searchQueries : []); + break; } } @@ -132,6 +158,13 @@ export class FilterOrgComponent extends FilterComponent implements OnInit { } else { return undefined; } + case SubQuery.DOMAIN: + const pdn = this.searchQueries.find((q) => (q as OrgQuery).toObject().domainQuery !== undefined); + if (pdn) { + return (pdn as OrgQuery).getDomainQuery(); + } else { + return undefined; + } } } diff --git a/console/src/app/modules/iam-views/iam-views.component.html b/console/src/app/modules/iam-views/iam-views.component.html new file mode 100644 index 0000000000..f6db886743 --- /dev/null +++ b/console/src/app/modules/iam-views/iam-views.component.html @@ -0,0 +1,40 @@ +

{{ 'IAM.VIEWS.TITLE' | translate }}

+

{{ 'IAM.VIEWS.DESCRIPTION' | translate }}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'IAM.VIEWS.VIEWNAME' | translate }}{{ view.viewName }}{{ 'IAM.VIEWS.DATABASE' | translate }}{{ view.database }}{{ 'IAM.VIEWS.SEQUENCE' | translate }}{{ view.processedSequence }}{{ 'IAM.VIEWS.EVENTTIMESTAMP' | translate }} + {{ view?.eventTimestamp | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} + {{ 'IAM.VIEWS.LASTSPOOL' | translate }} + {{ view?.lastSuccessfulSpoolerRun | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} +
+ + +
diff --git a/console/src/app/modules/iam-views/iam-views.component.scss b/console/src/app/modules/iam-views/iam-views.component.scss new file mode 100644 index 0000000000..b1d6596f1d --- /dev/null +++ b/console/src/app/modules/iam-views/iam-views.component.scss @@ -0,0 +1,3 @@ +.views-desc { + font-size: 14px; +} diff --git a/console/src/app/pages/iam-views/iam-views.component.spec.ts b/console/src/app/modules/iam-views/iam-views.component.spec.ts similarity index 100% rename from console/src/app/pages/iam-views/iam-views.component.spec.ts rename to console/src/app/modules/iam-views/iam-views.component.spec.ts diff --git a/console/src/app/pages/iam-views/iam-views.component.ts b/console/src/app/modules/iam-views/iam-views.component.ts similarity index 100% rename from console/src/app/pages/iam-views/iam-views.component.ts rename to console/src/app/modules/iam-views/iam-views.component.ts diff --git a/console/src/app/pages/iam-views/iam-views.module.ts b/console/src/app/modules/iam-views/iam-views.module.ts similarity index 94% rename from console/src/app/pages/iam-views/iam-views.module.ts rename to console/src/app/modules/iam-views/iam-views.module.ts index 13c30ba8df..5958ca0dce 100644 --- a/console/src/app/pages/iam-views/iam-views.module.ts +++ b/console/src/app/modules/iam-views/iam-views.module.ts @@ -18,13 +18,11 @@ import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.mod import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module'; import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module'; -import { IamViewsRoutingModule } from './iam-views-routing.module'; import { IamViewsComponent } from './iam-views.component'; @NgModule({ declarations: [IamViewsComponent], imports: [ - IamViewsRoutingModule, CommonModule, TableActionsModule, MatIconModule, @@ -44,6 +42,6 @@ import { IamViewsComponent } from './iam-views.component'; MatTableModule, MatSortModule, ], - exports: [], + exports: [IamViewsComponent], }) export default class IamViewsModule {} diff --git a/console/src/app/modules/nav/nav.component.html b/console/src/app/modules/nav/nav.component.html index 3317e41f91..d601a76be9 100644 --- a/console/src/app/modules/nav/nav.component.html +++ b/console/src/app/modules/nav/nav.component.html @@ -7,99 +7,12 @@ *ngIf=" breadc[breadc.length - 1] && !breadc[breadc.length - 1].hideNav && - breadc[breadc.length - 1].type !== BreadcrumbType.AUTHUSER + breadc[breadc.length - 1].type !== BreadcrumbType.AUTHUSER && + breadc[breadc.length - 1].type !== BreadcrumbType.INSTANCE " [ngSwitch]="breadc[0].type" >