mirror of
https://github.com/zitadel/zitadel.git
synced 2025-04-16 07:01:29 +00:00
Merge branch 'main' into next
# Conflicts: # go.mod # internal/query/user_auth_method_test.go
This commit is contained in:
commit
9a9753a911
@ -7,7 +7,17 @@ services:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
network_mode: service:db
|
||||
command: sleep infinity
|
||||
|
||||
environment:
|
||||
- 'ZITADEL_DATABASE_POSTGRES_HOST=db'
|
||||
- 'ZITADEL_DATABASE_POSTGRES_PORT=5432'
|
||||
- 'ZITADEL_DATABASE_POSTGRES_DATABASE=zitadel'
|
||||
- 'ZITADEL_DATABASE_POSTGRES_USER_USERNAME=zitadel'
|
||||
- 'ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=zitadel'
|
||||
- 'ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE=disable'
|
||||
- 'ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME=postgres'
|
||||
- 'ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD=postgres'
|
||||
- 'ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable'
|
||||
- 'ZITADEL_EXTERNALSECURE=false'
|
||||
db:
|
||||
image: postgres:latest
|
||||
restart: unless-stopped
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -85,4 +85,5 @@ go.work.sum
|
||||
|
||||
load-test/node_modules
|
||||
load-test/yarn-error.log
|
||||
load-test/dist
|
||||
load-test/dist
|
||||
.vercel
|
||||
|
@ -141,6 +141,20 @@ Replace "policeman" with "police officer," "manpower" with "workforce," and "bus
|
||||
Ableist language includes words or phrases such as crazy, insane, blind to or blind eye to, cripple, dumb, and others.
|
||||
Choose alternative words depending on the context.
|
||||
|
||||
### Developing ZITADEL with Dev Containers
|
||||
|
||||
Follow the instructions provided by your code editor/IDE to initiate the development container. This typically involves opening the "Command Palette" or similar functionality and searching for commands related to "Dev Containers" or "Remote Containers". The quick start guide for VS Code can found [here](https://code.visualstudio.com/docs/devcontainers/containers#_quick-start-open-an-existing-folder-in-a-container)
|
||||
|
||||
When you are connected to the container run the following commands to start ZITADEL.
|
||||
|
||||
```bash
|
||||
make compile && ./zitadel start-from-init --masterkey MasterkeyNeedsToHave32Characters --tlsMode disabled
|
||||
```
|
||||
|
||||
ZITADEL serves traffic as soon as you can see the following log line:
|
||||
|
||||
`INFO[0001] server is listening on [::]:8080`
|
||||
|
||||
### Backend/login
|
||||
|
||||
By executing the commands from this section, you run everything you need to develop the ZITADEL backend locally.
|
||||
@ -398,6 +412,13 @@ ZITADEL loads translations from four files:
|
||||
|
||||
You may edit the texts in these files or create a new file for additional language support. Make sure you set the locale (ISO 639-1 code) as the name of the new language file.
|
||||
Please make sure that the languages within the files remain in their own language, e.g. German must always be `Deutsch.
|
||||
If you have added support for a new language, please also ensure that it is added in the list of languages in all the other language files.
|
||||
|
||||
You also have to add some changes to the following files:
|
||||
- [Register Local File](./console/src/app/app.module.ts)
|
||||
- [Add Supported Language](./console/src/app/utils/language.ts)
|
||||
- [Customized Text Docs](./docs/docs/guides/manage/customize/texts.md)
|
||||
- [Add language option](./internal/api/ui/login/static/templates/external_not_found_option.html)
|
||||
|
||||
## Want to start ZITADEL?
|
||||
|
||||
|
@ -3,6 +3,40 @@
|
||||
Dear community!
|
||||
We're excited to announce bi-weekly office hours.
|
||||
|
||||
## #2 New Resources and Settings APIs
|
||||
|
||||
**Shape the future of ZITADEL Let's redesign the API for a better developer experience!**
|
||||
|
||||
Dear community,
|
||||
|
||||
Following the great success of our first office hours, we're back for round two! This time, we're focusing on YOU and how we can build the best possible ZITADEL API together.
|
||||
|
||||
We've been working on some ideas for the API, and we're excited to share them with you during the session. But more importantly, we want to hear YOUR thoughts! What does your dream ZITADEL API look like? What improvements would make your development life easier?
|
||||
|
||||
Join the open discussion next Wednesday in the office hours voice channel on Discord. We're ready for your honest feedback and fresh perspectives that help us shape the future of ZITADEL!
|
||||
|
||||
**What to expect**:
|
||||
|
||||
* **Our Suggestions**: @eliobischof will walk you through the improvement suggestions.
|
||||
* **Open Discussion**: Get your questions answered directly by the ZITADEL team, describe your pain points and drop your thoughts in an
|
||||
open discussion.
|
||||
|
||||
**Details**:
|
||||
|
||||
* **Target Audience**: Developers and IT Ops personnel using ZITADEL
|
||||
* **Topic**: API Redesign and Q&A
|
||||
* **When**: Wednesday 12th of June 12 pm PST / 3 pm EST / 9 pm CEST
|
||||
* **Duration**: about 1 hour
|
||||
* **Platform**: ZITADEL Discord Server (Join us here: https://zitadel.com/office-hours?event=1248016231936692274 )
|
||||
|
||||
**In the meantime**:
|
||||
|
||||
KUDOS, if you already [have a look at our proposal](https://zitadel.com/docs/apis/v3) before the start of the event. Share any inputs in the chat of the [office hours channel](https://zitadel.com/office-hours) on our Discord server.
|
||||
|
||||
We look forward to seeing you there!
|
||||
|
||||
P.S. Spread the word! Share this announcement with your fellow ZITADEL users who might be interested 📢
|
||||
|
||||
## #1 Dive Deep into Actions v2
|
||||
|
||||
The first office hour is dedicated to exploring the [new Actions v2 feature](https://zitadel.com/docs/concepts/features/actions_v2).
|
||||
@ -26,4 +60,4 @@ Feel free to share any questions you already have about Actions v2 in the chat o
|
||||
|
||||
We look forward to seeing you there!
|
||||
|
||||
P.S. Spread the word! Share this announcement with your fellow ZITADEL users who might be interested.
|
||||
P.S. Spread the word! Share this announcement with your fellow ZITADEL users who might be interested.
|
||||
|
@ -120,6 +120,10 @@ Database:
|
||||
Cert: "" # ZITADEL_DATABASE_COCKROACH_USER_SSL_CERT
|
||||
Key: "" # ZITADEL_DATABASE_COCKROACH_USER_SSL_KEY
|
||||
Admin:
|
||||
# By default, ExistingDatabase is not specified in the connection string
|
||||
# If the connection resolves to a database that is not existing in your system, configure an existing one here
|
||||
# It is used in zitadel init to connect to cockroach and create a dedicated database for ZITADEL.
|
||||
ExistingDatabase: # ZITADEL_DATABASE_COCKROACH_ADMIN_EXISTINGDATABASE
|
||||
Username: root # ZITADEL_DATABASE_COCKROACH_ADMIN_USERNAME
|
||||
Password: "" # ZITADEL_DATABASE_COCKROACH_ADMIN_PASSWORD
|
||||
SSL:
|
||||
@ -147,6 +151,10 @@ Database:
|
||||
Cert: # ZITADEL_DATABASE_POSTGRES_USER_SSL_CERT
|
||||
Key: # ZITADEL_DATABASE_POSTGRES_USER_SSL_KEY
|
||||
Admin:
|
||||
# The default ExistingDatabase is postgres
|
||||
# If your db system doesn't have a database named postgres, configure an existing database here
|
||||
# It is used in zitadel init to connect to postgres and create a dedicated database for ZITADEL.
|
||||
ExistingDatabase: # ZITADEL_DATABASE_POSTGRES_ADMIN_EXISTINGDATABASE
|
||||
Username: # ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME
|
||||
Password: # ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD
|
||||
SSL:
|
||||
|
@ -23,5 +23,5 @@ func (mig *User11AddLowerFieldsToVerifiedEmail) Execute(ctx context.Context, _ e
|
||||
}
|
||||
|
||||
func (mig *User11AddLowerFieldsToVerifiedEmail) String() string {
|
||||
return "25_user12_add_lower_fields_to_verified_email"
|
||||
return "25_user13_add_lower_fields_to_verified_email"
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
ALTER TABLE IF EXISTS projections.users12_notifications ADD COLUMN IF NOT EXISTS verified_email_lower TEXT GENERATED ALWAYS AS (lower(verified_email)) STORED;
|
||||
CREATE INDEX IF NOT EXISTS users12_notifications_email_search ON projections.users12_notifications (instance_id, verified_email_lower);
|
||||
ALTER TABLE IF EXISTS projections.users13_notifications ADD COLUMN IF NOT EXISTS verified_email_lower TEXT GENERATED ALWAYS AS (lower(verified_email)) STORED;
|
||||
CREATE INDEX IF NOT EXISTS users13_notifications_email_search ON projections.users13_notifications (instance_id, verified_email_lower);
|
||||
|
@ -14,6 +14,7 @@ import localePt from '@angular/common/locales/pt';
|
||||
import localeZh from '@angular/common/locales/zh';
|
||||
import localeRu from '@angular/common/locales/ru';
|
||||
import localeNl from '@angular/common/locales/nl';
|
||||
import localeSv from '@angular/common/locales/sv';
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
@ -99,6 +100,8 @@ registerLocaleData(localeCs);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/cs.json'));
|
||||
registerLocaleData(localeNl);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/nl.json'));
|
||||
registerLocaleData(localeSv);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/sv.json'));
|
||||
|
||||
export class WebpackTranslateLoader implements TranslateLoader {
|
||||
getTranslation(lang: string): Observable<any> {
|
||||
|
@ -248,12 +248,16 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 600px) {
|
||||
display: inline;
|
||||
display: inline;
|
||||
|
||||
i {
|
||||
margin-right: -0.5rem;
|
||||
margin-left: 0.25rem;
|
||||
i {
|
||||
margin-right: -0.5rem;
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 375px) {
|
||||
.iam-label {
|
||||
font-size: x-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +188,7 @@ export function mapRequestValues(map: Partial<Map>, req: Req): Req {
|
||||
|
||||
const r17 = new PasswordChangeScreenText();
|
||||
r17.setDescription(map.passwordChangeText?.description ?? '');
|
||||
r17.setExpiredDescription(map.passwordChangeText?.expiredDescription ?? '');
|
||||
r17.setNextButtonText(map.passwordChangeText?.nextButtonText ?? '');
|
||||
r17.setTitle(map.passwordChangeText?.title ?? '');
|
||||
r17.setNewPasswordLabel(map.passwordChangeText?.newPasswordLabel ?? '');
|
||||
|
@ -406,7 +406,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.tempUsername', value: '{{.TempUsername}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
@ -421,7 +421,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
@ -436,7 +436,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
@ -451,7 +451,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
@ -466,7 +466,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
@ -482,7 +482,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
@ -498,7 +498,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
@ -512,7 +512,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
@ -526,7 +526,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.username', value: '{{.UserName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.LastName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.nickName', value: '{{.NickName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.displayName', value: '{{.DisplayName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastEmail', value: '{{.LastEmail}}' },
|
||||
|
@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { PasswordAgePolicyComponent } from './password-age-policy.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: PasswordAgePolicyComponent,
|
||||
data: {
|
||||
animation: 'DetailPage',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class PasswordAgePolicyRoutingModule {}
|
@ -0,0 +1,50 @@
|
||||
<h2>{{ 'POLICY.PWD_AGE.TITLE' | translate }}</h2>
|
||||
<p class="cnsl-secondary-text">{{ 'POLICY.PWD_AGE.DESCRIPTION' | translate }}</p>
|
||||
|
||||
<div *ngIf="loading" class="spinner-wr">
|
||||
<mat-spinner diameter="30" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<ng-template cnslHasRole [hasRole]="['policy.delete']">
|
||||
<button
|
||||
*ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
|
||||
matTooltip="{{ 'POLICY.RESET' | translate }}"
|
||||
color="warn"
|
||||
(click)="resetPolicy()"
|
||||
mat-stroked-button
|
||||
>
|
||||
{{ 'POLICY.RESET' | translate }}
|
||||
</button>
|
||||
</ng-template>
|
||||
|
||||
<form class="lifetime-form" (ngSubmit)="savePolicy()" [formGroup]="passwordAgeForm" autocomplete="off">
|
||||
<cnsl-card *ngIf="passwordAgeData">
|
||||
<div class="age-content">
|
||||
<div class="row">
|
||||
<cnsl-form-field class="pwd-age-form-field" required="true">
|
||||
<cnsl-label>{{ 'POLICY.DATA.MAXAGEDAYS' | translate }}</cnsl-label>
|
||||
<input cnslInput type="number" name="maxAgeDays" formControlName="maxAgeDays" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<cnsl-form-field class="pwd-age-form-field" required="true">
|
||||
<cnsl-label>{{ 'POLICY.DATA.EXPIREWARNDAYS' | translate }}</cnsl-label>
|
||||
<input cnslInput type="number" name="expireWarnDays" formControlName="expireWarnDays" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</form>
|
||||
|
||||
<div class="btn-container">
|
||||
<button
|
||||
(click)="savePolicy()"
|
||||
[disabled]="(['policy.write'] | hasRole | async) === false"
|
||||
color="primary"
|
||||
type="submit"
|
||||
mat-raised-button
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
@ -0,0 +1,37 @@
|
||||
.default {
|
||||
display: block;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.policy-applied-to {
|
||||
margin: -1rem 0 0 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.age-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.3rem 0;
|
||||
|
||||
.pwd-age-form-field {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
|
||||
button {
|
||||
display: block;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { PasswordAgePolicyComponent } from './password-age-policy.component';
|
||||
|
||||
describe('PasswordLockoutPolicyComponent', () => {
|
||||
let component: PasswordAgePolicyComponent;
|
||||
let fixture: ComponentFixture<PasswordAgePolicyComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [PasswordAgePolicyComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PasswordAgePolicyComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,178 @@
|
||||
import { Component, Injector, Input, OnInit, Type } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { GetPasswordAgePolicyResponse as AdminGetPasswordAgePolicyResponse } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { GetPasswordAgePolicyResponse as MgmtGetPasswordAgePolicyResponse } from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { PasswordAgePolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { requiredValidator } from '../../form-field/validators/validators';
|
||||
import { Observable } from 'rxjs';
|
||||
import { GrpcAuthService } from '../../../services/grpc-auth.service';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-password-age-policy',
|
||||
templateUrl: './password-age-policy.component.html',
|
||||
styleUrls: ['./password-age-policy.component.scss'],
|
||||
})
|
||||
export class PasswordAgePolicyComponent implements OnInit {
|
||||
@Input() public service!: ManagementService | AdminService;
|
||||
@Input() public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
|
||||
public passwordAgeForm!: UntypedFormGroup;
|
||||
public passwordAgeData?: PasswordAgePolicy.AsObject;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public InfoSectionType: any = InfoSectionType;
|
||||
public loading: boolean = false;
|
||||
|
||||
public canWrite$: Observable<boolean> = this.authService.isAllowed([
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: this.serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: '',
|
||||
]);
|
||||
|
||||
constructor(
|
||||
private authService: GrpcAuthService,
|
||||
private toast: ToastService,
|
||||
private injector: Injector,
|
||||
private dialog: MatDialog,
|
||||
private fb: UntypedFormBuilder,
|
||||
) {
|
||||
this.passwordAgeForm = this.fb.group({
|
||||
maxAgeDays: ['', []],
|
||||
expireWarnDays: ['', []],
|
||||
});
|
||||
|
||||
this.canWrite$.pipe(take(1)).subscribe((canWrite) => {
|
||||
if (canWrite) {
|
||||
this.passwordAgeForm.enable();
|
||||
} else {
|
||||
this.passwordAgeForm.disable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
break;
|
||||
}
|
||||
this.fetchData();
|
||||
}
|
||||
|
||||
private fetchData(): void {
|
||||
this.loading = true;
|
||||
|
||||
this.getData().then((resp) => {
|
||||
if (resp.policy) {
|
||||
this.passwordAgeData = resp.policy;
|
||||
this.passwordAgeForm.patchValue(this.passwordAgeData);
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getData(): Promise<AdminGetPasswordAgePolicyResponse.AsObject | MgmtGetPasswordAgePolicyResponse.AsObject> {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
return (this.service as ManagementService).getPasswordAgePolicy();
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
return (this.service as AdminService).getPasswordAgePolicy();
|
||||
}
|
||||
}
|
||||
|
||||
public resetPolicy(): void {
|
||||
if (this.service instanceof ManagementService) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.RESET',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'SETTING.DIALOG.RESET.DEFAULTTITLE',
|
||||
descriptionKey: 'SETTING.DIALOG.RESET.DEFAULTDESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
(this.service as ManagementService)
|
||||
.resetPasswordAgePolicyToDefault()
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true);
|
||||
this.fetchData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
let promise: Promise<any>;
|
||||
if (this.passwordAgeData) {
|
||||
if (this.service instanceof AdminService) {
|
||||
promise = this.service
|
||||
.updatePasswordAgePolicy(this.maxAgeDays?.value ?? 0, this.expireWarnDays?.value ?? 0)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else {
|
||||
if ((this.passwordAgeData as PasswordAgePolicy.AsObject).isDefault) {
|
||||
promise = (this.service as ManagementService)
|
||||
.addCustomPasswordAgePolicy(this.maxAgeDays?.value ?? 0, this.expireWarnDays?.value ?? 0)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else {
|
||||
promise = (this.service as ManagementService)
|
||||
.updateCustomPasswordAgePolicy(this.maxAgeDays?.value ?? 0, this.expireWarnDays?.value ?? 0)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get isDefault(): boolean {
|
||||
if (this.passwordAgeData && this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
return (this.passwordAgeData as PasswordAgePolicy.AsObject).isDefault;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public get maxAgeDays(): AbstractControl | null {
|
||||
return this.passwordAgeForm.get('maxAgeDays');
|
||||
}
|
||||
|
||||
public get expireWarnDays(): AbstractControl | null {
|
||||
return this.passwordAgeForm.get('expireWarnDays');
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { CardModule } from '../../card/card.module';
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { WarnDialogModule } from '../../warn-dialog/warn-dialog.module';
|
||||
import { PasswordAgePolicyRoutingModule } from './password-age-policy-routing.module';
|
||||
import { PasswordAgePolicyComponent } from './password-age-policy.component';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
|
||||
@NgModule({
|
||||
declarations: [PasswordAgePolicyComponent],
|
||||
imports: [
|
||||
PasswordAgePolicyRoutingModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
MatSlideToggleModule,
|
||||
HasRolePipeModule,
|
||||
MatDialogModule,
|
||||
WarnDialogModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
MatTooltipModule,
|
||||
CardModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
InfoSectionModule,
|
||||
ReactiveFormsModule,
|
||||
MatProgressSpinnerModule,
|
||||
],
|
||||
exports: [PasswordAgePolicyComponent],
|
||||
})
|
||||
export class PasswordAgePolicyModule {}
|
@ -8,7 +8,7 @@ import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { CardModule } from '../../card/card.module';
|
||||
import { FormFieldModule } from '../../form-field/form-field.module';
|
||||
import { InputModule } from '../../input/input.module';
|
||||
@ -31,6 +31,7 @@ import { SecretGeneratorComponent } from './secret-generator.component';
|
||||
MatProgressSpinnerModule,
|
||||
MatSelectModule,
|
||||
TranslateModule,
|
||||
MatDialogModule,
|
||||
],
|
||||
exports: [SecretGeneratorComponent, DialogAddSecretGeneratorComponent],
|
||||
})
|
||||
|
@ -18,6 +18,9 @@
|
||||
<ng-container *ngIf="currentSetting === 'complexity'">
|
||||
<cnsl-password-complexity-policy [serviceType]="serviceType"></cnsl-password-complexity-policy>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="currentSetting === 'age'">
|
||||
<cnsl-password-age-policy [serviceType]="serviceType"></cnsl-password-age-policy>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="currentSetting === 'lockout'">
|
||||
<cnsl-password-lockout-policy [serviceType]="serviceType"></cnsl-password-lockout-policy>
|
||||
</ng-container>
|
||||
|
@ -16,6 +16,7 @@ import { NotificationPolicyModule } from '../policies/notification-policy/notifi
|
||||
import { NotificationSMSProviderModule } from '../policies/notification-sms-provider/notification-sms-provider.module';
|
||||
import { OIDCConfigurationModule } from '../policies/oidc-configuration/oidc-configuration.module';
|
||||
import { PasswordComplexityPolicyModule } from '../policies/password-complexity-policy/password-complexity-policy.module';
|
||||
import { PasswordAgePolicyModule } from '../policies/password-age-policy/password-age-policy.module';
|
||||
import { PasswordLockoutPolicyModule } from '../policies/password-lockout-policy/password-lockout-policy.module';
|
||||
import { PrivacyPolicyModule } from '../policies/privacy-policy/privacy-policy.module';
|
||||
import { PrivateLabelingPolicyModule } from '../policies/private-labeling-policy/private-labeling-policy.module';
|
||||
@ -40,6 +41,7 @@ import OrgListModule from 'src/app/pages/org-list/org-list.module';
|
||||
LoginPolicyModule,
|
||||
CardModule,
|
||||
PasswordComplexityPolicyModule,
|
||||
PasswordAgePolicyModule,
|
||||
PasswordLockoutPolicyModule,
|
||||
PrivateLabelingPolicyModule,
|
||||
LanguageSettingsModule,
|
||||
|
@ -117,6 +117,16 @@ export const LOCKOUT: SidenavSetting = {
|
||||
},
|
||||
};
|
||||
|
||||
export const AGE: SidenavSetting = {
|
||||
id: 'age',
|
||||
i18nKey: 'SETTINGS.LIST.AGE',
|
||||
groupI18nKey: 'SETTINGS.GROUPS.LOGIN',
|
||||
requiredRoles: {
|
||||
[PolicyComponentServiceType.MGMT]: ['policy.read'],
|
||||
[PolicyComponentServiceType.ADMIN]: ['iam.policy.read'],
|
||||
},
|
||||
};
|
||||
|
||||
export const COMPLEXITY: SidenavSetting = {
|
||||
id: 'complexity',
|
||||
i18nKey: 'SETTINGS.LIST.COMPLEXITY',
|
||||
|
@ -25,7 +25,7 @@
|
||||
<i *ngIf="copied !== tokenResponse.token" class="las la-clipboard"></i>
|
||||
<i *ngIf="copied === tokenResponse.token" class="las la-clipboard-check"></i>
|
||||
</button>
|
||||
<span>{{ tokenResponse.token }}</span>
|
||||
<span class="token">{{ tokenResponse.token }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@ -40,6 +40,11 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.token {
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.ctc {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
title="{{
|
||||
id ? ('SMTP.DETAIL.TITLE' | translate) : ('SMTP.CREATE.STEPS.TITLE' | translate: { value: providerDefaultSetting.name })
|
||||
}}"
|
||||
[createSteps]="3"
|
||||
[createSteps]="4"
|
||||
[currentCreateStep]="currentCreateStep"
|
||||
(closed)="close()"
|
||||
>
|
||||
@ -93,7 +93,7 @@
|
||||
[disabled]="firstFormGroup.invalid"
|
||||
color="primary"
|
||||
matStepperNext
|
||||
data-e2e="continue-button"
|
||||
data-e2e="continue-to-2nd-form"
|
||||
>
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
@ -130,19 +130,74 @@
|
||||
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
class="create-button"
|
||||
[disabled]="secondFormGroup.invalid"
|
||||
color="primary"
|
||||
data-e2e="create-button"
|
||||
(click)="savePolicy(stepper)"
|
||||
[disabled]="
|
||||
firstFormGroup.invalid || secondFormGroup.invalid || (['iam.policy.write'] | hasRole | async) === false
|
||||
"
|
||||
matStepperNext
|
||||
data-e2e="continue-button"
|
||||
>
|
||||
{{ !hasSMTPConfig ? ('ACTIONS.CREATE' | translate) : ('ACTIONS.SAVE' | translate) }}
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [editable]="true">
|
||||
<form>
|
||||
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.SAVE_SETTINGS' | translate }}</ng-template>
|
||||
<cnsl-info-section>
|
||||
<div class="title-row">
|
||||
<div class="left">
|
||||
<h2 class="title">{{ 'SMTP.CREATE.STEPS.TEST.TITLE' | translate }}</h2>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button color="primary" mat-raised-button class="continue-button" (click)="testEmailConfiguration()">
|
||||
{{ 'ACTIONS.TEST' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="cnsl-secondary-text description">{{ 'SMTP.CREATE.STEPS.TEST.DESCRIPTION' | translate }}</p>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'SMTP.LIST.DIALOG.TEST_EMAIL' | translate }}</cnsl-label>
|
||||
<input
|
||||
cnslInput
|
||||
[(ngModel)]="email"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
data-e2e="email-test-dialog-input"
|
||||
/>
|
||||
</cnsl-form-field>
|
||||
|
||||
<div class="is-loading" *ngIf="isLoading()">
|
||||
<mat-spinner diameter="50"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<cnsl-form-field class="formfield" *ngIf="testResult">
|
||||
<cnsl-label>{{ 'SMTP.LIST.DIALOG.TEST_RESULT' | translate }}</cnsl-label>
|
||||
<textarea
|
||||
cnslInput
|
||||
class="{{ resultClass }}"
|
||||
[(ngModel)]="testResult"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
></textarea>
|
||||
</cnsl-form-field>
|
||||
</cnsl-info-section>
|
||||
|
||||
<div class="smtp-create-actions">
|
||||
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
class="create-button"
|
||||
color="primary"
|
||||
data-e2e="create-button"
|
||||
(click)="savePolicy(stepper)"
|
||||
[disabled]="
|
||||
firstFormGroup.invalid || secondFormGroup.invalid || (['iam.policy.write'] | hasRole | async) === false
|
||||
"
|
||||
>
|
||||
{{ !hasSMTPConfig ? ('ACTIONS.CREATE' | translate) : ('ACTIONS.SAVE' | translate) }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [editable]="true">
|
||||
<form>
|
||||
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.NEXT_STEPS' | translate }}</ng-template>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, signal } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Subject, take } from 'rxjs';
|
||||
import { StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||
import { Options } from 'src/app/proto/generated/zitadel/idp_pb';
|
||||
import { requiredValidator } from '../form-field/validators/validators';
|
||||
@ -11,6 +11,7 @@ import { PolicyComponentServiceType } from '../policies/policy-component-types.e
|
||||
import {
|
||||
AddSMTPConfigRequest,
|
||||
AddSMTPConfigResponse,
|
||||
TestSMTPConfigRequest,
|
||||
UpdateSMTPConfigRequest,
|
||||
UpdateSMTPConfigResponse,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
@ -31,8 +32,10 @@ import {
|
||||
OutlookDefaultSettings,
|
||||
SendgridDefaultSettings,
|
||||
} from './known-smtp-providers-settings';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { MatStepper } from '@angular/material/stepper';
|
||||
import { SMTPConfigState } from 'src/app/proto/generated/zitadel/settings_pb';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-smtp-provider',
|
||||
@ -61,6 +64,11 @@ export class SMTPProviderComponent {
|
||||
|
||||
public senderEmailPlaceholder = 'sender@example.com';
|
||||
|
||||
public resultClass = 'test-success';
|
||||
public isLoading = signal(false);
|
||||
public email: string = '';
|
||||
public testResult: string = '';
|
||||
|
||||
constructor(
|
||||
private service: AdminService,
|
||||
private _location: Location,
|
||||
@ -68,6 +76,8 @@ export class SMTPProviderComponent {
|
||||
private toast: ToastService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private authService: GrpcAuthService,
|
||||
private translate: TranslateService,
|
||||
) {
|
||||
this.route.parent?.url.subscribe((urlPath) => {
|
||||
const providerName = urlPath[urlPath.length - 1].path;
|
||||
@ -136,6 +146,17 @@ export class SMTPProviderComponent {
|
||||
this.fetchData(this.id);
|
||||
}
|
||||
}
|
||||
|
||||
this.authService
|
||||
.getMyUser()
|
||||
.then((resp) => {
|
||||
if (resp.user) {
|
||||
this.email = resp.user.human?.email?.email || '';
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -281,6 +302,38 @@ export class SMTPProviderComponent {
|
||||
});
|
||||
}
|
||||
|
||||
public testEmailConfiguration(): void {
|
||||
this.isLoading.set(true);
|
||||
|
||||
const req = new TestSMTPConfigRequest();
|
||||
req.setSenderAddress(this.senderAddress?.value ?? '');
|
||||
req.setSenderName(this.senderName?.value ?? '');
|
||||
req.setHost(this.hostAndPort?.value ?? '');
|
||||
req.setUser(this.user?.value);
|
||||
req.setPassword(this.password?.value ?? '');
|
||||
req.setTls(this.tls?.value ?? false);
|
||||
req.setId(this.id ?? '');
|
||||
req.setReceiverAddress(this.email ?? '');
|
||||
|
||||
this.service
|
||||
.testSMTPConfig(req)
|
||||
.then(() => {
|
||||
this.resultClass = 'test-success';
|
||||
this.isLoading.set(false);
|
||||
this.translate
|
||||
.get('SMTP.CREATE.STEPS.TEST.RESULT')
|
||||
.pipe(take(1))
|
||||
.subscribe((msg) => {
|
||||
this.testResult = msg;
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.resultClass = 'test-error';
|
||||
this.isLoading.set(false);
|
||||
this.testResult = error;
|
||||
});
|
||||
}
|
||||
|
||||
public get description(): AbstractControl | null {
|
||||
return this.firstFormGroup.get('description');
|
||||
}
|
||||
|
@ -96,4 +96,26 @@
|
||||
width: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.continue-button {
|
||||
margin-top: 3rem;
|
||||
display: block;
|
||||
height: 3.5rem;
|
||||
padding: 0 4rem;
|
||||
}
|
||||
|
||||
.is-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.test-error {
|
||||
border-color: #ff3b5b !important;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.test-success {
|
||||
border-color: #10b981 !important;
|
||||
min-height: 200px;
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,18 @@
|
||||
<i class="las la-times-circle"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
actions
|
||||
[disabled]="(['iam.write'] | hasRole | async) === false"
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
matTooltip="{{ 'SMTP.LIST.TEST' | translate }}"
|
||||
data-e2e="test-provider-button"
|
||||
(click)="testSMTPConfig(config.id); $event.stopPropagation()"
|
||||
>
|
||||
<i class="las la-flask"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
actions
|
||||
[disabled]="(['iam.write'] | hasRole | async) === false"
|
||||
|
@ -16,6 +16,7 @@ import { SMTPConfig } from 'src/app/proto/generated/zitadel/settings_pb';
|
||||
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { SmtpTestDialogComponent } from '../smtp-test-dialog/smtp-test-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-smtp-table',
|
||||
@ -149,6 +150,21 @@ export class SMTPTableComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
public testSMTPConfig(id: string): void {
|
||||
this.dialog.open(SmtpTestDialogComponent, {
|
||||
data: {
|
||||
id: id,
|
||||
confirmKey: 'ACTIONS.TEST',
|
||||
cancelKey: 'ACTIONS.CLOSE',
|
||||
titleKey: 'SMTP.LIST.DIALOG.TEST_TITLE',
|
||||
descriptionKey: 'SMTP.LIST.DIALOG.TEST_DESCRIPTION',
|
||||
emailKey: 'SMTP.LIST.DIALOG.TEST_EMAIL',
|
||||
testResultKey: 'SMTP.LIST.DIALOG.TEST_RESULT',
|
||||
},
|
||||
width: '500px',
|
||||
});
|
||||
}
|
||||
|
||||
private async getData(limit: number, offset: number): Promise<void> {
|
||||
this.loadingSubject.next(true);
|
||||
|
||||
|
@ -18,6 +18,7 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { SmtpTestDialogModule } from '../smtp-test-dialog/smtp-test-dialog.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SMTPTableComponent],
|
||||
@ -40,6 +41,7 @@ import { MatTableModule } from '@angular/material/table';
|
||||
HasRoleModule,
|
||||
HasRolePipeModule,
|
||||
TruncatePipeModule,
|
||||
SmtpTestDialogModule,
|
||||
],
|
||||
exports: [SMTPTableComponent],
|
||||
})
|
||||
|
@ -0,0 +1,47 @@
|
||||
<h1 mat-dialog-title>
|
||||
<span>{{ data.titleKey | translate: data.titleParam }}</span>
|
||||
</h1>
|
||||
|
||||
<div mat-dialog-content>
|
||||
<div class="icon-wrapper" *ngIf="data.icon">
|
||||
<i class="icon {{ data.icon }}"></i>
|
||||
</div>
|
||||
<p class="desc cnsl-secondary-text">{{ data.descriptionKey | translate: data.descriptionParam }}</p>
|
||||
|
||||
<cnsl-info-section *ngIf="data.warnSectionKey" [type]="InfoSectionType.WARN">
|
||||
{{ data.warnSectionKey | translate }}
|
||||
</cnsl-info-section>
|
||||
|
||||
<p *ngIf="data.hintKey" class="desc cnsl-secondary-text">{{ data.hintKey | translate: { value: data.confirmation } }}</p>
|
||||
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ data.emailKey | translate }}</cnsl-label>
|
||||
<input cnslInput [(ngModel)]="email" data-e2e="email-test-dialog-input" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<div class="is-loading" *ngIf="isLoading()">
|
||||
<mat-spinner diameter="50"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<cnsl-form-field class="formfield" *ngIf="testResult">
|
||||
<cnsl-label>{{ data.testResultKey | translate }}</cnsl-label>
|
||||
<textarea cnslInput class="{{ resultClass }}" [(ngModel)]="testResult"></textarea>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
||||
<div class="action" mat-dialog-actions>
|
||||
<button *ngIf="data.cancelKey" mat-stroked-button (click)="closeDialog()">
|
||||
{{ data.cancelKey | translate }}
|
||||
</button>
|
||||
<span class="fill-space"></span>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="!email || isLoading()"
|
||||
mat-raised-button
|
||||
class="ok-button"
|
||||
(click)="testEmailConfiguration()"
|
||||
data-e2e="test-email-button"
|
||||
>
|
||||
{{ data.confirmKey | translate }}
|
||||
</button>
|
||||
</div>
|
@ -0,0 +1,51 @@
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
margin: 1rem;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
|
||||
button {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.ok-button {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.fill-space {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.is-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.test-error {
|
||||
border-color: #ff3b5b;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.test-success {
|
||||
border-color: #10b981;
|
||||
min-height: 200px;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { SmtpTestDialogComponent } from './smtp-test-dialog.component';
|
||||
|
||||
describe('SmtpTestDialogComponent', () => {
|
||||
let component: SmtpTestDialogComponent;
|
||||
let fixture: ComponentFixture<SmtpTestDialogComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [SmtpTestDialogComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SmtpTestDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,72 @@
|
||||
import { Component, Inject, signal } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
import { InfoSectionType } from '../info-section/info-section.component';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { TestSMTPConfigByIdRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { take } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-smtp-test-dialog',
|
||||
templateUrl: './smtp-test-dialog.component.html',
|
||||
styleUrls: ['./smtp-test-dialog.component.scss'],
|
||||
})
|
||||
export class SmtpTestDialogComponent {
|
||||
public resultClass = 'test-success';
|
||||
public isLoading = signal(false);
|
||||
public email: string = '';
|
||||
public testResult: string = '';
|
||||
InfoSectionType: any = InfoSectionType;
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<SmtpTestDialogComponent>,
|
||||
private adminService: AdminService,
|
||||
private authService: GrpcAuthService,
|
||||
private toast: ToastService,
|
||||
private translate: TranslateService,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) {
|
||||
this.authService
|
||||
.getMyUser()
|
||||
.then((resp) => {
|
||||
if (resp.user) {
|
||||
this.email = resp.user.human?.email?.email || '';
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
public testEmailConfiguration(): void {
|
||||
this.isLoading.set(true);
|
||||
|
||||
const req = new TestSMTPConfigByIdRequest();
|
||||
req.setId(this.data.id);
|
||||
req.setReceiverAddress(this.email);
|
||||
|
||||
this.adminService
|
||||
.testSMTPConfigById(req)
|
||||
.then(() => {
|
||||
this.resultClass = 'test-success';
|
||||
this.isLoading.set(false);
|
||||
this.translate
|
||||
.get('SMTP.CREATE.STEPS.TEST.RESULT')
|
||||
.pipe(take(1))
|
||||
.subscribe((msg) => {
|
||||
this.testResult = msg;
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.resultClass = 'test-error';
|
||||
this.isLoading.set(false);
|
||||
this.testResult = error;
|
||||
});
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { InfoSectionModule } from '../info-section/info-section.module';
|
||||
import { InputModule } from '../input/input.module';
|
||||
import { SmtpTestDialogComponent } from './smtp-test-dialog.component';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SmtpTestDialogComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
MatDialogModule,
|
||||
MatProgressSpinnerModule,
|
||||
TranslateModule,
|
||||
InfoSectionModule,
|
||||
MatButtonModule,
|
||||
InputModule,
|
||||
],
|
||||
})
|
||||
export class SmtpTestDialogModule {}
|
@ -18,6 +18,7 @@ import {
|
||||
LANGUAGES,
|
||||
IDP,
|
||||
LOCKOUT,
|
||||
AGE,
|
||||
LOGIN,
|
||||
LOGINTEXTS,
|
||||
MESSAGETEXTS,
|
||||
@ -64,6 +65,7 @@ export class InstanceComponent implements OnInit, OnDestroy {
|
||||
LOGIN,
|
||||
IDP,
|
||||
COMPLEXITY,
|
||||
AGE,
|
||||
LOCKOUT,
|
||||
|
||||
DOMAIN,
|
||||
|
@ -7,6 +7,7 @@ import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/
|
||||
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import {
|
||||
AGE,
|
||||
BRANDING,
|
||||
COMPLEXITY,
|
||||
DOMAIN,
|
||||
@ -33,6 +34,7 @@ export class OrgSettingsComponent implements OnInit {
|
||||
LOGIN,
|
||||
IDP,
|
||||
COMPLEXITY,
|
||||
AGE,
|
||||
LOCKOUT,
|
||||
NOTIFICATIONS,
|
||||
VERIFIED_DOMAINS,
|
||||
|
@ -240,6 +240,10 @@ import {
|
||||
SetSecurityPolicyResponse,
|
||||
SetUpOrgRequest,
|
||||
SetUpOrgResponse,
|
||||
TestSMTPConfigByIdRequest,
|
||||
TestSMTPConfigByIdResponse,
|
||||
TestSMTPConfigRequest,
|
||||
TestSMTPConfigResponse,
|
||||
UpdateAppleProviderRequest,
|
||||
UpdateAppleProviderResponse,
|
||||
UpdateAzureADProviderRequest,
|
||||
@ -330,6 +334,7 @@ import {
|
||||
} from '../proto/generated/zitadel/milestone/v1/milestone_pb';
|
||||
import { OrgFieldName, OrgQuery } from '../proto/generated/zitadel/org_pb';
|
||||
import { SortDirection } from '@angular/material/sort';
|
||||
import { SMTPConfig } from '../proto/generated/zitadel/settings_pb';
|
||||
|
||||
export interface OnboardingActions {
|
||||
order: number;
|
||||
@ -946,6 +951,14 @@ export class AdminService {
|
||||
return this.grpcService.admin.deactivateSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public testSMTPConfigById(req: TestSMTPConfigByIdRequest): Promise<TestSMTPConfigByIdResponse.AsObject> {
|
||||
return this.grpcService.admin.testSMTPConfigById(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public testSMTPConfig(req: TestSMTPConfigRequest): Promise<TestSMTPConfigResponse.AsObject> {
|
||||
return this.grpcService.admin.testSMTPConfig(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public removeSMTPConfig(id: string): Promise<RemoveSMTPConfigResponse.AsObject> {
|
||||
const req = new RemoveSMTPConfigRequest();
|
||||
req.setId(id);
|
||||
|
@ -1,3 +1,3 @@
|
||||
export const supportedLanguages = ['de', 'en', 'es', 'fr', 'it', 'ja', 'pl', 'zh', 'bg', 'pt', 'mk', 'cs', 'ru', 'nl'];
|
||||
export const supportedLanguagesRegexp: RegExp = /de|en|es|fr|it|ja|pl|zh|bg|pt|mk|cs|ru|nl/;
|
||||
export const supportedLanguages = ['de', 'en', 'es', 'fr', 'it', 'ja', 'pl', 'zh', 'bg', 'pt', 'mk', 'cs', 'ru', 'nl', 'sv'];
|
||||
export const supportedLanguagesRegexp: RegExp = /de|en|es|fr|it|ja|pl|zh|bg|pt|mk|cs|ru|nl|sv/;
|
||||
export const fallbackLanguage: string = 'en';
|
||||
|
@ -485,8 +485,15 @@
|
||||
"NEXT": "Следващ",
|
||||
"MORE": "Повече ▼",
|
||||
"STEP": "стъпка",
|
||||
"SETUP": "Настройвам",
|
||||
"COMINGSOON": "Очаквайте скоро",
|
||||
"TEST": "Тест",
|
||||
"UNSAVEDCHANGES": "Незапазени промени",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
"DESCRIPTION": "Сигурни ли сте, че искате да отхвърлите това ново действие? Вашето действие ще бъде загубено",
|
||||
"CANCEL": "Отказ",
|
||||
"DISCARD": "Изхвърлете"
|
||||
}
|
||||
},
|
||||
"TABLE": {
|
||||
"SHOWUSER": "Покажи потребител {{value}}"
|
||||
},
|
||||
@ -1319,6 +1326,7 @@
|
||||
"LANGUAGES": "Езици",
|
||||
"LOGIN": "Поведение при влизане и сигурност",
|
||||
"LOCKOUT": "Блокиране",
|
||||
"AGE": "Изтичане на паролата",
|
||||
"COMPLEXITY": "Сложност на паролата",
|
||||
"NOTIFICATIONS": "Настройки за известията",
|
||||
"SMTP_PROVIDER": "SMTP доставчик",
|
||||
@ -1373,7 +1381,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1538,8 +1547,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Остаряване на паролата",
|
||||
"DESCRIPTION": "Можете да зададете политика за остаряването на паролите. "
|
||||
"TITLE": "Изтичане на паролата",
|
||||
"DESCRIPTION": "Можете да зададете политика за изтичане на паролите. Тази политика ще принуди потребителя да смени паролата при следващото влизане след изтичането. Няма автоматични предупреждения и известия."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Политика за блокиране",
|
||||
@ -1602,7 +1611,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Проверката на имейл е извършена",
|
||||
@ -1691,8 +1701,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "показва грешки при блокиране",
|
||||
"MAXPASSWORDATTEMPTS": "Максимален брой опити за парола",
|
||||
"MAXOTPATTEMPTS": "Максимален брой опити за OTP",
|
||||
"EXPIREWARNDAYS": "Предупреждение за изтичане след ден",
|
||||
"MAXAGEDAYS": "Максимална възраст в дни",
|
||||
"EXPIREWARNDAYS": "Предупреждение за изтичане след дни",
|
||||
"MAXAGEDAYS": "Максимална валидност в дни",
|
||||
"USERLOGINMUSTBEDOMAIN": "Добавяне на домейн на организация като суфикс към имената за вход",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Ако активирате тази настройка, всички имена за вход ще имат суфикс с домейна на организацията. ",
|
||||
"VALIDATEORGDOMAINS": "Верификация на домейна на организацията е необходима (DNS или HTTP предизвикателство)",
|
||||
@ -2225,6 +2235,7 @@
|
||||
"ACTIVATED": "Активиран",
|
||||
"ACTIVATE": "Активирайте доставчика",
|
||||
"DEACTIVATE": "Деактивирайте доставчика",
|
||||
"TEST": "Тествайте вашия доставчик",
|
||||
"TYPE": "Тип",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP конфигурацията е активирана",
|
||||
@ -2248,7 +2259,6 @@
|
||||
"CURRENT_DESC_TITLE": "Това са вашите SMTP настройки",
|
||||
"PROVIDER_SETTINGS": "Настройки на SMTP доставчик",
|
||||
"SENDER_SETTINGS": "Настройки на изпращача",
|
||||
"TEST_SETTINGS": "Тествайте настройките на SMTP",
|
||||
"NEXT_STEPS": "Следващи стъпки",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Активирайте вашия SMTP доставчик",
|
||||
@ -2257,6 +2267,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Деактивирайте вашия SMTP доставчик",
|
||||
"DESCRIPTION": "Ако деактивирате този SMTP доставчик, ZITADEL не може да го използва за изпращане на известия, докато не го активирате отново."
|
||||
},
|
||||
"SAVE_SETTINGS": "Запазете вашите настройки",
|
||||
"TEST": {
|
||||
"TITLE": "Тествайте настройките си",
|
||||
"DESCRIPTION": "Можете да тествате настройките на вашия SMTP доставчик и да проверите резултата от теста, преди да ги запазите",
|
||||
"RESULT": "Вашият имейл беше изпратен успешно"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2531,7 +2547,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Добавяне на мениджър",
|
||||
|
@ -486,6 +486,7 @@
|
||||
"MORE": "více",
|
||||
"STEP": "Krok",
|
||||
"SETUP": "Nastavit",
|
||||
"TEST": "Test",
|
||||
"UNSAVEDCHANGES": "Neuložené změny",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1326,6 +1327,7 @@
|
||||
"LANGUAGES": "Jazyky",
|
||||
"LOGIN": "Chování při přihlášení a bezpečnost",
|
||||
"LOCKOUT": "Blokování",
|
||||
"AGE": "Expirace hesla",
|
||||
"COMPLEXITY": "Složitost hesla",
|
||||
"NOTIFICATIONS": "Oznámení",
|
||||
"SMTP_PROVIDER": "Poskytovatel SMTP",
|
||||
@ -1380,7 +1382,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1545,8 +1548,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Stáří hesla",
|
||||
"DESCRIPTION": "Můžete nastavit politiku pro stáří hesel. Tato politika vydá varování po uplynutí konkrétního času stáří."
|
||||
"TITLE": "Expirace hesla",
|
||||
"DESCRIPTION": "Můžete nastavit pravidlo pro vypršení platnosti hesel. Toto pravidlo donutí uživatele změnit heslo při dalším přihlášení po uplynutí platnosti. Neexistují žádná automatická varování a upozornění."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Politika uzamčení",
|
||||
@ -1609,7 +1612,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Ověření e-mailu dokončeno",
|
||||
@ -1698,8 +1702,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "zobrazit neúspěšné pokusy o uzamčení",
|
||||
"MAXPASSWORDATTEMPTS": "Maximální počet pokusů o heslo",
|
||||
"MAXOTPATTEMPTS": "Maximální počet pokusů o OTP",
|
||||
"EXPIREWARNDAYS": "Upozornění na expiraci po dni",
|
||||
"MAXAGEDAYS": "Maximální stáří v dnech",
|
||||
"EXPIREWARNDAYS": "Upozornění na uplynutí po dnech",
|
||||
"MAXAGEDAYS": "Maximální platnost v dnech",
|
||||
"USERLOGINMUSTBEDOMAIN": "Přidat doménu organizace jako příponu k přihlašovacím jménům",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Pokud povolíte toto nastavení, všechna přihlašovací jména budou doplněna o doménu organizace. Pokud je toto nastavení zakázáno, musíte zajistit, aby byla uživatelská jména jedinečná napříč všemi organizacemi.",
|
||||
"VALIDATEORGDOMAINS": "Požadováno ověření domény organizace (DNS nebo HTTP výzva)",
|
||||
@ -2244,6 +2248,7 @@
|
||||
"ACTIVATED": "Aktivováno",
|
||||
"ACTIVATE": "Aktivujte poskytovatele",
|
||||
"DEACTIVATE": "Deaktivovat poskytovatele",
|
||||
"TEST": "Otestujte svého poskytovatele",
|
||||
"TYPE": "Typ",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Konfigurace SMTP byla aktivována",
|
||||
@ -2267,7 +2272,6 @@
|
||||
"CURRENT_DESC_TITLE": "Toto jsou vaše nastavení SMTP",
|
||||
"PROVIDER_SETTINGS": "Nastavení poskytovatele SMTP",
|
||||
"SENDER_SETTINGS": "Nastavení odesílatele",
|
||||
"TEST_SETTINGS": "Otestujte nastavení SMTP",
|
||||
"NEXT_STEPS": "Další kroky",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Aktivujte svého poskytovatele SMTP",
|
||||
@ -2276,6 +2280,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Deaktivujte svého poskytovatele SMTP",
|
||||
"DESCRIPTION": "Pokud deaktivujete tohoto poskytovatele SMTP, ZITADEL jej nebude moci používat k odesílání upozornění, dokud jej znovu neaktivujete."
|
||||
},
|
||||
"SAVE_SETTINGS": "Uložte nastavení",
|
||||
"TEST": {
|
||||
"TITLE": "Otestujte svá nastavení",
|
||||
"DESCRIPTION": "Nastavení poskytovatele SMTP můžete otestovat a před uložením zkontrolovat výsledek testu",
|
||||
"RESULT": "Váš email byl úspěšně odeslán"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2550,7 +2560,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Přidat manažera",
|
||||
|
@ -485,6 +485,8 @@
|
||||
"NEXT": "Weiter",
|
||||
"MORE": "mehr",
|
||||
"STEP": "Schritt",
|
||||
"SETUP": "Aufstellen",
|
||||
"TEST": "Prüfen",
|
||||
"UNSAVEDCHANGES": "Nicht gespeicherte Änderungen",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1325,6 +1327,7 @@
|
||||
"LANGUAGES": "Sprachen",
|
||||
"LOGIN": "Loginverhalten und Sicherheit",
|
||||
"LOCKOUT": "Sperrmechanismen",
|
||||
"AGE": "Passwortgültigkeitsdauer",
|
||||
"COMPLEXITY": "Passwordkomplexität",
|
||||
"NOTIFICATIONS": "Benachrichtigungseinstellungen",
|
||||
"SMTP_PROVIDER": "SMTP-Anbieter",
|
||||
@ -1379,7 +1382,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1545,7 +1549,7 @@
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Gültigkeitsdauer für Passwörter",
|
||||
"DESCRIPTION": "Du kannst eine Richtlinie für die maximale Gültigkeitsdauer von Passwörtern festlegen. Diese Richtlinie löst eine Warnung nach Ablauf einer festgelegten Gültigkeitsdauer aus."
|
||||
"DESCRIPTION": "Du kannst eine Richtlinie für die maximale Gültigkeitsdauer von Passwörtern festlegen. Diese Richtlinie zwingt den Benutzer dazu, das Passwort bei der nächsten Anmeldung nach dem Ablauf zu ändern. Es gibt keine automatischen Warnungen und Benachrichtigungen."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Passwortsperre",
|
||||
@ -1608,7 +1612,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Email Verification erfolgreich",
|
||||
@ -2234,6 +2239,7 @@
|
||||
"ACTIVATED": "Aktiviert",
|
||||
"ACTIVATE": "Anbieter aktivieren",
|
||||
"DEACTIVATE": "Anbieter deaktivieren",
|
||||
"TEST": "Testen Sie Ihren Anbieter",
|
||||
"TYPE": "Typ",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Die SMTP-Konfiguration wurde aktiviert",
|
||||
@ -2257,7 +2263,6 @@
|
||||
"CURRENT_DESC_TITLE": "Dies sind Ihre SMTP-Einstellungen",
|
||||
"PROVIDER_SETTINGS": "SMTP-Anbietereinstellungen",
|
||||
"SENDER_SETTINGS": "Absendereinstellungen",
|
||||
"TEST_SETTINGS": "Testen Sie die SMTP-Einstellungen",
|
||||
"NEXT_STEPS": "Nächste Schritte",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Aktivieren Sie Ihren SMTP-Anbieter",
|
||||
@ -2266,6 +2271,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Deaktivieren Sie Ihren SMTP-Anbieter",
|
||||
"DESCRIPTION": "Wenn Sie diesen SMTP-Anbieter deaktivieren, kann ZITADEL ihn nicht zum Versenden von Benachrichtigungen verwenden, bis Sie ihn erneut aktivieren."
|
||||
},
|
||||
"SAVE_SETTINGS": "Speichern Sie Ihre Einstellungen",
|
||||
"TEST": {
|
||||
"TITLE": "Testen Sie Ihre Einstellungen",
|
||||
"DESCRIPTION": "Sie können die Einstellungen Ihres SMTP-Anbieters testen und das Testergebnis überprüfen, bevor Sie sie speichern",
|
||||
"RESULT": "Deine E-Mail wurde erfolgreich versandt"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2540,7 +2551,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Manager hinzufügen",
|
||||
|
@ -486,6 +486,7 @@
|
||||
"MORE": "more",
|
||||
"STEP": "Step",
|
||||
"SETUP": "Setup",
|
||||
"TEST": "Test",
|
||||
"UNSAVEDCHANGES": "Unsaved changes",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1326,6 +1327,7 @@
|
||||
"LANGUAGES": "Languages",
|
||||
"LOGIN": "Login Behavior and Security",
|
||||
"LOCKOUT": "Lockout",
|
||||
"AGE": "Password expiry",
|
||||
"COMPLEXITY": "Password complexity",
|
||||
"NOTIFICATIONS": "Notifications",
|
||||
"SMTP_PROVIDER": "SMTP Provider",
|
||||
@ -1380,7 +1382,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1545,8 +1548,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Password Aging",
|
||||
"DESCRIPTION": "You can set a policy for the aging of passwords. This policy emits a warning after the specific aging time has elapsed."
|
||||
"TITLE": "Password Expiry",
|
||||
"DESCRIPTION": "You can set a policy for the expiry of passwords. This policy will force the user to change the password on the next login after the expiration. There are no automatic warnings and notifications."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Lockout Policy",
|
||||
@ -1609,7 +1612,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Email verification done",
|
||||
@ -1698,8 +1702,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "show lockout failures",
|
||||
"MAXPASSWORDATTEMPTS": "Password maximum attempts",
|
||||
"MAXOTPATTEMPTS": "OTP maximum attempts",
|
||||
"EXPIREWARNDAYS": "Expiration Warning after day",
|
||||
"MAXAGEDAYS": "Max Age in days",
|
||||
"EXPIREWARNDAYS": "Expiration Warning after days",
|
||||
"MAXAGEDAYS": "Maximum validity in days",
|
||||
"USERLOGINMUSTBEDOMAIN": "Add organization domain as suffix to loginnames",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "If you enable this setting, all loginnames will be suffixed with the organization domain. If this settings is disabled, you have to ensure that usernames are unique over all organizations.",
|
||||
"VALIDATEORGDOMAINS": "Organization domain verification required (DNS or HTTP challenge)",
|
||||
@ -2256,6 +2260,7 @@
|
||||
"ACTIVATED": "Activated",
|
||||
"ACTIVATE": "Activate provider",
|
||||
"DEACTIVATE": "Deactivate provider",
|
||||
"TEST": "Test your provider",
|
||||
"TYPE": "Type",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP config has been activated",
|
||||
@ -2267,7 +2272,11 @@
|
||||
"DELETE_TITLE": "Delete SMTP config",
|
||||
"DELETE_DESCRIPTION": "You are about to delete a configuration. Confirm this action typing the sender name",
|
||||
"DELETED": "SMTP config has been deleted",
|
||||
"SENDER": "Type {{value}}, to delete this SMTP configuration."
|
||||
"SENDER": "Type {{value}}, to delete this SMTP configuration.",
|
||||
"TEST_TITLE": "Test your SMTP config",
|
||||
"TEST_DESCRIPTION": "Specify an email address to test your SMTP configuration for this provider",
|
||||
"TEST_EMAIL": "Email address",
|
||||
"TEST_RESULT": "Test result"
|
||||
}
|
||||
},
|
||||
"CREATE": {
|
||||
@ -2279,7 +2288,6 @@
|
||||
"CURRENT_DESC_TITLE": "These are your SMTP settings",
|
||||
"PROVIDER_SETTINGS": "SMTP Provider Settings",
|
||||
"SENDER_SETTINGS": "Sender Settings",
|
||||
"TEST_SETTINGS": "Test SMTP Settings",
|
||||
"NEXT_STEPS": "Next Steps",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Activate your SMTP Provider",
|
||||
@ -2288,6 +2296,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Deactivate your SMTP Provider",
|
||||
"DESCRIPTION": "If you deactivate this SMTP Provider, ZITADEL cannot use it to send notifications until you activate it again."
|
||||
},
|
||||
"SAVE_SETTINGS": "Save your settings",
|
||||
"TEST": {
|
||||
"TITLE": "Test your settings",
|
||||
"DESCRIPTION": "You can test your SMTP provider settings and check the test result before saving them",
|
||||
"RESULT": "Your email was succesfully sent"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2562,7 +2576,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Add a Manager",
|
||||
|
@ -486,6 +486,7 @@
|
||||
"MORE": "más",
|
||||
"STEP": "Paso",
|
||||
"SETUP": "Configurar",
|
||||
"TEST": "Probar",
|
||||
"UNSAVEDCHANGES": "Cambios no guardados",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1327,6 +1328,7 @@
|
||||
"LANGUAGES": "Idiomas",
|
||||
"LOGIN": "Comportamiento del inicio de sesión y de la seguridad",
|
||||
"LOCKOUT": "Bloqueo",
|
||||
"AGE": "Caducidad de la contraseña",
|
||||
"COMPLEXITY": "Complejidad de contraseña",
|
||||
"NOTIFICATIONS": "Ajustes de notificación",
|
||||
"SMTP_PROVIDER": "Proveedor SMTP",
|
||||
@ -1381,7 +1383,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1546,8 +1549,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Antigüedad de la contraseña",
|
||||
"DESCRIPTION": "Puedes establecer una política para la antigüedad de las contraseñas. Esta política emite un aviso después de que la antigüedad máxima se haya superado."
|
||||
"TITLE": "Caducidad de la contraseña",
|
||||
"DESCRIPTION": "Puedes establecer una política para la caducidad de las contraseñas. Esta política obligará al usuario a cambiar la contraseña en el próximo inicio de sesión después de la caducidad. No hay avisos ni notificaciones automáticos."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Política de bloqueo",
|
||||
@ -1610,7 +1613,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verificación de email realizada",
|
||||
@ -1699,8 +1703,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "mostrar fallos de bloqueo",
|
||||
"MAXPASSWORDATTEMPTS": "Intentos máximos de contraseña",
|
||||
"MAXOTPATTEMPTS": "Intentos máximos de OTP",
|
||||
"EXPIREWARNDAYS": "Aviso de expiración después de estos días: ",
|
||||
"MAXAGEDAYS": "Antigüedad máxima en días",
|
||||
"EXPIREWARNDAYS": "Aviso de caducidad después de días",
|
||||
"MAXAGEDAYS": "Validez máxima en días",
|
||||
"USERLOGINMUSTBEDOMAIN": "Añadir el dominio de la organización como sufijo de los nombres de inicio de sesión",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Si activas esta opción, todos los nombres de inicio de sesión tendrán como sufijo el dominio de esta organización. Si esta opción está desactivada, tendrás que asegurarte de que los nombres de usuario son únicos para todas las organizaciones.",
|
||||
"VALIDATEORGDOMAINS": "Verificación de dominio de la organización requerida (desafío DNS o HTTP)",
|
||||
@ -2232,6 +2236,7 @@
|
||||
"ACTIVATED": "Activado",
|
||||
"ACTIVATE": "Activar proveedor",
|
||||
"DEACTIVATE": "Desactivar proveedor",
|
||||
"TEST": "Prueba tu proveedor",
|
||||
"TYPE": "Tipo",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Tu configuración SMTP ha sido activada",
|
||||
@ -2255,7 +2260,6 @@
|
||||
"CURRENT_DESC_TITLE": "Estas son tus configuraciones SMTP",
|
||||
"PROVIDER_SETTINGS": "Configuración del proveedor SMTP",
|
||||
"SENDER_SETTINGS": "Configuración del remitente",
|
||||
"TEST_SETTINGS": "Probar la configuración SMTP",
|
||||
"NEXT_STEPS": "Pŕoximos pasos",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Activa tu proveedor SMTP",
|
||||
@ -2264,6 +2268,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Desactiva tu proveedor SMTP",
|
||||
"DESCRIPTION": "Si desactivas este proveedor SMTP, ZITADEL no puede utilizarlo para enviar notificationes hasta que lo actives otra vez."
|
||||
},
|
||||
"SAVE_SETTINGS": "Guarda tu configuración",
|
||||
"TEST": {
|
||||
"TITLE": "Prueba tu configuración",
|
||||
"DESCRIPTION": "Puedes probar tu configuración SMTP y revisar el resultado de la prueba antes de guardar la configuración",
|
||||
"RESULT": "Tu email fue enviado con éxito"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2538,7 +2548,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Añadir un Mánager",
|
||||
|
@ -485,6 +485,8 @@
|
||||
"NEXT": "Suivant",
|
||||
"MORE": "Plus",
|
||||
"STEP": "Étape",
|
||||
"SETUP": "Installation",
|
||||
"TEST": "Test",
|
||||
"UNSAVEDCHANGES": "Modifications non enregistrées",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1325,6 +1327,7 @@
|
||||
"LANGUAGES": "Langues",
|
||||
"LOGIN": "Comportement de connexion et sécurité",
|
||||
"LOCKOUT": "Verrouillage",
|
||||
"AGE": "Expiration du mot de passe",
|
||||
"COMPLEXITY": "Complexité du mot de passe",
|
||||
"NOTIFICATIONS": "Paramètres de notification",
|
||||
"SMTP_PROVIDER": "Fournisseur SMTP",
|
||||
@ -1379,7 +1382,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1544,8 +1548,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Vieillissement des mots de passe",
|
||||
"DESCRIPTION": "Vous pouvez définir une politique pour le vieillissement des mots de passe. Cette politique émet un avertissement après que le temps de vieillissement spécifique se soit écoulé."
|
||||
"TITLE": "Expiration du mot de passe",
|
||||
"DESCRIPTION": "Vous pouvez définir une politique d'expiration des mots de passe. Cette politique obligera l'utilisateur à changer son mot de passe lors de la prochaine connexion après l'expiration. Il n'y a pas d'avertissements ni de notifications automatiques."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Politique de verrouillage",
|
||||
@ -1608,7 +1612,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Vérification de l'e-mail effectuée",
|
||||
@ -1697,8 +1702,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "montrer les échecs de verrouillage",
|
||||
"MAXPASSWORDATTEMPTS": "Tentatives maximales du mot de passe",
|
||||
"MAXOTPATTEMPTS": "Tentatives maximales de l'OTP",
|
||||
"EXPIREWARNDAYS": "Avertissement d'expiration après le jour",
|
||||
"MAXAGEDAYS": "Âge maximum en jours",
|
||||
"EXPIREWARNDAYS": "Avertissement d'expiration après jours",
|
||||
"MAXAGEDAYS": "Validité maximale en jours",
|
||||
"USERLOGINMUSTBEDOMAIN": "Le nom de connexion de l'utilisateur doit contenir le nom de domaine de l'organisation",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Si vous activez ce paramètre, tous les noms de connexion seront suffixés avec le domaine de l'organisation. Si ce paramètre est désactivé, vous devez vous assurer que les noms d'utilisateur sont uniques pour toutes les organisations.",
|
||||
"VALIDATEORGDOMAINS": "Vérification du domaine de l'organisation requise (challenge DNS ou HTTP)",
|
||||
@ -2235,6 +2240,7 @@
|
||||
"ACTIVATED": "Activé",
|
||||
"ACTIVATE": "Activer le fournisseur",
|
||||
"DEACTIVATE": "Désactiver le fournisseur",
|
||||
"TEST": "Testez votre fournisseur",
|
||||
"TYPE": "Type",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "La configuration SMTP a été activée",
|
||||
@ -2258,7 +2264,6 @@
|
||||
"CURRENT_DESC_TITLE": "Ce sont vos paramètres SMTP",
|
||||
"PROVIDER_SETTINGS": "Paramètres du fournisseur SMTP",
|
||||
"SENDER_SETTINGS": "Paramètres de l'expéditeur",
|
||||
"TEST_SETTINGS": "Tester les paramètres SMTP",
|
||||
"NEXT_STEPS": "Prochaines étapes",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Activez votre fournisseur SMTP",
|
||||
@ -2267,6 +2272,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Désactivez votre fournisseur SMTP",
|
||||
"DESCRIPTION": "Si vous désactivez l'option SMTP, vous ne pourrez pas vous connecter à l'application, le dossier sera alors désactivé."
|
||||
},
|
||||
"SAVE_SETTINGS": "Enregistrez vos paramètres",
|
||||
"TEST": {
|
||||
"TITLE": "Testez vos paramètres",
|
||||
"DESCRIPTION": "Vous pouvez tester les paramètres de votre fournisseur SMTP et vérifier le résultat du test avant de les enregistrer",
|
||||
"RESULT": "Votre email a été envoyé avec succès"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2541,7 +2552,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Ajouter un responsable",
|
||||
|
@ -485,6 +485,8 @@
|
||||
"NEXT": "Avanti",
|
||||
"MORE": "azioni",
|
||||
"STEP": "Passo",
|
||||
"SETUP": "Setup",
|
||||
"TEST": "Test",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
"DESCRIPTION": "Sei sicuro di voler eliminare questa nuova azione? La tua azione andrà persa",
|
||||
@ -1325,6 +1327,7 @@
|
||||
"LANGUAGES": "Lingue",
|
||||
"LOGIN": "Comportamento login e sicurezza",
|
||||
"LOCKOUT": "Meccanismi di bloccaggio",
|
||||
"AGE": "Scadenza password",
|
||||
"COMPLEXITY": "Complessità della password",
|
||||
"NOTIFICATIONS": "Impostazioni di notifica",
|
||||
"SMTP_PROVIDER": "Fornitore SMTP",
|
||||
@ -1379,7 +1382,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1544,8 +1548,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Impostazioni di validità della password",
|
||||
"DESCRIPTION": "È possibile impostare una impostazone per la validità delle password. Questa emette un avviso dopo che il tempo di invecchiamento specifico è trascorso."
|
||||
"TITLE": "Scadenza password",
|
||||
"DESCRIPTION": "Puoi impostare una policy per la scadenza delle password. Questa policy obbligherà l'utente a cambiare la password al prossimo accesso dopo la scadenza. Non ci sono avvisi e notifiche automatiche."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Impostazioni di blocco",
|
||||
@ -1608,7 +1612,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verifica dell'e-mail terminata con successo.",
|
||||
@ -1697,8 +1702,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "mostra i fallimenti del blocco",
|
||||
"MAXPASSWORDATTEMPTS": "Massimo numero di tentativi di password",
|
||||
"MAXOTPATTEMPTS": "Massimo numero di tentativi di OTP",
|
||||
"EXPIREWARNDAYS": "Avviso scadenza dopo il giorno",
|
||||
"MAXAGEDAYS": "Lunghezza massima in giorni",
|
||||
"EXPIREWARNDAYS": "Avviso di scadenza dopo giorni",
|
||||
"MAXAGEDAYS": "Validità massima in giorni",
|
||||
"USERLOGINMUSTBEDOMAIN": "Nome utente deve contenere il dominio dell' organizzazione",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Se abiliti questa impostazione, a tutti i nomi di accesso verrà aggiunto il suffisso del dominio dell'organizzazione. Se questa impostazione è disabilitata, devi assicurarti che i nomi utente siano univoci per tutte le organizzazioni.",
|
||||
"VALIDATEORGDOMAINS": "Verifica del dominio dell'organizzazione richiesta (challenge DNS o HTTP)",
|
||||
@ -2235,6 +2240,7 @@
|
||||
"ACTIVATED": "Attivato",
|
||||
"ACTIVATE": "Attiva fornitore",
|
||||
"DEACTIVATE": "Disattiva fornitore",
|
||||
"TEST": "Metti alla prova il tuo fornitore",
|
||||
"TYPE": "Tipo",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "La configurazione SMTP è stata attivata",
|
||||
@ -2258,7 +2264,6 @@
|
||||
"CURRENT_DESC_TITLE": "Queste sono le tue impostazioni SMTP",
|
||||
"PROVIDER_SETTINGS": "Impostazioni del provider SMTP",
|
||||
"SENDER_SETTINGS": "Impostazioni mittente",
|
||||
"TEST_SETTINGS": "Testare le impostazioni SMTP",
|
||||
"NEXT_STEPS": "Prossimi passi",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Attiva il tuo provider SMTP",
|
||||
@ -2267,6 +2272,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Disattiva il tuo provider SMTP",
|
||||
"DESCRIPTION": "Dopo aver disattivato l'archivio SMTP, la schermata non è disponibile per l'utente, il documento è nuovo e non è attivo."
|
||||
},
|
||||
"SAVE_SETTINGS": "Salva le tue impostazioni",
|
||||
"TEST": {
|
||||
"TITLE": "Metti alla prova le tue impostazioni",
|
||||
"DESCRIPTION": "Puoi testare le impostazioni del tuo provider SMTP e controllare il risultato del test prima di salvarle",
|
||||
"RESULT": "La tua email è stata inviata correttamente"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2541,7 +2552,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Aggiungi un manager",
|
||||
|
@ -486,6 +486,7 @@
|
||||
"MORE": "さらに",
|
||||
"STEP": "ステップ",
|
||||
"SETUP": "セットアップ",
|
||||
"TEST": "テスト",
|
||||
"UNSAVEDCHANGES": "未保存の変更",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1326,6 +1327,7 @@
|
||||
"LANGUAGES": "一般設定",
|
||||
"LOGIN": "ログイン動作とセキュリティ",
|
||||
"LOCKOUT": "ロックアウト",
|
||||
"AGE": "パスワードの有効期限",
|
||||
"COMPLEXITY": "パスワードの複雑さ",
|
||||
"NOTIFICATIONS": "通知設定",
|
||||
"SMTP_PROVIDER": "SMTPプロバイダー",
|
||||
@ -1380,7 +1382,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1541,8 +1544,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "パスワードエージング",
|
||||
"DESCRIPTION": "パスワードエージングに関するポリシーを設定できます。このポリシーは、特定のエージング時間が経過した後に警告を発します。"
|
||||
"TITLE": "パスワードの有効期限",
|
||||
"DESCRIPTION": "パスワードの有効期限ポリシーを設定できます。 このポリシーにより、有効期限が切れた後にユーザーは次回のログイン時にパスワードを変更することを求められます。 自動的な警告や通知はない。"
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "ロックアウトポリシー",
|
||||
@ -1605,7 +1608,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "メール認証が完了しました",
|
||||
@ -1694,8 +1698,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "ロックアウトの失敗を表示する",
|
||||
"MAXPASSWORDATTEMPTS": "パスワードの最大試行",
|
||||
"MAXOTPATTEMPTS": "最大OTP試行回数",
|
||||
"EXPIREWARNDAYS": "有効期限の翌日以降の警告",
|
||||
"MAXAGEDAYS": "最大有効期限",
|
||||
"EXPIREWARNDAYS": "数日後に有効期限が切れます",
|
||||
"MAXAGEDAYS": "最大有効期限 (日数)",
|
||||
"USERLOGINMUSTBEDOMAIN": "ログイン名の接尾辞として組織ドメインを追加する",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "この設定を有効にすると、すべてのログイン名が組織ドメインで接尾辞が付けられます。この設定が無効になっている場合、ユーザー名がすべての組織で一意であることを確認する必要があります。",
|
||||
"VALIDATEORGDOMAINS": "組織のドメイン検証が必要です (DNSまたはHTTPチャレンジ)",
|
||||
@ -2227,6 +2231,7 @@
|
||||
"ACTIVATED": "アクティブ化された",
|
||||
"ACTIVATE": "プロバイダーをアクティブ化する",
|
||||
"DEACTIVATE": "プロバイダーを非アクティブ化する",
|
||||
"TEST": "プロバイダーをテストする",
|
||||
"TYPE": "タイプ",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP設定が有効化されました",
|
||||
@ -2250,7 +2255,6 @@
|
||||
"CURRENT_DESC_TITLE": "これらは SMTP 設定です",
|
||||
"PROVIDER_SETTINGS": "SMTPプロバイダーの設定",
|
||||
"SENDER_SETTINGS": "送信者の設定",
|
||||
"TEST_SETTINGS": "SMTP設定をテストする",
|
||||
"NEXT_STEPS": "次のステップ",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "SMTP プロバイダーをアクティブ化する",
|
||||
@ -2259,6 +2263,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "SMTPプロバイダーを非アクティブ化します",
|
||||
"DESCRIPTION": "この SMTP プロバイダーを非アクティブ化すると、再度アクティブ化するまで、Zitadel はそれを使用して通知を送信できなくなります。"
|
||||
},
|
||||
"SAVE_SETTINGS": "設定を保存する",
|
||||
"TEST": {
|
||||
"TITLE": "設定をテストする",
|
||||
"DESCRIPTION": "SMTP プロバイダーの設定をテストし、保存する前にテスト結果を確認できます。",
|
||||
"RESULT": "あなたの電子メールが正常に送信されました"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2533,7 +2543,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "マネージャーを追加する",
|
||||
|
@ -486,6 +486,7 @@
|
||||
"MORE": "повеќе",
|
||||
"STEP": "Чекор",
|
||||
"SETUP": "Подесување",
|
||||
"TEST": "Тест",
|
||||
"UNSAVEDCHANGES": "Незачувани промени",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1327,6 +1328,7 @@
|
||||
"LANGUAGES": "Општо",
|
||||
"LOGIN": "Правила и безбедност при најава",
|
||||
"LOCKOUT": "Забрана на пристап",
|
||||
"AGE": "Истекување на лозинката",
|
||||
"COMPLEXITY": "Сложеност на лозинката",
|
||||
"NOTIFICATIONS": "Подесувања за известувања",
|
||||
"SMTP_PROVIDER": "SMTP провајдер",
|
||||
@ -1381,7 +1383,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1546,8 +1549,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Важност на лозинка",
|
||||
"DESCRIPTION": "Можете да поставите политика за истекување на лозинките. Оваа политика издава предупредување откако ќе помени одреденото време на истекување."
|
||||
"TITLE": "Истекување на лозинката",
|
||||
"DESCRIPTION": "Можете да поставите политика за истекување на лозинките. Оваа политика ќе го принуди корисникот да ја смени лозинката при следлогото влегување по истекувањето. Нема автоматски предупредувања и известувања."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Политика за забрана на пристап",
|
||||
@ -1610,7 +1613,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Е-поштата е верифицирана",
|
||||
@ -1699,8 +1703,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "прикажи неуспешни заклучувања",
|
||||
"MAXPASSWORDATTEMPTS": "Максимален број на обиди за лозинка",
|
||||
"MAXOTPATTEMPTS": "Максимални обиди за OTP",
|
||||
"EXPIREWARNDAYS": "Предупредување за истекување по ден",
|
||||
"MAXAGEDAYS": "Максимална возраст во денови",
|
||||
"EXPIREWARNDAYS": "Предупредување за истекување по денови",
|
||||
"MAXAGEDAYS": "Максимална валидност во денови",
|
||||
"USERLOGINMUSTBEDOMAIN": "Додади организациски домен како суфикс на корисничките имиња",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Ако го овозможите ова подесување, сите кориснички имиња ќе имаат суфикс на организацискиот домен. Доколку ова подесување е оневозможено, морате да се осигурате дека корисничките имиња се уникатни низ сите организации.",
|
||||
"VALIDATEORGDOMAINS": "Потврда на доменот на организацијата е неопходна (DNS или HTTP предизвик)",
|
||||
@ -2232,6 +2236,7 @@
|
||||
"ACTIVATED": "Активиран",
|
||||
"ACTIVATE": "Активирајте го провајдерот",
|
||||
"DEACTIVATE": "Деактивирајте го провајдерот",
|
||||
"TEST": "Тестирајте го вашиот провајдер",
|
||||
"TYPE": "Тип",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP конфигурацијата е активирана",
|
||||
@ -2255,7 +2260,6 @@
|
||||
"CURRENT_DESC_TITLE": "Ова се вашите поставки за SMTP",
|
||||
"PROVIDER_SETTINGS": "Поставки на провајдерот SMTP",
|
||||
"SENDER_SETTINGS": "Поставки на испраќачот",
|
||||
"TEST_SETTINGS": "Тестирајте ги поставките за SMTP",
|
||||
"NEXT_STEPS": "Следните чекори",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Активирајте го вашиот SMTP провајдер",
|
||||
@ -2264,6 +2268,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Деактивирајте го вашиот SMTP провајдер",
|
||||
"DESCRIPTION": "Ако го деактивирате овој SMTP провајдер, ZITADEL не може да го користи за испраќање известувања додека не го активирате повторно."
|
||||
},
|
||||
"SAVE_SETTINGS": "Зачувајте ги вашите поставки",
|
||||
"TEST": {
|
||||
"TITLE": "Тестирајте ги вашите поставки",
|
||||
"DESCRIPTION": "Можете да ги тестирате поставките на провајдерот SMTP и да го проверите резултатот од тестот пред да ги зачувате",
|
||||
"RESULT": "Вашата е-пошта беше успешно испратена"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2538,7 +2548,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Додај Менаџер",
|
||||
|
@ -486,6 +486,7 @@
|
||||
"MORE": "meer",
|
||||
"STEP": "Stap",
|
||||
"SETUP": "Instellen",
|
||||
"TEST": "Test",
|
||||
"UNSAVEDCHANGES": "Niet-opgeslagen wijzigingen",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1326,6 +1327,7 @@
|
||||
"LANGUAGES": "Talen",
|
||||
"LOGIN": "Login Gedrag en Beveiliging",
|
||||
"LOCKOUT": "Lockout",
|
||||
"AGE": "Wachtwoord verloopt",
|
||||
"COMPLEXITY": "Wachtwoord complexiteit",
|
||||
"NOTIFICATIONS": "Notificaties",
|
||||
"SMTP_PROVIDER": "SMTP Provider",
|
||||
@ -1380,7 +1382,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1545,8 +1548,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Wachtwoord Veroudering",
|
||||
"DESCRIPTION": "U kunt een beleid instellen voor de veroudering van wachtwoorden. Dit beleid geeft een waarschuwing nadat de specifieke verouderingstijd is verstreken."
|
||||
"TITLE": "Wachtwoord verloopt",
|
||||
"DESCRIPTION": "U kunt een beleid instellen voor het verlopen van wachtwoorden. Dit beleid dwingt de gebruiker om het wachtwoord te wijzigen bij de volgende aanmelding na het verlopen. Er zijn geen automatische waarschuwingen en meldingen."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Lockout Beleid",
|
||||
@ -1609,7 +1612,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "E-mail verificatie voltooid",
|
||||
@ -1698,8 +1702,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "toon lockout mislukkingen",
|
||||
"MAXPASSWORDATTEMPTS": "Maximum pogingen voor wachtwoord",
|
||||
"MAXOTPATTEMPTS": "Maximale OTP-pogingen",
|
||||
"EXPIREWARNDAYS": "Vervaldatum Waarschuwing na dag",
|
||||
"MAXAGEDAYS": "Maximale Leeftijd in dagen",
|
||||
"EXPIREWARNDAYS": "Waarschuwing voor verlopen na dagen",
|
||||
"MAXAGEDAYS": "Maximale geldigheid in dagen",
|
||||
"USERLOGINMUSTBEDOMAIN": "Voeg organisatie domein toe als achtervoegsel aan inlognamen",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Als u deze instelling inschakelt, worden alle inlognamen voorzien van een achtervoegsel met het domein van de organisatie. Als deze instelling is uitgeschakeld, moet u ervoor zorgen dat gebruikersnamen uniek zijn over alle organisaties.",
|
||||
"VALIDATEORGDOMAINS": "Verificatie van organisatiedomeinen vereist (DNS of HTTP-uitdaging)",
|
||||
@ -2253,6 +2257,7 @@
|
||||
"ACTIVATED": "Geactiveerd",
|
||||
"ACTIVATE": "Aanbieder activeren",
|
||||
"DEACTIVATE": "Aanbieder deactiveren",
|
||||
"TEST": "Test uw aanbieder",
|
||||
"TYPE": "Type",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP-configuratie is geactiveerd",
|
||||
@ -2276,7 +2281,6 @@
|
||||
"CURRENT_DESC_TITLE": "Dit zijn uw SMTP-instellingen",
|
||||
"PROVIDER_SETTINGS": "SMTP-providerinstellingen",
|
||||
"SENDER_SETTINGS": "Afzenderinstellingen",
|
||||
"TEST_SETTINGS": "SMTP-instellingen testen",
|
||||
"NEXT_STEPS": "Volgende stappen",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Activeer uw SMTP-provider",
|
||||
@ -2285,6 +2289,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Deactiveer uw SMTP-provider",
|
||||
"DESCRIPTION": "Als u deze SMTP-provider deactiveert, kan ZITADEL deze niet gebruiken om meldingen te verzenden totdat u deze opnieuw activeert."
|
||||
},
|
||||
"SAVE_SETTINGS": "Sla uw instellingen op",
|
||||
"TEST": {
|
||||
"TITLE": "Test uw instellingen",
|
||||
"DESCRIPTION": "U kunt de instellingen van uw SMTP-provider testen en het testresultaat controleren voordat u deze opslaat",
|
||||
"RESULT": "Je email is succesvol verzonden"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2559,7 +2569,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Voeg een Manager toe",
|
||||
|
@ -486,6 +486,7 @@
|
||||
"MORE": "więcej",
|
||||
"STEP": "Krok",
|
||||
"UNSAVEDCHANGES": "Niezapisane zmiany",
|
||||
"TEST": "Test",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
"DESCRIPTION": "Czy na pewno chcesz odrzucić to nowe działanie? Twoje działanie zostanie utracone",
|
||||
@ -1325,6 +1326,7 @@
|
||||
"LANGUAGES": "Języki",
|
||||
"LOGIN": "Zachowanie logowania i bezpieczeństwo",
|
||||
"LOCKOUT": "Blokada",
|
||||
"AGE": "Wygaśnięcie hasła",
|
||||
"COMPLEXITY": "Złożoność hasła",
|
||||
"NOTIFICATIONS": "Ustawienia powiadomień",
|
||||
"SMTP_PROVIDER": "Dostawca SMTP",
|
||||
@ -1379,7 +1381,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1544,8 +1547,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Starzenie się hasła",
|
||||
"DESCRIPTION": "Możesz ustawić politykę dotyczącą starzenia się haseł. Ta polityka emituje ostrzeżenie po upływie określonego czasu starzenia."
|
||||
"TITLE": "Wygaśnięcie hasła",
|
||||
"DESCRIPTION": "Możesz ustawić zasady wygasania haseł. Ta zasada zmusi użytkownika do zmiany hasła przy następnym logowaniu po jego wygaśnięciu. Nie ma automatycznych ostrzeżeń i powiadomień."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Polityka blokowania",
|
||||
@ -1608,7 +1611,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Weryfikacja adresu e-mail zakończona",
|
||||
@ -1697,8 +1701,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "pokaż blokady nieudanych prób",
|
||||
"MAXPASSWORDATTEMPTS": "Maksymalna liczba prób wprowadzenia hasła",
|
||||
"MAXOTPATTEMPTS": "Maksymalna liczba prób OTP",
|
||||
"EXPIREWARNDAYS": "Ostrzeżenie o wygaśnięciu po dniu",
|
||||
"MAXAGEDAYS": "Maksymalny wiek w dniach",
|
||||
"EXPIREWARNDAYS": "Ostrzeżenie o wygaśnięciu po dniach",
|
||||
"MAXAGEDAYS": "Maksymalna ważność w dniach",
|
||||
"USERLOGINMUSTBEDOMAIN": "Dodaj domenę organizacji jako przyrostek do nazw logowania",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Jeśli włączysz to ustawienie, wszystkie nazwy logowania będą miały przyrostek z domeną organizacji. Jeśli to ustawienie jest wyłączone, musisz zapewnić unikalność nazw użytkowników we wszystkich organizacjach.",
|
||||
"VALIDATEORGDOMAINS": "Weryfikacja domeny organizacji jest wymagana (wyzwanie DNS lub HTTP)",
|
||||
@ -2235,6 +2239,7 @@
|
||||
"ACTIVATED": "Aktywowany",
|
||||
"ACTIVATE": "Aktywuj dostawcę",
|
||||
"DEACTIVATE": "Dezaktywuj dostawcę",
|
||||
"TEST": "Przetestuj swojego dostawcę",
|
||||
"TYPE": "Typ",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Konfiguracja SMTP została aktywowana",
|
||||
@ -2258,7 +2263,6 @@
|
||||
"CURRENT_DESC_TITLE": "To są Twoje ustawienia SMTP",
|
||||
"PROVIDER_SETTINGS": "Ustawienia dostawcy SMTP",
|
||||
"SENDER_SETTINGS": "Ustawienia nadawcy",
|
||||
"TEST_SETTINGS": "Przetestuj ustawienia SMTP",
|
||||
"NEXT_STEPS": "Następne kroki",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Aktywuj swojego dostawcę SMTP",
|
||||
@ -2267,6 +2271,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Dezaktywuj swojego dostawcę SMTP",
|
||||
"DESCRIPTION": "Jeśli dezaktywujesz tego dostawcę SMTP, ZITADEL nie będzie mógł go używać do wysyłania powiadomień, dopóki nie aktywujesz go ponownie."
|
||||
},
|
||||
"SAVE_SETTINGS": "Zapisz swoje ustawienia",
|
||||
"TEST": {
|
||||
"TITLE": "Przetestuj swoje ustawienia",
|
||||
"DESCRIPTION": "Możesz przetestować ustawienia dostawcy SMTP i sprawdzić wynik testu przed ich zapisaniem",
|
||||
"RESULT": "Twój email został wysłany"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2541,7 +2551,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Dodaj managera",
|
||||
|
@ -486,6 +486,7 @@
|
||||
"MORE": "mais",
|
||||
"STEP": "Passo",
|
||||
"SETUP": "Configuração",
|
||||
"TEST": "Teste",
|
||||
"UNSAVEDCHANGES": "Alterações não salvas",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1327,6 +1328,7 @@
|
||||
"LANGUAGES": "Idiomas",
|
||||
"LOGIN": "Comportamento de Login e Segurança",
|
||||
"LOCKOUT": "Bloqueio",
|
||||
"AGE": "Expiração da senha",
|
||||
"COMPLEXITY": "Complexidade de Senha",
|
||||
"NOTIFICATIONS": "Configurações de Notificação",
|
||||
"SMTP_PROVIDER": "Provedor SMTP",
|
||||
@ -1381,7 +1383,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1546,8 +1549,8 @@
|
||||
}
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Envelhecimento de senha",
|
||||
"DESCRIPTION": "Você pode definir uma política para o envelhecimento de senhas. Essa política emite um aviso após o tempo de envelhecimento específico ter passado."
|
||||
"TITLE": "Expiração da senha",
|
||||
"DESCRIPTION": "Você pode definir uma política para a expiração de senhas. Esta política forçará o usuário a alterar a senha no próximo login após a expiração. Não existem avisos e notificações automáticas."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Política de bloqueio",
|
||||
@ -1610,7 +1613,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verificação de email concluída",
|
||||
@ -1700,7 +1704,7 @@
|
||||
"MAXPASSWORDATTEMPTS": "Máximo de tentativas de senha",
|
||||
"MAXOTPATTEMPTS": "Máximo de tentativas de OTP",
|
||||
"EXPIREWARNDAYS": "Aviso de expiração após dias",
|
||||
"MAXAGEDAYS": "Idade máxima em dias",
|
||||
"MAXAGEDAYS": "Validade máxima em dias",
|
||||
"USERLOGINMUSTBEDOMAIN": "Adicionar domínio da organização como sufixo aos nomes de login",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Se você habilitar essa configuração, todos os nomes de login serão sufixados com o domínio da organização. Se essa configuração estiver desabilitada, você deve garantir que os nomes de usuário sejam exclusivos em todas as organizações.",
|
||||
"VALIDATEORGDOMAINS": "Verificação de domínio da organização necessária (desafio DNS ou HTTP)",
|
||||
@ -2230,6 +2234,7 @@
|
||||
"ACTIVATED": "Ativado",
|
||||
"ACTIVATE": "Ativar provedor",
|
||||
"DEACTIVATE": "Desativar provedor",
|
||||
"TEST": "Teste seu provedor",
|
||||
"TYPE": "Tipo",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "A configuração SMTP foi ativada",
|
||||
@ -2253,7 +2258,6 @@
|
||||
"CURRENT_DESC_TITLE": "Estas são suas configurações de SMTP",
|
||||
"PROVIDER_SETTINGS": "Configurações do provedor SMTP",
|
||||
"SENDER_SETTINGS": "Configurações do remetente",
|
||||
"TEST_SETTINGS": "Testar configurações de SMTP",
|
||||
"NEXT_STEPS": "Próximos passos",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Ative seu provedor SMTP",
|
||||
@ -2262,6 +2266,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Desative seu provedor SMTP",
|
||||
"DESCRIPTION": "Se você desativar este provedor SMTP, a ZITADEL não poderá usá-lo para enviar notificações até que você o ative novamente."
|
||||
},
|
||||
"SAVE_SETTINGS": "Salve suas configurações",
|
||||
"TEST": {
|
||||
"TITLE": "Teste suas configurações",
|
||||
"DESCRIPTION": "Você pode testar as configurações do seu provedor SMTP e verificar o resultado do teste antes de salvá-las",
|
||||
"RESULT": "Seu e-mail foi enviado com sucesso"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2536,7 +2546,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Adicionar um Gerente",
|
||||
|
@ -485,6 +485,7 @@
|
||||
"MORE": "больше",
|
||||
"STEP": "Шаг",
|
||||
"SETUP": "Настроить",
|
||||
"TEST": "Тест",
|
||||
"UNSAVEDCHANGES": "Несохраненные изменения",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1373,6 +1374,7 @@
|
||||
"LANGUAGES": "Языки",
|
||||
"LOGIN": "Действия при входе и безопасность",
|
||||
"LOCKOUT": "Блокировка",
|
||||
"AGE": "Срок действия пароля",
|
||||
"COMPLEXITY": "Сложность пароля",
|
||||
"NOTIFICATIONS": "Настройки уведомлений",
|
||||
"NOTIFICATIONS_DESC": "Настройки SMTP и SMS",
|
||||
@ -1423,7 +1425,8 @@
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1595,7 +1598,7 @@
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "Срок действия пароля",
|
||||
"DESCRIPTION": "Вы можете установить политику срока действия паролей. Данная политика предупреждает об истечении определённого времени срока действия."
|
||||
"DESCRIPTION": "Вы можете установить политику истечения срока действия паролей. Эта политика вынудит пользователя изменить пароль при следующем входе в систему после истечения срока его действия. Нет никаких автоматических предупреждений и уведомлений."
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "Политика блокировки",
|
||||
@ -1664,7 +1667,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"LOCALE": "Код языка",
|
||||
"LOCALES": {
|
||||
@ -1765,8 +1769,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "Показать ошибки блокировки",
|
||||
"MAXPASSWORDATTEMPTS": "Максимальное количество попыток пароля",
|
||||
"MAXOTPATTEMPTS": "Максимальное количество попыток OTP",
|
||||
"EXPIREWARNDAYS": "Предупреждение об истечении срока действия после дня",
|
||||
"MAXAGEDAYS": "Максимальный возраст в днях",
|
||||
"EXPIREWARNDAYS": "Предупреждение об истечении срока действия через несколько дней",
|
||||
"MAXAGEDAYS": "Максимальная продолжительность действия (дни)",
|
||||
"USERLOGINMUSTBEDOMAIN": "Добавить домен организации в качестве суффикса к именам логина",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "Если вы включите данный параметр, все имена входа будут иметь суффикс домена организации. Если данный параметр отключен, вы должны убедиться, что имена пользователей уникальны для всех организаций.",
|
||||
"VALIDATEORGDOMAINS": "Проверка доменов организации",
|
||||
@ -2347,6 +2351,7 @@
|
||||
"ACTIVATED": "Активировано",
|
||||
"ACTIVATE": "Активировать провайдера",
|
||||
"DEACTIVATE": "Деактивировать провайдера",
|
||||
"TEST": "Проверьте своего провайдера",
|
||||
"TYPE": "Тип",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "Конфигурация SMTP активирована",
|
||||
@ -2370,7 +2375,6 @@
|
||||
"CURRENT_DESC_TITLE": "Это ваши настройки SMTP",
|
||||
"PROVIDER_SETTINGS": "Настройки SMTP-провайдера",
|
||||
"SENDER_SETTINGS": "Настройки отправителя",
|
||||
"TEST_SETTINGS": "Проверка настроек SMTP",
|
||||
"NEXT_STEPS": "Следующие шаги",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "Активируйте своего SMTP-провайдера",
|
||||
@ -2379,6 +2383,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "Деактивируйте своего SMTP-провайдера",
|
||||
"DESCRIPTION": "Если вы деактивируете этого поставщика SMTP, ZITADEL не сможет использовать его для отправки уведомлений, пока вы не активируете его снова."
|
||||
},
|
||||
"SAVE_SETTINGS": "Сохраните настройки",
|
||||
"TEST": {
|
||||
"TITLE": "Проверьте свои настройки",
|
||||
"DESCRIPTION": "Вы можете проверить настройки своего провайдера SMTP и проверить результаты проверки перед их сохранением.",
|
||||
"RESULT": "Ваше письмо было успешно отправлено"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2649,7 +2659,8 @@
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Добавить менеджера",
|
||||
|
2657
console/src/assets/i18n/sv.json
Normal file
2657
console/src/assets/i18n/sv.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -485,6 +485,8 @@
|
||||
"NEXT": "下一页",
|
||||
"MORE": "更多",
|
||||
"STEP": "步",
|
||||
"SETUP": "设置",
|
||||
"TEST": "测试",
|
||||
"UNSAVEDCHANGES": "未保存的更改",
|
||||
"UNSAVED": {
|
||||
"DIALOG": {
|
||||
@ -1325,6 +1327,7 @@
|
||||
"LANGUAGES": "语言",
|
||||
"LOGIN": "登录行为和安全",
|
||||
"LOCKOUT": "安全锁策略",
|
||||
"AGE": "密码过期",
|
||||
"COMPLEXITY": "密码复杂性",
|
||||
"NOTIFICATIONS": "通知设置",
|
||||
"SMTP_PROVIDER": "SMTP 提供商",
|
||||
@ -1379,7 +1382,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1544,7 +1548,7 @@
|
||||
},
|
||||
"PWD_AGE": {
|
||||
"TITLE": "密码过期",
|
||||
"DESCRIPTION": "您可以设置密码过期策略。此策略会在特定过期时间过后发出警告。"
|
||||
"DESCRIPTION": "您可以设置密码过期策略。此策略将强制用户在密码过期后下次登录时更改密码。没有自动警告和通知。"
|
||||
},
|
||||
"PWD_LOCKOUT": {
|
||||
"TITLE": "锁定策略",
|
||||
@ -1607,7 +1611,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "电子邮件验证完成",
|
||||
@ -1696,8 +1701,8 @@
|
||||
"SHOWLOCKOUTFAILURES": "显示锁定失败",
|
||||
"MAXPASSWORDATTEMPTS": "密码最大尝试次数",
|
||||
"MAXOTPATTEMPTS": "最多尝试 OTP 次数",
|
||||
"EXPIREWARNDAYS": "密码过期警告",
|
||||
"MAXAGEDAYS": "Max Age in days",
|
||||
"EXPIREWARNDAYS": "密码将在几天后过期",
|
||||
"MAXAGEDAYS": "最大有效期 (天)",
|
||||
"USERLOGINMUSTBEDOMAIN": "用户名必须包含组织域名",
|
||||
"USERLOGINMUSTBEDOMAIN_DESCRIPTION": "如果启用此设置,所有登录名都将以组织域为后缀。如果禁用此设置,您必须确保用户名在所有组织中都是唯一的。",
|
||||
"VALIDATEORGDOMAINS": "组织域名验证需要 (DNS 或 HTTP 挑战)",
|
||||
@ -2234,6 +2239,7 @@
|
||||
"ACTIVATED": "活性",
|
||||
"ACTIVATE": "激活提供商",
|
||||
"DEACTIVATE": "停用提供商",
|
||||
"TEST": "测试您的提供商",
|
||||
"TYPE": "类型",
|
||||
"DIALOG": {
|
||||
"ACTIVATED": "SMTP 配置已激活",
|
||||
@ -2257,7 +2263,6 @@
|
||||
"CURRENT_DESC_TITLE": "这些是您的 SMTP 设置",
|
||||
"PROVIDER_SETTINGS": "SMTP 提供商设置",
|
||||
"SENDER_SETTINGS": "发件人设置",
|
||||
"TEST_SETTINGS": "测试 SMTP 设置",
|
||||
"NEXT_STEPS": "下一步",
|
||||
"ACTIVATE": {
|
||||
"TITLE": "激活您的 SMTP 提供商",
|
||||
@ -2266,6 +2271,12 @@
|
||||
"DEACTIVATE": {
|
||||
"TITLE": "停用您的 SMTP 提供商",
|
||||
"DESCRIPTION": "如果您停用此 SMTP 提供程序,Zitadel 将无法使用它发送通知,直到您再次激活它。"
|
||||
},
|
||||
"SAVE_SETTINGS": "保存您的设置",
|
||||
"TEST": {
|
||||
"TITLE": "测试您的设置",
|
||||
"DESCRIPTION": "您可以测试您的 SMTP 提供商设置并在保存之前检查测试结果",
|
||||
"RESULT": "您的电子邮件已成功发送"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2540,7 +2551,8 @@
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "添加管理者",
|
||||
|
1
docs/.gitignore
vendored
1
docs/.gitignore
vendored
@ -26,3 +26,4 @@ package-lock.json
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.vercel
|
||||
|
@ -1,13 +0,0 @@
|
||||
## Angular lint workspace and production build
|
||||
FROM node:18 as builder
|
||||
WORKDIR /docs
|
||||
COPY docs/package.json docs/yarn.lock ./
|
||||
RUN yarn install --frozen-lockfile
|
||||
COPY docs .
|
||||
COPY proto /proto
|
||||
RUN yarn build
|
||||
|
||||
## Final image for serving
|
||||
FROM nginx as final
|
||||
COPY docs/nginx.conf /etc/nginx/nginx.conf
|
||||
COPY --from=builder /docs/build /usr/share/nginx/html
|
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve("@docusaurus/core/lib/babel/preset")],
|
||||
compact: true
|
||||
compact: auto
|
||||
};
|
||||
|
123
docs/docs/apis/_v3_action_execution.proto
Normal file
123
docs/docs/apis/_v3_action_execution.proto
Normal file
@ -0,0 +1,123 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.action.v3alpha;
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
import "zitadel/protoc_gen_zitadel/v2/options.proto";
|
||||
|
||||
import "zitadel/resources/object/v3alpha/object.proto";
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
|
||||
|
||||
message Execution {
|
||||
Condition condition = 1;
|
||||
// Target IDs which are called when the defined conditions trigger.
|
||||
repeated string targets = 2;
|
||||
// Included executions with the same condition-types.
|
||||
repeated string includes = 3;
|
||||
}
|
||||
|
||||
message GetExecution {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
Execution execution = 2;
|
||||
}
|
||||
|
||||
message Condition {
|
||||
// Condition-types under which conditions the execution should trigger. Only one is possible.
|
||||
oneof condition_type {
|
||||
option (validate.required) = true;
|
||||
|
||||
// Condition-type to execute after a request on the defined API point is received.
|
||||
RequestExecution request = 1;
|
||||
// Condition-type to execute before a response on the defined API point is returned.
|
||||
ResponseExecution response = 2;
|
||||
// Condition-type to execute when a function is used, replaces actions v1.
|
||||
string function = 3;
|
||||
// Condition-type to execute after an event is created in the system.
|
||||
EventExecution event = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message RequestExecution {
|
||||
// Condition for the request execution. Only one is possible.
|
||||
oneof condition{
|
||||
// GRPC-method as condition.
|
||||
string method = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 1000},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 1000,
|
||||
example: "\"/zitadel.session.v2beta.SessionService/ListSessions\"";
|
||||
}
|
||||
];
|
||||
// GRPC-service as condition.
|
||||
string service = 2 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 1000},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 1000,
|
||||
example: "\"zitadel.session.v2beta.SessionService\"";
|
||||
}
|
||||
];
|
||||
// All calls to any available services and methods as condition.
|
||||
bool all = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message ResponseExecution {
|
||||
// Condition for the response execution. Only one is possible.
|
||||
oneof condition{
|
||||
// GRPC-method as condition.
|
||||
string method = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 1000},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 1000,
|
||||
example: "\"/zitadel.session.v2beta.SessionService/ListSessions\"";
|
||||
}
|
||||
];
|
||||
// GRPC-service as condition.
|
||||
string service = 2 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 1000},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 1000,
|
||||
example: "\"zitadel.session.v2beta.SessionService\"";
|
||||
}
|
||||
];
|
||||
// All calls to any available services and methods as condition.
|
||||
bool all = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message EventExecution{
|
||||
// Condition for the event execution. Only one is possible.
|
||||
oneof condition{
|
||||
// Event name as condition.
|
||||
string event = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 1000},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 1000,
|
||||
example: "\"user.human.added\"";
|
||||
}
|
||||
];
|
||||
// Event group as condition, all events under this group.
|
||||
string group = 2 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 1000},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 1000,
|
||||
example: "\"user.human\"";
|
||||
}
|
||||
];
|
||||
// all events as condition.
|
||||
bool all = 3;
|
||||
}
|
||||
}
|
||||
|
111
docs/docs/apis/_v3_action_search.proto
Normal file
111
docs/docs/apis/_v3_action_search.proto
Normal file
@ -0,0 +1,111 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.action.v3alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
import "zitadel/resources/object/v3alpha/object.proto";
|
||||
import "zitadel/resources/action/v3alpha/execution.proto";
|
||||
|
||||
message ExecutionSearchFilter {
|
||||
oneof filter {
|
||||
option (validate.required) = true;
|
||||
|
||||
InConditionsFilter in_conditions = 1;
|
||||
ExecutionTypeFilter execution_type = 2;
|
||||
TargetFilter target = 3;
|
||||
IncludeFilter include = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message InConditionsFilter {
|
||||
// Defines the conditions to query for.
|
||||
repeated Condition conditions = 1;
|
||||
}
|
||||
|
||||
message ExecutionTypeFilter {
|
||||
// Defines the type to query for.
|
||||
ExecutionType type = 1;
|
||||
}
|
||||
|
||||
message TargetFilter {
|
||||
// Defines the id to query for.
|
||||
string id = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "the id of the targets to include"
|
||||
example: "\"69629023906488334\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message IncludeFilter {
|
||||
// Defines the include to query for.
|
||||
string include = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "the id of the include"
|
||||
example: "\"request.zitadel.session.v2beta.SessionService\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message TargetSearchFilter {
|
||||
oneof query {
|
||||
option (validate.required) = true;
|
||||
|
||||
TargetNameFilter name = 1;
|
||||
InTargetIDsFilter in_ids = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message TargetNameFilter {
|
||||
// Defines the name of the target to query for.
|
||||
string name = 1 [
|
||||
(validate.rules).string = {max_len: 200},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
max_length: 200;
|
||||
example: "\"ip_allow_list\"";
|
||||
}
|
||||
];
|
||||
// Defines which text comparison method used for the name query.
|
||||
zitadel.resources.object.v3alpha.TextFilterMethod method = 2 [
|
||||
(validate.rules).enum.defined_only = true,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "defines which text equality method is used";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message InTargetIDsFilter {
|
||||
// Defines the ids to query for.
|
||||
repeated string ids = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "the ids of the targets to include"
|
||||
example: "[\"69629023906488334\",\"69622366012355662\"]";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
enum ExecutionType {
|
||||
EXECUTION_TYPE_UNSPECIFIED = 0;
|
||||
EXECUTION_TYPE_REQUEST = 1;
|
||||
EXECUTION_TYPE_RESPONSE = 2;
|
||||
EXECUTION_TYPE_EVENT = 3;
|
||||
EXECUTION_TYPE_FUNCTION = 4;
|
||||
}
|
||||
|
||||
enum TargetFieldName {
|
||||
TARGET_FIELD_NAME_UNSPECIFIED = 0;
|
||||
TARGET_FIELD_NAME_ID = 1;
|
||||
TARGET_FIELD_NAME_CREATION_DATE = 2;
|
||||
TARGET_FIELD_NAME_CHANGE_DATE = 3;
|
||||
TARGET_FIELD_NAME_NAME = 4;
|
||||
TARGET_FIELD_NAME_TARGET_TYPE = 5;
|
||||
TARGET_FIELD_NAME_URL = 6;
|
||||
TARGET_FIELD_NAME_TIMEOUT = 7;
|
||||
TARGET_FIELD_NAME_ASYNC = 8;
|
||||
TARGET_FIELD_NAME_INTERRUPT_ON_ERROR = 9;
|
||||
}
|
554
docs/docs/apis/_v3_action_service.proto
Normal file
554
docs/docs/apis/_v3_action_service.proto
Normal file
@ -0,0 +1,554 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.action.v3alpha;
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
import "zitadel/protoc_gen_zitadel/v2/options.proto";
|
||||
|
||||
import "zitadel/resources/action/v3alpha/target.proto";
|
||||
import "zitadel/resources/action/v3alpha/execution.proto";
|
||||
import "zitadel/resources/action/v3alpha/search.proto";
|
||||
import "zitadel/resources/object/v3alpha/object.proto";
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "Action Service";
|
||||
version: "3.0-alpha";
|
||||
description: "This API is intended to manage custom executions (previously known as actions) in a ZITADEL instance. It is behind the feature flag \"multitenancy_resources_api\". It will continue breaking as long as it is in alpha state.";
|
||||
contact:{
|
||||
name: "ZITADEL"
|
||||
url: "https://zitadel.com"
|
||||
email: "hi@zitadel.com"
|
||||
}
|
||||
license: {
|
||||
name: "Apache 2.0",
|
||||
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
|
||||
};
|
||||
};
|
||||
schemes: HTTPS;
|
||||
schemes: HTTP;
|
||||
|
||||
consumes: "application/json";
|
||||
consumes: "application/grpc";
|
||||
|
||||
produces: "application/json";
|
||||
produces: "application/grpc";
|
||||
|
||||
consumes: "application/grpc-web+proto";
|
||||
produces: "application/grpc-web+proto";
|
||||
|
||||
host: "$ZITADEL_DOMAIN";
|
||||
base_path: "/resources/v3alpha";
|
||||
|
||||
external_docs: {
|
||||
description: "Detailed information about ZITADEL",
|
||||
url: "https://zitadel.com/docs"
|
||||
}
|
||||
security_definitions: {
|
||||
security: {
|
||||
key: "OAuth2";
|
||||
value: {
|
||||
type: TYPE_OAUTH2;
|
||||
flow: FLOW_ACCESS_CODE;
|
||||
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
|
||||
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
|
||||
scopes: {
|
||||
scope: {
|
||||
key: "openid";
|
||||
value: "openid";
|
||||
}
|
||||
scope: {
|
||||
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
security: {
|
||||
security_requirement: {
|
||||
key: "OAuth2";
|
||||
value: {
|
||||
scope: "openid";
|
||||
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
}
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
key: "403";
|
||||
value: {
|
||||
description: "Returned when the user does not have permission to access the resource.";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/rpcStatus";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
key: "404";
|
||||
value: {
|
||||
description: "Returned when the resource does not exist.";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/rpcStatus";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
service ZITADELActions {
|
||||
|
||||
// Create a target
|
||||
//
|
||||
// Create a new target, which can be used in executions.
|
||||
rpc CreateTarget (CreateTargetRequest) returns (CreateTargetResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/targets"
|
||||
body: "target"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "action.target.write"
|
||||
}
|
||||
http_response: {
|
||||
success_code: 201
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "201";
|
||||
value: {
|
||||
description: "Target successfully created";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/v2CreateTargetResponse";
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Patch a target
|
||||
//
|
||||
// Patch an existing target.
|
||||
rpc PatchTarget (PatchTargetRequest) returns (PatchTargetResponse) {
|
||||
option (google.api.http) = {
|
||||
patch: "/targets/{id}"
|
||||
body: "target"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "action.target.write"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "Target successfully updated";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Delete a target
|
||||
//
|
||||
// Delete an existing target. This will remove it from any configured execution as well.
|
||||
rpc DeleteTarget (DeleteTargetRequest) returns (DeleteTargetResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/targets/{id}"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "action.target.delete"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "Target successfully deleted";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Target by ID
|
||||
//
|
||||
// Returns the target identified by the requested ID.
|
||||
rpc GetTarget (GetTargetRequest) returns (GetTargetResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/targets/{id}"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "action.target.read"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200"
|
||||
value: {
|
||||
description: "Target successfully retrieved";
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Search targets
|
||||
//
|
||||
// Search all matching targets. By default, we will return all targets of your instance.
|
||||
// Make sure to include a limit and sorting for pagination.
|
||||
rpc SearchTargets (SearchTargetsRequest) returns (SearchTargetsResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/targets/_search",
|
||||
body: "filters"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "action.target.read"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "A list of all targets matching the query";
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
key: "400";
|
||||
value: {
|
||||
description: "invalid list query";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/rpcStatus";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Put an execution to call a target or include the targets of another execution.
|
||||
//
|
||||
// Creates an execution for the given condition if it doesn't exists.
|
||||
// Otherwise, the existing execution is updated.
|
||||
rpc PutExecution (PutExecutionRequest) returns (PutExecutionResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/executions"
|
||||
body: "execution"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "action.execution.write"
|
||||
}
|
||||
http_response: {
|
||||
success_code: 201
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "201";
|
||||
value: {
|
||||
description: "Execution successfully created";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/v2CreateExecutionResponse";
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "Execution successfully updated";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Delete an execution
|
||||
//
|
||||
// Delete an existing execution.
|
||||
rpc DeleteExecution (DeleteExecutionRequest) returns (DeleteExecutionResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/executions/{id}"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "action.execution.delete"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "Execution successfully deleted";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Search executions
|
||||
//
|
||||
// Search all matching executions. By default, we will return all executions of your instance.
|
||||
// Depending on the ZITADEL configuration, the number of returned resources is most probably limited.
|
||||
// To make sure you get deterministic results, sort and paginate by the resources creation dates.
|
||||
rpc SearchExecutions (SearchExecutionsRequest) returns (SearchExecutionsResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/executions/_search"
|
||||
body: "filters"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "execution.read"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "A list of all executions matching the query";
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
key: "400";
|
||||
value: {
|
||||
description: "invalid list query";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/rpcStatus";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// List all available functions
|
||||
//
|
||||
// List all available functions which can be used as condition for executions.
|
||||
rpc ListAvailableExecutionFunctions (ListAvailableExecutionFunctionsRequest) returns (ListAvailableExecutionFunctionsResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/executions/functions"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "execution.read"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "List all functions successfully";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
// List all available methods
|
||||
//
|
||||
// List all available methods which can be used as condition for executions.
|
||||
rpc ListAvailableExecutionMethods (ListAvailableExecutionMethodsRequest) returns (ListAvailableExecutionMethodsResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/executions/methods"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "execution.read"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "List all methods successfully";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
// List all available service
|
||||
//
|
||||
// List all available services which can be used as condition for executions.
|
||||
rpc ListAvailableExecutionServices (ListAvailableExecutionServicesRequest) returns (ListAvailableExecutionServicesResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/executions/services"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "execution.read"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "List all services successfully";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message CreateTargetRequest {
|
||||
Target target = 2;
|
||||
}
|
||||
|
||||
message CreateTargetResponse {
|
||||
zitadel.resources.object.v3alpha.Details details = 2;
|
||||
}
|
||||
|
||||
message PatchTargetRequest {
|
||||
string id = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 200,
|
||||
example: "\"69629026806489455\"";
|
||||
}
|
||||
];
|
||||
PatchTarget target = 2;
|
||||
}
|
||||
|
||||
message PatchTargetResponse {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
}
|
||||
|
||||
message DeleteTargetRequest {
|
||||
string id = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 200,
|
||||
example: "\"69629026806489455\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message DeleteTargetResponse {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
}
|
||||
|
||||
message SearchTargetsRequest {
|
||||
// list limitations and ordering.
|
||||
zitadel.resources.object.v3alpha.ListQuery query = 2;
|
||||
// the field the result is sorted.
|
||||
zitadel.resources.action.v3alpha.TargetFieldName sorting_column = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"FIELD_NAME_SCHEMA_TYPE\""
|
||||
}
|
||||
];
|
||||
// Define the criteria to query for.
|
||||
repeated zitadel.resources.action.v3alpha.TargetSearchFilter filters = 4;
|
||||
}
|
||||
|
||||
message SearchTargetsResponse {
|
||||
zitadel.resources.object.v3alpha.ListDetails details = 1;
|
||||
zitadel.resources.action.v3alpha.TargetFieldName sorting_column = 2;
|
||||
repeated zitadel.resources.action.v3alpha.GetTarget result = 3;
|
||||
}
|
||||
|
||||
message GetTargetRequest {
|
||||
// unique identifier of the target.
|
||||
string id = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 200,
|
||||
example: "\"69629026806489455\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message GetTargetResponse {
|
||||
zitadel.resources.action.v3alpha.GetTarget target = 1;
|
||||
}
|
||||
|
||||
message PutExecutionRequest {
|
||||
Execution execution = 2;
|
||||
}
|
||||
|
||||
message PutExecutionResponse {
|
||||
zitadel.resources.object.v3alpha.Details details = 2;
|
||||
}
|
||||
|
||||
message DeleteExecutionRequest {
|
||||
string id = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 200,
|
||||
example: "\"69629026806489455\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message DeleteExecutionResponse {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
}
|
||||
|
||||
message SearchExecutionsRequest {
|
||||
// list limitations and ordering.
|
||||
zitadel.resources.object.v3alpha.ListQuery query = 1;
|
||||
// Define the criteria to query for.
|
||||
repeated zitadel.resources.action.v3alpha.ExecutionSearchFilter filters = 2;
|
||||
}
|
||||
|
||||
message SearchExecutionsResponse {
|
||||
zitadel.resources.object.v3alpha.ListDetails details = 1;
|
||||
repeated zitadel.resources.action.v3alpha.GetExecution result = 2;
|
||||
}
|
||||
|
||||
message ListAvailableExecutionFunctionsRequest{}
|
||||
message ListAvailableExecutionFunctionsResponse{
|
||||
// All available functions
|
||||
repeated string functions = 1;
|
||||
}
|
||||
message ListAvailableExecutionMethodsRequest{}
|
||||
message ListAvailableExecutionMethodsResponse{
|
||||
// All available methods
|
||||
repeated string methods = 1;
|
||||
}
|
||||
|
||||
message ListAvailableExecutionServicesRequest{}
|
||||
message ListAvailableExecutionServicesResponse{
|
||||
// All available services
|
||||
repeated string services = 1;
|
||||
}
|
94
docs/docs/apis/_v3_action_target.proto
Normal file
94
docs/docs/apis/_v3_action_target.proto
Normal file
@ -0,0 +1,94 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.action.v3alpha;
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
import "zitadel/protoc_gen_zitadel/v2/options.proto";
|
||||
|
||||
import "zitadel/resources/object/v3alpha/object.proto";
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
|
||||
|
||||
message Target {
|
||||
string name = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"ip_allow_list\"";
|
||||
}
|
||||
];
|
||||
// Defines the target type and how the response of the target is treated.
|
||||
oneof target_type {
|
||||
SetRESTWebhook rest_webhook = 4;
|
||||
SetRESTRequestResponse rest_request_response = 5;
|
||||
}
|
||||
// Timeout defines the duration until ZITADEL cancels the execution.
|
||||
google.protobuf.Duration timeout = 6 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"10s\"";
|
||||
}
|
||||
];
|
||||
oneof execution_type {
|
||||
// Set the execution to run asynchronously.
|
||||
bool is_async = 7;
|
||||
// Define if any error stops the whole execution. By default the process continues as normal.
|
||||
bool interrupt_on_error = 8;
|
||||
}
|
||||
}
|
||||
|
||||
message GetTarget {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
Target target = 2;
|
||||
}
|
||||
|
||||
message PatchTarget {
|
||||
optional string name = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"ip_allow_list\"";
|
||||
}
|
||||
];
|
||||
// Defines the target type and how the response of the target is treated.
|
||||
oneof target_type {
|
||||
SetRESTWebhook rest_webhook = 3;
|
||||
SetRESTRequestResponse rest_request_response = 4;
|
||||
}
|
||||
// Timeout defines the duration until ZITADEL cancels the execution.
|
||||
optional google.protobuf.Duration timeout = 5 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"10s\"";
|
||||
}
|
||||
];
|
||||
oneof execution_type {
|
||||
// Set the execution to run asynchronously.
|
||||
bool is_async = 6;
|
||||
// Define if any error stops the whole execution. By default the process continues as normal.
|
||||
bool interrupt_on_error = 7;
|
||||
}
|
||||
}
|
||||
|
||||
message SetRESTWebhook {
|
||||
string url = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 1000, uri: true},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 1000,
|
||||
example: "\"https://example.com/hooks/ip_check\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message SetRESTRequestResponse {
|
||||
string url = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 1000, uri: true},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 1000,
|
||||
example: "\"https://example.com/hooks/ip_check\"";
|
||||
}
|
||||
];
|
||||
}
|
94
docs/docs/apis/_v3_idp.proto
Normal file
94
docs/docs/apis/_v3_idp.proto
Normal file
@ -0,0 +1,94 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.idp.v3alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/idp/v3alpha;idp";
|
||||
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
import "zitadel/resources/object/v3alpha/object.proto";
|
||||
|
||||
message IDP {
|
||||
string name = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"GitLab\"";
|
||||
}
|
||||
];
|
||||
zitadel.resources.object.v3alpha.StatePolicy state_policy = 2;
|
||||
Options options = 3;
|
||||
}
|
||||
|
||||
message PatchIDP {
|
||||
optional string name = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"GitLab\"";
|
||||
}
|
||||
];
|
||||
optional zitadel.resources.object.v3alpha.StatePolicy state_policy = 2;
|
||||
optional Options options = 3;
|
||||
}
|
||||
|
||||
|
||||
message GetIDP {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
optional zitadel.resources.object.v3alpha.Parent parent = 2;
|
||||
zitadel.resources.object.v3alpha.State state = 3;
|
||||
ProviderType type = 4;
|
||||
IDP idp = 5;
|
||||
}
|
||||
|
||||
enum ProviderType {
|
||||
PROVIDER_TYPE_UNSPECIFIED = 0;
|
||||
PROVIDER_TYPE_OIDC = 1;
|
||||
PROVIDER_TYPE_JWT = 2;
|
||||
PROVIDER_TYPE_LDAP = 3;
|
||||
PROVIDER_TYPE_OAUTH = 4;
|
||||
PROVIDER_TYPE_AZURE_AD = 5;
|
||||
PROVIDER_TYPE_GITHUB = 6;
|
||||
PROVIDER_TYPE_GITHUB_ES = 7;
|
||||
PROVIDER_TYPE_GITLAB = 8;
|
||||
PROVIDER_TYPE_GITLAB_SELF_HOSTED = 9;
|
||||
PROVIDER_TYPE_GOOGLE = 10;
|
||||
PROVIDER_TYPE_APPLE = 11;
|
||||
PROVIDER_TYPE_SAML = 12;
|
||||
}
|
||||
|
||||
|
||||
enum AutoLinkingOption {
|
||||
// AUTO_LINKING_OPTION_UNSPECIFIED disables the auto linking prompt.
|
||||
AUTO_LINKING_OPTION_UNSPECIFIED = 0;
|
||||
// AUTO_LINKING_OPTION_USERNAME will use the username of the external user to check for a corresponding ZITADEL user.
|
||||
AUTO_LINKING_OPTION_USERNAME = 1;
|
||||
// AUTO_LINKING_OPTION_EMAIL will use the email of the external user to check for a corresponding ZITADEL user with the same verified email
|
||||
// Note that in case multiple users match, no prompt will be shown.
|
||||
AUTO_LINKING_OPTION_EMAIL = 2;
|
||||
}
|
||||
|
||||
message Options {
|
||||
bool is_linking_allowed = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "Enable if users should be able to link an existing ZITADEL user with an external account.";
|
||||
}
|
||||
];
|
||||
bool is_creation_allowed = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "Enable if users should be able to create a new account in ZITADEL when using an external account.";
|
||||
}
|
||||
];
|
||||
bool is_auto_creation = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "Enable if a new account in ZITADEL should be created automatically when login with an external account.";
|
||||
}
|
||||
];
|
||||
bool is_auto_update = 4 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "Enable if a the ZITADEL account fields should be updated automatically on each login.";
|
||||
}
|
||||
];
|
||||
AutoLinkingOption auto_linking = 5 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "Enable if users should get prompted to link an existing ZITADEL user to an external account if the selected attribute matches.";
|
||||
}
|
||||
];
|
||||
}
|
59
docs/docs/apis/_v3_idp_gitlab.proto
Normal file
59
docs/docs/apis/_v3_idp_gitlab.proto
Normal file
@ -0,0 +1,59 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.idp.v3alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/idp/v3alpha;idp";
|
||||
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
import "zitadel/resources/object/v3alpha/object.proto";
|
||||
import "zitadel/resources/idp/v3alpha/idp.proto";
|
||||
|
||||
message GetGitLabIDP {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
optional zitadel.resources.object.v3alpha.Parent parent = 2;
|
||||
zitadel.resources.object.v3alpha.State state = 3;
|
||||
ProviderType type = 4;
|
||||
GitLabIDP idp = 5;
|
||||
}
|
||||
|
||||
message GitLabIDP {
|
||||
IDP idp = 1;
|
||||
GitLabConfig config = 2;
|
||||
}
|
||||
|
||||
message PatchGitLabIDP {
|
||||
optional PatchIDP idp = 1;
|
||||
optional PatchGitLabConfig config = 2;
|
||||
}
|
||||
|
||||
message GitLabConfig {
|
||||
string client_id = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"client-id\"";
|
||||
description: "client id of the GitLab application";
|
||||
}
|
||||
];
|
||||
repeated string scopes = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "[\"openid\", \"profile\", \"email\"]";
|
||||
description: "the scopes requested by ZITADEL during the request to GitLab";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message PatchGitLabConfig {
|
||||
optional string client_id = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"client-id\"";
|
||||
description: "client id of the GitLab application";
|
||||
}
|
||||
];
|
||||
repeated string scopes = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "[\"openid\", \"profile\", \"email\"]";
|
||||
description: "the scopes requested by ZITADEL during the request to GitLab";
|
||||
}
|
||||
];
|
||||
}
|
47
docs/docs/apis/_v3_idp_search.proto
Normal file
47
docs/docs/apis/_v3_idp_search.proto
Normal file
@ -0,0 +1,47 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.idp.v3alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/idp/v3alpha;idp";
|
||||
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
import "zitadel/resources/object/v3alpha/object.proto";
|
||||
|
||||
enum IDPFieldName {
|
||||
IDP_FIELD_NAME_UNSPECIFIED = 0;
|
||||
IDP_FIELD_NAME_NAME = 1;
|
||||
}
|
||||
|
||||
message IDPSearchFilter {
|
||||
oneof filter {
|
||||
IDPIDFilter id = 1;
|
||||
IDPNameFilter name = 2;
|
||||
resources.object.v3alpha.StateFilter state = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message IDPIDFilter {
|
||||
string id = 1 [
|
||||
(validate.rules).string = {max_len: 200},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"69629023906488334\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message IDPNameFilter {
|
||||
string name = 1 [
|
||||
(validate.rules).string = {max_len: 200},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"google\"";
|
||||
}
|
||||
];
|
||||
zitadel.resources.object.v3alpha.TextFilterMethod method = 2 [
|
||||
(validate.rules).enum.defined_only = true,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "defines which text equality method is used";
|
||||
}
|
||||
];
|
||||
}
|
325
docs/docs/apis/_v3_idp_service.proto
Normal file
325
docs/docs/apis/_v3_idp_service.proto
Normal file
@ -0,0 +1,325 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.idp.v3alpha;
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
import "zitadel/protoc_gen_zitadel/v2/options.proto";
|
||||
|
||||
import "zitadel/resources/object/v3alpha/object.proto";
|
||||
import "zitadel/resources/idp/v3alpha/search.proto";
|
||||
import "zitadel/resources/idp/v3alpha/idp.proto";
|
||||
import "zitadel/resources/idp/v3alpha/gitlab.proto";
|
||||
import "zitadel/object/v3alpha/object.proto";
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/idp/v3alpha;idp";
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "Identity Provider Service";
|
||||
version: "3.0-alpha";
|
||||
description: "This API is intended to manage identity providers (IDPs). IDPs can be created for specific organizations or for an instance. IDPs created on an instance can be activated (reused) or deactivated in organizations. It is behind the feature flag \"multitenancy_resources_api\". It will continue breaking as long as it is in alpha state.";
|
||||
contact:{
|
||||
name: "ZITADEL"
|
||||
url: "https://zitadel.com"
|
||||
email: "hi@zitadel.com"
|
||||
}
|
||||
license: {
|
||||
name: "Apache 2.0",
|
||||
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
|
||||
};
|
||||
};
|
||||
schemes: HTTPS;
|
||||
schemes: HTTP;
|
||||
|
||||
consumes: "application/json";
|
||||
consumes: "application/grpc";
|
||||
|
||||
produces: "application/json";
|
||||
produces: "application/grpc";
|
||||
|
||||
consumes: "application/grpc-web+proto";
|
||||
produces: "application/grpc-web+proto";
|
||||
|
||||
host: "$ZITADEL_DOMAIN";
|
||||
base_path: "/resources/v3alpha";
|
||||
|
||||
external_docs: {
|
||||
description: "Detailed information about ZITADEL",
|
||||
url: "https://zitadel.com/docs"
|
||||
}
|
||||
security_definitions: {
|
||||
security: {
|
||||
key: "OAuth2";
|
||||
value: {
|
||||
type: TYPE_OAUTH2;
|
||||
flow: FLOW_ACCESS_CODE;
|
||||
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
|
||||
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
|
||||
scopes: {
|
||||
scope: {
|
||||
key: "openid";
|
||||
value: "openid";
|
||||
}
|
||||
scope: {
|
||||
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
security: {
|
||||
security_requirement: {
|
||||
key: "OAuth2";
|
||||
value: {
|
||||
scope: "openid";
|
||||
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
}
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
key: "403";
|
||||
value: {
|
||||
description: "Returned when the user does not have permission to access the resource.";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/rpcStatus";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
key: "404";
|
||||
value: {
|
||||
description: "Returned when the resource does not exist.";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/rpcStatus";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
service ZITADELIdentityProviders {
|
||||
|
||||
// Create a GitLab IDP
|
||||
rpc CreateGitLabIDP (CreateGitLabIDPRequest) returns (CreateGitLabIDPResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/idps/gitlab"
|
||||
body: "idp"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "idp.write"
|
||||
}
|
||||
http_response: {
|
||||
success_code: 201
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "201";
|
||||
value: {
|
||||
description: "GitLabIDP successfully created";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/v2CreateGitLabIDPResponse";
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Patch a GitLab IDP
|
||||
rpc PatchGitLabIDP (PatchGitLabIDPRequest) returns (PatchGitLabIDPResponse) {
|
||||
option (google.api.http) = {
|
||||
patch: "/idps/gitlab/{id}"
|
||||
body: "idp"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "idp.write"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "GitLabIDP successfully updated";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Find a GitLab IDP by ID
|
||||
rpc GetGitLabIDP (GetGitLabIDPRequest) returns (GetGitLabIDPResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/idps/gitlab/{id}"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "idp.read"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200"
|
||||
value: {
|
||||
description: "GitLabIDP successfully retrieved";
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Delete an IDP of any type
|
||||
rpc DeleteIDP (DeleteIDPRequest) returns (DeleteIDPResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/idps/{id}"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "idp.delete"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "Identity provider successfully deleted";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Search IDPs
|
||||
//
|
||||
// Search all matching IDPs. By default, all instance-level and organization-level providers of all types are returned.
|
||||
// Only type-agnostic properties are returned in the response.
|
||||
// To get the full details of a specific IDP, use the specific types Get method.
|
||||
// If you search by passing an organization context, the state and the state policy might be different than if you search within the default instance-level context.
|
||||
// Make sure to include a limit and sorting for pagination.
|
||||
rpc SearchIDPs (SearchIDPsRequest) returns (SearchIDPsResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/idps/_search",
|
||||
body: "filters"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "idp.read"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
responses: {
|
||||
key: "200";
|
||||
value: {
|
||||
description: "A list of all IDPs matching the query";
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
key: "400";
|
||||
value: {
|
||||
description: "invalid list query";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/rpcStatus";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message CreateGitLabIDPRequest {
|
||||
optional zitadel.object.v3alpha.RequestContext ctx = 1;
|
||||
GitLabIDP idp = 2;
|
||||
}
|
||||
|
||||
message CreateGitLabIDPResponse {
|
||||
zitadel.resources.object.v3alpha.Details details = 2;
|
||||
}
|
||||
|
||||
message PatchGitLabIDPRequest {
|
||||
string id = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 200,
|
||||
example: "\"69629026806489455\"";
|
||||
}
|
||||
];
|
||||
PatchGitLabIDP idp = 2;
|
||||
}
|
||||
|
||||
message PatchGitLabIDPResponse {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
}
|
||||
|
||||
message DeleteIDPRequest {
|
||||
string id = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 200,
|
||||
example: "\"69629026806489455\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message DeleteIDPResponse {
|
||||
zitadel.resources.object.v3alpha.Details details = 1;
|
||||
}
|
||||
|
||||
message SearchIDPsRequest {
|
||||
optional zitadel.object.v3alpha.RequestContext ctx = 1;
|
||||
// list limitations and ordering.
|
||||
zitadel.resources.object.v3alpha.ListQuery query = 2;
|
||||
// the field the result is sorted.
|
||||
zitadel.resources.idp.v3alpha.IDPFieldName sorting_column = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"FIELD_NAME_SCHEMA_TYPE\""
|
||||
}
|
||||
];
|
||||
repeated zitadel.resources.idp.v3alpha.IDPSearchFilter filters = 4;
|
||||
}
|
||||
|
||||
message SearchIDPsResponse {
|
||||
zitadel.resources.object.v3alpha.ListDetails details = 1;
|
||||
zitadel.resources.idp.v3alpha.IDPFieldName sorting_column = 2;
|
||||
repeated zitadel.resources.idp.v3alpha.GetIDP result = 3;
|
||||
}
|
||||
|
||||
message GetGitLabIDPRequest {
|
||||
string id = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
min_length: 1,
|
||||
max_length: 200,
|
||||
example: "\"69629026806489455\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message GetGitLabIDPResponse {
|
||||
zitadel.resources.idp.v3alpha.GetGitLabIDP idp = 1;
|
||||
}
|
69
docs/docs/apis/_v3_language.proto
Normal file
69
docs/docs/apis/_v3_language.proto
Normal file
@ -0,0 +1,69 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.settings.language.v3alpha;
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/settings/language/v3alpha;language";
|
||||
|
||||
import "validate/validate.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
|
||||
import "zitadel/settings/object/v3alpha/object.proto";
|
||||
import "zitadel/object/v3alpha/object.proto";
|
||||
|
||||
message SetLanguageSettings {
|
||||
optional zitadel.settings.object.v3alpha.Language default_language = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "default language for the current context"
|
||||
example: "\"en\""
|
||||
}
|
||||
];
|
||||
optional SetLanguages restricted_languages = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "To these languages, message texts and default login UI labels are translated to. Also, the discovery endpoint only lists these languages."
|
||||
example: "[\"en\", \"de\"]"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message ResolvedLanguageSettings {
|
||||
zitadel.settings.object.v3alpha.ResolvedString default_language = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "default language for the current context"
|
||||
example: "\"en\""
|
||||
}
|
||||
];
|
||||
ResolvedLanguages restricted_languages = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "To these languages, message texts and default login UI labels are translated to. Also, the discovery endpoint only lists these languages."
|
||||
example: "[\"en\", \"de\"]"
|
||||
}
|
||||
];
|
||||
ResolvedLanguages supported_languages = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "These languages are supported by the system. For simplicity, the field is of type ResolvedLanguages, even though the list is immutable and the owner is always of OWNER_TYPE_SYSTEM."
|
||||
example: "[\"en\", \"de\", \"it\"]"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message SetLanguages {
|
||||
repeated zitadel.settings.object.v3alpha.Language languages = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "List of languages to set"
|
||||
example: "[\"en\", \"de\"]"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message ResolvedLanguages {
|
||||
repeated zitadel.settings.object.v3alpha.Language value = 1[
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "List of languages"
|
||||
example: "[\"en\", \"de\"]"
|
||||
}
|
||||
];
|
||||
optional zitadel.object.v3alpha.Owner owner = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If the value is inherited, the value is inherited from this owner.";
|
||||
}
|
||||
];
|
||||
}
|
158
docs/docs/apis/_v3_language_service.proto
Normal file
158
docs/docs/apis/_v3_language_service.proto
Normal file
@ -0,0 +1,158 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.settings.language.v3alpha;
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/settings/language/v3alpha;language";
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
|
||||
import "zitadel/object/v3alpha/object.proto";
|
||||
import "zitadel/settings/object/v3alpha/object.proto";
|
||||
import "zitadel/settings/language/v3alpha/language.proto";
|
||||
import "zitadel/protoc_gen_zitadel/v2/options.proto";
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "Language Settings Service";
|
||||
version: "3.0-alpha";
|
||||
description: "Language Service is intended to manage languages for ZITADEL. Enable the feature flag \"multitenancy_settings\" in order to activate it. Languages are settings, and are therefore inherited through the context hierarchy system -> instance -> org. It will continue breaking as long as it is in alpha state.";
|
||||
contact:{
|
||||
name: "ZITADEL"
|
||||
url: "https://zitadel.com"
|
||||
email: "hi@zitadel.com"
|
||||
}
|
||||
license: {
|
||||
name: "Apache 2.0",
|
||||
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
|
||||
};
|
||||
};
|
||||
schemes: HTTPS;
|
||||
schemes: HTTP;
|
||||
|
||||
consumes: "application/json";
|
||||
consumes: "application/grpc";
|
||||
consumes: "application/grpc-web+proto";
|
||||
|
||||
produces: "application/json";
|
||||
produces: "application/grpc";
|
||||
produces: "application/grpc-web+proto";
|
||||
|
||||
host: "$ZITADEL_DOMAIN";
|
||||
base_path: "/settings/v3alpha";
|
||||
|
||||
external_docs: {
|
||||
description: "Detailed information about ZITADEL",
|
||||
url: "https://zitadel.com/docs"
|
||||
}
|
||||
security_definitions: {
|
||||
security: {
|
||||
key: "OAuth2";
|
||||
value: {
|
||||
type: TYPE_OAUTH2;
|
||||
flow: FLOW_ACCESS_CODE;
|
||||
authorization_url: "$ZITADEL_DOMAIN/oauth/v2/authorize";
|
||||
token_url: "$ZITADEL_DOMAIN/oauth/v2/token";
|
||||
scopes: {
|
||||
scope: {
|
||||
key: "openid";
|
||||
value: "openid";
|
||||
}
|
||||
scope: {
|
||||
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
security: {
|
||||
security_requirement: {
|
||||
key: "OAuth2";
|
||||
value: {
|
||||
scope: "openid";
|
||||
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
|
||||
}
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
key: "403";
|
||||
value: {
|
||||
description: "Returned when the user does not have permission to access the settings in the given context.";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "#/definitions/rpcStatus";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ZITADELLanguageSettings is intended to manage languages for ZITADEL.
|
||||
// Enable the feature flag \"multitenancy_settings\" in order to activate it.
|
||||
// Languages are settings, and are therefore inherited through the context hierarchy system -> instance -> org.
|
||||
service ZITADELLanguageSettings {
|
||||
rpc SetLanguages (SetLanguageSettingsRequest) returns (SetLanguageSettingsResponse) {
|
||||
option (google.api.http) = {
|
||||
patch: "/languages"
|
||||
body: "settings"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "authenticated"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
summary: "Set languages for a given context";
|
||||
description: "Configure and set languages for a given context. Only fields present in the request are set or unset."
|
||||
responses: {
|
||||
key: "200"
|
||||
value: {
|
||||
description: "OK";
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
rpc ResolveLanguages (ResolveLanguageSettingsRequest) returns (ResolveLanguageSettingsResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/languages"
|
||||
};
|
||||
|
||||
option (zitadel.protoc_gen_zitadel.v2.options) = {
|
||||
auth_option: {
|
||||
permission: "authenticated"
|
||||
}
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
summary: "Get the languages in the given context";
|
||||
description: "Returns all configured and inherited languages for the given context."
|
||||
responses: {
|
||||
key: "200"
|
||||
value: {
|
||||
description: "OK";
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
message SetLanguageSettingsRequest{
|
||||
optional zitadel.object.v3alpha.RequestContext ctx = 1;
|
||||
SetLanguageSettings settings = 2;
|
||||
}
|
||||
|
||||
message SetLanguageSettingsResponse{
|
||||
zitadel.settings.object.v3alpha.Details details = 1;
|
||||
}
|
||||
|
||||
message ResolveLanguageSettingsRequest{
|
||||
optional zitadel.object.v3alpha.RequestContext ctx = 1;
|
||||
}
|
||||
|
||||
message ResolveLanguageSettingsResponse{
|
||||
zitadel.settings.object.v3alpha.Details details = 1;
|
||||
ResolvedLanguageSettings settings = 2;
|
||||
}
|
33
docs/docs/apis/_v3_object.proto
Normal file
33
docs/docs/apis/_v3_object.proto
Normal file
@ -0,0 +1,33 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.object.v3alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/object/v3alpha;object";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
message RequestContext {
|
||||
// By default, the request context is set to the instance discovered by the domain from the requests host header.
|
||||
oneof owner {
|
||||
bool system = 1 [(validate.rules).bool = {const: true}]; // TODO: move the source of truth from the defaults.yaml into the database
|
||||
string instance_id = 2;
|
||||
string instance_domain = 3;
|
||||
string org_id = 4;
|
||||
string org_domain = 5;
|
||||
}
|
||||
}
|
||||
|
||||
enum OwnerType {
|
||||
OWNER_TYPE_UNSPECIFIED = 0;
|
||||
OWNER_TYPE_SYSTEM = 1; // TODO: move the source of truth from the defaults.yaml into the database
|
||||
OWNER_TYPE_INSTANCE = 2;
|
||||
OWNER_TYPE_ORG = 3;
|
||||
}
|
||||
|
||||
message Owner {
|
||||
OwnerType type = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
155
docs/docs/apis/_v3_resource_object.proto
Normal file
155
docs/docs/apis/_v3_resource_object.proto
Normal file
@ -0,0 +1,155 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.resources.object.v3alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/object/v3alpha;object";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
import "zitadel/object/v3alpha/object.proto";
|
||||
|
||||
message Organization {
|
||||
oneof org {
|
||||
string org_id = 1;
|
||||
string org_domain = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message Details {
|
||||
string id = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"69629012906488334\"";
|
||||
}
|
||||
];
|
||||
|
||||
//sequence represents the order of events. It's always counting
|
||||
//
|
||||
// on read: the sequence of the last event reduced by the projection
|
||||
//
|
||||
// on manipulation: the timestamp of the event(s) added by the manipulation
|
||||
uint64 sequence = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"2\"";
|
||||
}
|
||||
];
|
||||
//change_date is the timestamp when the object was changed
|
||||
//
|
||||
// on read: the timestamp of the last event reduced by the projection
|
||||
//
|
||||
// on manipulation: the timestamp of the event(s) added by the manipulation
|
||||
google.protobuf.Timestamp change_date = 3;
|
||||
//resource_owner represents the context an object belongs to
|
||||
zitadel.object.v3alpha.Owner resource_owner = 4 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"69629023906488334\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
enum State {
|
||||
EFFECTIVE_STATE_UNSPECIFIED = 0;
|
||||
EFFECTIVE_STATE_ACTIVE = 1;
|
||||
EFFECTIVE_STATE_INACTIVE = 2;
|
||||
}
|
||||
|
||||
enum StatePolicy {
|
||||
STATE_POLICY_UNSPECIFIED = 0;
|
||||
STATE_POLICY_ACTIVATE = 1;
|
||||
STATE_POLICY_DEACTIVATE = 2;
|
||||
STATE_POLICY_INHERIT = 3;
|
||||
}
|
||||
|
||||
message StateFilter {
|
||||
// Defines the state to query for.
|
||||
resources.object.v3alpha.State state = 1 [
|
||||
(validate.rules).enum.defined_only = true,
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"STATE_ACTIVE\""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message Parent {
|
||||
zitadel.object.v3alpha.Owner parent = 1;
|
||||
State state = 2;
|
||||
}
|
||||
|
||||
message ListQuery {
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
|
||||
json_schema: {
|
||||
title: "General List Query"
|
||||
description: "Object unspecific list filters like offset, limit and asc/desc."
|
||||
}
|
||||
};
|
||||
uint64 offset = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"0\"";
|
||||
}
|
||||
];
|
||||
uint32 limit = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "100";
|
||||
description: "Maximum amount of events returned. The default is 100, the maximum is 1000. If the limit exceeds the maximum, ZITADEL throws an error.";
|
||||
}
|
||||
];
|
||||
bool asc = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "default is descending"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message ListDetails {
|
||||
uint32 applied_limit = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "100";
|
||||
}
|
||||
];
|
||||
bool end_of_list = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "true";
|
||||
}
|
||||
];
|
||||
uint64 total_result = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"2\"";
|
||||
}
|
||||
];
|
||||
uint64 processed_sequence = 4 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"267831\"";
|
||||
}
|
||||
];
|
||||
google.protobuf.Timestamp timestamp = 5 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "the last time the projection got updated"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
enum TextFilterMethod {
|
||||
TEXT_FILTER_METHOD_EQUALS = 0;
|
||||
TEXT_FILTER_METHOD_EQUALS_IGNORE_CASE = 1;
|
||||
TEXT_FILTER_METHOD_STARTS_WITH = 2;
|
||||
TEXT_FILTER_METHOD_STARTS_WITH_IGNORE_CASE = 3;
|
||||
TEXT_FILTER_METHOD_CONTAINS = 4;
|
||||
TEXT_FILTER_METHOD_CONTAINS_IGNORE_CASE = 5;
|
||||
TEXT_FILTER_METHOD_ENDS_WITH = 6;
|
||||
TEXT_FILTER_METHOD_ENDS_WITH_IGNORE_CASE = 7;
|
||||
}
|
||||
|
||||
enum ListFilterMethod {
|
||||
LIST_FILTER_METHOD_IN = 0;
|
||||
}
|
||||
|
||||
enum TimestampFilterMethod {
|
||||
TIMESTAMP_Filter_METHOD_EQUALS = 0;
|
||||
TIMESTAMP_Filter_METHOD_GREATER = 1;
|
||||
TIMESTAMP_Filter_METHOD_GREATER_OR_EQUALS = 2;
|
||||
TIMESTAMP_Filter_METHOD_LESS = 3;
|
||||
TIMESTAMP_Filter_METHOD_LESS_OR_EQUALS = 4;
|
||||
}
|
193
docs/docs/apis/_v3_settings_object.proto
Normal file
193
docs/docs/apis/_v3_settings_object.proto
Normal file
@ -0,0 +1,193 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.settings.object.v3alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/settings/object/v3alpha;object";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
|
||||
import "zitadel/object/v3alpha/object.proto";
|
||||
|
||||
message Details {
|
||||
//sequence represents the order of events. It's always counting
|
||||
//
|
||||
// on read: the sequence of the last event reduced by the projection
|
||||
//
|
||||
// on manipulation: the timestamp of the event(s) added by the manipulation
|
||||
uint64 sequence = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"2\"";
|
||||
}
|
||||
];
|
||||
//change_date is the timestamp when the object was changed
|
||||
//
|
||||
// on read: the timestamp of the last event reduced by the projection
|
||||
//
|
||||
// on manipulation: the timestamp of the event(s) added by the manipulation
|
||||
google.protobuf.Timestamp change_date = 2;
|
||||
//resource_owner represents the context an object belongs to
|
||||
zitadel.object.v3alpha.Owner owner = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"69629023906488334\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
message ResolvedBool {
|
||||
bool value = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "false";
|
||||
description: "The resolved value is valid for the given context. Either the value was explicitly set for the given context or it is inherited from a higher-level context.";
|
||||
}
|
||||
];
|
||||
optional zitadel.object.v3alpha.Owner owner = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If the value is inherited, the value is inherited from this owner.";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message SetBool {
|
||||
oneof value {
|
||||
bool set = 1;
|
||||
bool reset = 2 [(validate.rules).bool = {
|
||||
const: true
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
message ResolvedString {
|
||||
string value = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"a resolved string\"";
|
||||
description: "The resolved value is valid for the given context. Either the value was explicitly set for the given context or it is inherited from a higher-level context.";
|
||||
}
|
||||
];
|
||||
optional zitadel.object.v3alpha.Owner owner = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If the value is inherited, the value is inherited from this owner.";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message SetString {
|
||||
oneof value {
|
||||
string set = 1 [
|
||||
(validate.rules).string = {
|
||||
max_len: 256
|
||||
}
|
||||
];
|
||||
bool reset = 2 [(validate.rules).bool = {
|
||||
const: true
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
message SetStringLong {
|
||||
oneof value {
|
||||
string set = 1 [
|
||||
(validate.rules).string = {
|
||||
max_len: 2048
|
||||
}
|
||||
];
|
||||
bool reset = 2 [(validate.rules).bool = {
|
||||
const: true
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
message SetStringShort {
|
||||
oneof value {
|
||||
string set = 1 [
|
||||
(validate.rules).string = {
|
||||
max_len: 64
|
||||
}
|
||||
];
|
||||
bool reset = 2 [(validate.rules).bool = {
|
||||
const: true
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
message Language {
|
||||
string key = 1 [(validate.rules).string = {pattern: "^[a-z]{2}$"}];
|
||||
}
|
||||
|
||||
message ResolvedStrings {
|
||||
repeated string value = 1[
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "[\"a\", \"resolved\", \"list\", \"of\", \"strings\"]";
|
||||
description: "The resolved value is valid for the given context. Either the value was explicitly set for the given context or it is inherited from a higher-level context.";
|
||||
}
|
||||
];
|
||||
optional zitadel.object.v3alpha.Owner owner = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If the value is inherited, the value is inherited from this owner.";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message SetStrings {
|
||||
oneof value {
|
||||
SetStringsValue set = 1;
|
||||
bool reset = 2 [(validate.rules).bool = {
|
||||
const: true
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
message SetStringsValue {
|
||||
repeated string value = 1;
|
||||
}
|
||||
|
||||
message ResolvedUInt64 {
|
||||
uint64 value = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "1000";
|
||||
description: "The resolved value is valid for the given context. Either the value was explicitly set for the given context or it is inherited from a higher-level context.";
|
||||
}
|
||||
];
|
||||
optional zitadel.object.v3alpha.Owner owner = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If the value is inherited, the value is inherited from this owner.";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message SetUInt64 {
|
||||
oneof value {
|
||||
uint64 set = 1;
|
||||
bool reset = 2 [(validate.rules).bool = {
|
||||
const: true
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
message ResolvedDuration {
|
||||
google.protobuf.Duration value = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"5s\"";
|
||||
description: "The resolved value is valid for the given context. Either the value was explicitly set for the given context or it is inherited from a higher-level context.";
|
||||
}
|
||||
];
|
||||
optional zitadel.object.v3alpha.Owner owner = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If the value is inherited, the value is inherited from this owner.";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message SetDuration {
|
||||
oneof value {
|
||||
google.protobuf.Duration set = 1;
|
||||
bool reset = 2 [(validate.rules).bool = {
|
||||
const: true
|
||||
}];
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ Please check below the matrix for an overview where which scope is asserted.
|
||||
| phone_verified | When requested | When requested | When requested and response_type `id_token` | No |
|
||||
| preferred_username (username when Introspect) | When requested | When requested | Yes | No |
|
||||
| sub | Yes | Yes | Yes | When JWT |
|
||||
| urn:zitadel:iam:org:domain:primary:{domainname} | When requested | When requested | When requested | When JWT and requested |
|
||||
| urn:zitadel:iam:org:domain:primary:\{domainname} | When requested | When requested | When requested | When JWT and requested |
|
||||
| urn:zitadel:iam:org:project:roles | When requested | When requested | When requested or configured | When JWT and requested or configured |
|
||||
| urn:zitadel:iam:user:metadata | When requested | When requested | When requested | When JWT and requested |
|
||||
| urn:zitadel:iam:user:resourceowner:id | When requested | When requested | When requested | When JWT and requested |
|
||||
@ -101,11 +101,11 @@ ZITADEL reserves some claims to assert certain data. Please check out the [reser
|
||||
|
||||
| Claims | Example | Description |
|
||||
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| urn:zitadel:iam:action:{actionname}:log | `{"urn:zitadel:iam:action:appendCustomClaims:log": ["test log", "another test log"]}` | This claim is set during Actions as a log, e.g. if two custom claims with the same keys are set. |
|
||||
| urn:zitadel:iam:org:domain:primary:{domainname} | `{"urn:zitadel:iam:org:domain:primary": "acme.ch"}` | This claim represents the primary domain of the organization the user belongs to. |
|
||||
| urn:zitadel:iam:action:\{actionname}:log | `{"urn:zitadel:iam:action:appendCustomClaims:log": ["test log", "another test log"]}` | This claim is set during Actions as a log, e.g. if two custom claims with the same keys are set. |
|
||||
| urn:zitadel:iam:org:domain:primary:\{domainname} | `{"urn:zitadel:iam:org:domain:primary": "acme.ch"}` | This claim represents the primary domain of the organization the user belongs to. |
|
||||
| urn:zitadel:iam:org:project:roles | `{"urn:zitadel:iam:org:project:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role on the current project (where your client belongs to). |
|
||||
| urn:zitadel:iam:org:project:{projectid}:roles | `{"urn:zitadel:iam:org:project:id3:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role on a specific project. |
|
||||
| urn:zitadel:iam:roles:{rolename} | TBA | TBA |
|
||||
| urn:zitadel:iam:org:project:\{projectid}:roles | `{"urn:zitadel:iam:org:project:id3:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role on a specific project. |
|
||||
| urn:zitadel:iam:roles:\{rolename} | TBA | TBA |
|
||||
| urn:zitadel:iam:user:metadata | `{"urn:zitadel:iam:user:metadata": [ {"key": "VmFsdWU=" } ] }` | The metadata claim will include all metadata of a user. The values are base64 encoded. |
|
||||
| urn:zitadel:iam:user:resourceowner:id | `{"urn:zitadel:iam:user:resourceowner:id": "orgid"}` | This claim represents the id of the resource owner organisation of the user. |
|
||||
| urn:zitadel:iam:user:resourceowner:name | `{"urn:zitadel:iam:user:resourceowner:name": "ACME"}` | This claim represents the name of the resource owner organisation of the user. |
|
||||
|
@ -12,13 +12,13 @@ import TokenExchangeTypes from "./_token_exchange_types.mdx";
|
||||
## OpenID Connect 1.0 Discovery
|
||||
|
||||
The OpenID Connect Discovery Endpoint is located within the issuer domain.
|
||||
This would give us {your_domain}/.well-known/openid-configuration.
|
||||
This would give us `{your_domain}/.well-known/openid-configuration`.
|
||||
|
||||
**Link to spec.** [OpenID Connect Discovery 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-discovery-1_0.html)
|
||||
|
||||
## authorization_endpoint
|
||||
|
||||
{your_domain}/oauth/v2/authorize
|
||||
`{your_domain}/oauth/v2/authorize`
|
||||
|
||||
:::note
|
||||
The authorization_endpoint is located with the login page, due to the need of accessing the same cookie domain
|
||||
@ -104,6 +104,22 @@ no additional parameters required
|
||||
| prompt | If the Auth Server prompts the user for (re)authentication. <br />no prompt: the user will have to choose a session if more than one session exists<br />`none`: user must be authenticated without interaction, an error is returned otherwise <br />`login`: user must reauthenticate / provide a user name <br />`select_account`: user is prompted to select one of the existing sessions or create a new one <br />`create`: the registration form will be displayed to the user directly |
|
||||
| state | Opaque value used to maintain state between the request and the callback. Used for Cross-Site Request Forgery (CSRF) mitigation as well, therefore highly **recommended**. |
|
||||
| ui_locales | Spaces delimited list of preferred locales for the login UI, e.g. `de-CH de en`. If none is provided or matches the possible locales provided by the login UI, the `accept-language` header of the browser will be taken into account. |
|
||||
| response_mode | The mechanism to be used for returning parameters to the application. See [response modes](#response-modes) for valid values. Invalid values are ignored. |
|
||||
|
||||
#### Response modes
|
||||
|
||||
ZITADEL supports the following `response_mode` values. When no response mode is requested, the response mode is choosen based on the configured Response Type of the application.
|
||||
As per [OpenID Connect Core 1.0, Section 3.1.2.1](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest):
|
||||
|
||||
> The use of this parameter is NOT RECOMMENDED when the Response Mode that would be requested is the default mode specified for the Response Type.
|
||||
|
||||
| Response Mode | Description |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| query | Encode the returned parameters in the URL query string. This is the default when the Response type is `code`, for example [Web applications](/docs/guides/manage/console/applications#web). |
|
||||
| fragment | Encode the returned parameters in the URL fragment. This is the default when the Response Type is `id_token`, for example implicit [User Agent apps](/docs/guides/manage/console/applications#user-agent). This mode will not work for server-side applications, because fragments are never sent by the browser to the server. |
|
||||
| form_post[^1] | ZITADEL serves a small JavaScript to the browser which will send the returned parameters to the `redirect_uri` using HTTP POST. This mode only works for server-side applications and user agents which support / allow JavaScript. |
|
||||
|
||||
[^1]: Implements [OAuth 2.0 Form Post Response Mode](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)
|
||||
|
||||
### Successful code response
|
||||
|
||||
@ -156,7 +172,7 @@ the error will be display directly to the user on the auth server
|
||||
|
||||
## token_endpoint
|
||||
|
||||
{your_domain}/oauth/v2/token
|
||||
`{your_domain}/oauth/v2/token`
|
||||
|
||||
The token_endpoint will as the name suggests return various tokens (access, id and refresh) depending on the used `grant_type`.
|
||||
When using [`authorization_code`](#authorization-code-grant-code-exchange) flow call this endpoint after receiving the code from the authorization_endpoint.
|
||||
@ -455,7 +471,7 @@ Send a `client_assertion` as JWT for us to validate the signature against the re
|
||||
|
||||
## introspection_endpoint
|
||||
|
||||
{your_domain}/oauth/v2/introspect
|
||||
`{your_domain}/oauth/v2/introspect`
|
||||
|
||||
This endpoint enables clients to validate an `acccess_token`, either opaque or JWT. Unlike client side JWT validation,
|
||||
this endpoint will check if the token is not revoked (by client or logout).
|
||||
@ -538,7 +554,7 @@ If the authorization fails, an HTTP 401 with `invalid_client` will be returned.
|
||||
|
||||
## userinfo_endpoint
|
||||
|
||||
{your_domain}/oidc/v1/userinfo
|
||||
`{your_domain}/oidc/v1/userinfo`
|
||||
|
||||
This endpoint will return information about the authorized user.
|
||||
|
||||
@ -561,7 +577,7 @@ If the token is invalid or expired, an HTTP 401 will be returned.
|
||||
|
||||
## revocation_endpoint
|
||||
|
||||
{your_domain}/oauth/v2/revoke
|
||||
`{your_domain}/oauth/v2/revoke`
|
||||
|
||||
This endpoint enables clients to revoke an `access_token` or `refresh_token` they have been granted.
|
||||
|
||||
@ -633,7 +649,7 @@ curl --request POST \
|
||||
|
||||
## end_session_endpoint
|
||||
|
||||
{your_domain}/oidc/v1/end_session
|
||||
`{your_domain}/oidc/v1/end_session`
|
||||
|
||||
The endpoint has to be opened in the user agent (browser) to terminate the user sessions.
|
||||
|
||||
@ -651,7 +667,7 @@ If both parameters are provided, they must be equal.
|
||||
|
||||
## jwks_uri
|
||||
|
||||
{your_domain}/oauth/v2/keys
|
||||
`{your_domain}/oauth/v2/keys`
|
||||
|
||||
The endpoint returns a JSON Web Key Set (JWKS) containing the public keys that can be used to locally validate JWTs you received from ZITADEL.
|
||||
The alternative would be to validate tokens with the [introspection endpoint](#introspection_endpoint).
|
||||
|
@ -24,14 +24,17 @@ ZITADEL supports the usage of scopes as way of requesting information from the I
|
||||
In addition to the standard compliant scopes we utilize the following scopes.
|
||||
|
||||
| Scopes | Example | Description |
|
||||
|:--------------------------------------------------|:-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| :------------------------------------------------ | :----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `urn:zitadel:iam:org:project:role:{rolekey}` | `urn:zitadel:iam:org:project:role:user` | By using this scope a client can request the claim `urn:zitadel:iam:org:project:roles` to be asserted when possible. As an alternative approach you can enable all roles to be asserted from the [project](/guides/manage/console/roles#authorizations) a client belongs to. |
|
||||
| `urn:zitadel:iam:org:projects:roles` | `urn:zitadel:iam:org:projects:roles` | By using this scope a client can request the claim `urn:zitadel:iam:org:project:{projectid}:roles` to be asserted for each requested project. All projects of the token audience, requested by the `urn:zitadel:iam:org:project:id:{projectid}:aud` scopes will be used. |
|
||||
| `urn:zitadel:iam:org:id:{id}` | `urn:zitadel:iam:org:id:178204173316174381` | When requesting this scope **ZITADEL** will enforce that the user is a member of the selected organization. If the organization does not exist a failure is displayed. It will assert the `urn:zitadel:iam:user:resourceowner` claims. |
|
||||
| `urn:zitadel:iam:org:domain:primary:{domainname}` | `urn:zitadel:iam:org:domain:primary:acme.ch` | When requesting this scope **ZITADEL** will enforce that the user is a member of the selected organization and the username is suffixed by the provided domain. If the organization does not exist a failure is displayed |
|
||||
| `urn:zitadel:iam:role:{rolename}` | | |
|
||||
| `urn:zitadel:iam:org:roles:id:{orgID}` | `urn:zitadel:iam:org:roles:id:178204173316174381` | This scope can be used one or more times to limit the granted organization IDs in the returned roles. Unknown organization IDs are ignored. When this scope is not used, all granted organizations are returned inside the roles.[^1] |
|
||||
| `urn:zitadel:iam:org:project:id:{projectid}:aud` | `urn:zitadel:iam:org:project:id:69234237810729019:aud` | By adding this scope, the requested projectid will be added to the audience of the access token |
|
||||
| `urn:zitadel:iam:org:project:id:zitadel:aud` | `urn:zitadel:iam:org:project:id:zitadel:aud` | By adding this scope, the ZITADEL project ID will be added to the audience of the access token |
|
||||
| `urn:zitadel:iam:user:metadata` | `urn:zitadel:iam:user:metadata` | By adding this scope, the metadata of the user will be included in the token. The values are base64 encoded. |
|
||||
| `urn:zitadel:iam:user:resourceowner` | `urn:zitadel:iam:user:resourceowner` | By adding this scope, the resourceowner (id, name, primary_domain) of the user will be included in the token. |
|
||||
| `urn:zitadel:iam:org:idp:id:{idp_id}` | `urn:zitadel:iam:org:idp:id:76625965177954913` | By adding this scope the user will directly be redirected to the identity provider to authenticate. Make sure you also send the primary domain scope if a custom login policy is configured. Otherwise the system will not be able to identify the identity provider. |
|
||||
|
||||
[^1]: `urn:zitadel:iam:org:roles:id:{orgID}` is not supported when the `oidcLegacyIntrospection` [feature flag](/docs/apis/resources/feature_service_v2/feature-service-set-instance-features) is enabled.
|
||||
|
@ -3,13 +3,338 @@ title: APIs V3 (Preview)
|
||||
---
|
||||
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import ActionServiceProto from '!!raw-loader!./_v3_action_service.proto'
|
||||
import ActionExecutionProto from '!!raw-loader!./_v3_action_execution.proto'
|
||||
import ActionTargetProto from '!!raw-loader!./_v3_action_target.proto'
|
||||
import ActionSearchProto from '!!raw-loader!./_v3_action_search.proto'
|
||||
import IDPServiceProto from '!!raw-loader!./_v3_idp_service.proto'
|
||||
import IDPProto from '!!raw-loader!./_v3_idp.proto'
|
||||
import IDPSearchProto from '!!raw-loader!./_v3_idp_search.proto'
|
||||
import IDPGitLabProto from '!!raw-loader!./_v3_idp_gitlab.proto'
|
||||
import LanguageServiceProto from '!!raw-loader!./_v3_language_service.proto'
|
||||
import LanguageProto from '!!raw-loader!./_v3_language.proto'
|
||||
import ObjectProto from '!!raw-loader!./_v3_object.proto'
|
||||
import ResourceObjectProto from '!!raw-loader!./_v3_resource_object.proto'
|
||||
import SettingsObjectProto from '!!raw-loader!./_v3_settings_object.proto'
|
||||
|
||||
APIs (V3) organize access by resources (users, settings, etc.), unlike context-specific V1 APIs.
|
||||
This simplifies finding the right API, especially for multi-organization resources.
|
||||
V3 also offers more flexibility over the V2 API in these points:
|
||||
- User schema definition for custom user management.
|
||||
- Behavior customization (API call manipulation, webhooks).
|
||||
The APIs described in this section are currently either in *Preview* stage or not implemented, yet.
|
||||
Before using these APIs, pleases consider the [API release policy below](#api-release-policy)
|
||||
|
||||
**Note**: V3 is currently in [Preview](/support/software-release-cycles-support#preview) and not yet generally available (breaking changes possible). Check individual services for availability.
|
||||
## We Appreciate your Help
|
||||
|
||||
We invite you to...
|
||||
- ... [discuss the concept with the ZITADEL community on GitHub](https://github.com/zitadel/zitadel/discussions/8125).
|
||||
- ... try the implementations and provide feedback [by filing issues on GitHub](https://github.com/zitadel/zitadel/issues/new/choose).
|
||||
|
||||
## The Ideas behind the New V3 APIs
|
||||
|
||||
The current ZITADEL *GA* APIs are structured around contexts like System, Admin, Management, and Auth.
|
||||
This structure leads to duplicate methods and makes it hard to find the right API for the right task.
|
||||
Especially interacting with resources from multiple organizations is cumbersome.
|
||||
Also, the APIs evolved over time, which lead to inconsistencies and a lack of flexibility in development.
|
||||
|
||||
We address these issues with the following new API categories:
|
||||
|
||||
- [Standard Resources](#standard-resources)
|
||||
- [Reusable Resources](#reusable-resources)
|
||||
- [Settings](#settings)
|
||||
|
||||
The designs for the new API categories aim for the following improvements:
|
||||
|
||||
### Service Structure
|
||||
|
||||
Instead of structuring the API methods around contexts, new APIs are structured around resources and settings.
|
||||
This means, eventually, we deprecate the old System-, Admin-, Management- and AuthAPIs in favor of User-, Action-, Language-, FeatureAPIs and so on.
|
||||
This change makes it easier to find the right API for the right task, especially for multi-organization resources.
|
||||
Also, it allows for faster development and independent versioning of the APIs.
|
||||
|
||||
### Multitenancy Management and Consistency
|
||||
|
||||
To improve managing and reusing resources and settings in multitenancy scenarios, we define some rules for the new APIs:
|
||||
|
||||
- Single properties from instance settings are overridable (patchable) in organizations.
|
||||
- Some settings support user-defined custom properties that are also overridable in organizations.
|
||||
- Improved experience with reusing resources in multiple organizations and instances.
|
||||
- Resources are searchable over all organizations with a single call by default.
|
||||
|
||||
### HTTP and gRPC Consistency
|
||||
|
||||
To make the APIs more consistent and easier to use, we follow the same patterns in all Proto files.
|
||||
- Patching is favored over updating resources and settings.
|
||||
- HTTP calls are mapped so that query parameters can be used as much as possible. We avoid the annotation `body: "*"`.
|
||||
- For search performance, we enforce query limits.
|
||||
|
||||
## Standard Resources
|
||||
|
||||
Standard resources exist in exactly one context.
|
||||
For example, a user is always assigned to exactly one organization.
|
||||
Or one SMS provider is always assigned to exactly one instance.
|
||||
|
||||
Standard resource methods behave like this:
|
||||
|
||||
- Search request results can be scoped to a RequestContext.
|
||||
- Search request results only contain results for which the requesting user has the necessary read permissions.
|
||||
- Search requests are limited to 100 by default. The limit can be increased by the caller up to 1000 by default.
|
||||
- Resource configurations are partially updatable. With HTTP, this is done via PATCH requests. If no changes were made, the response is successful.
|
||||
- Status changes or other actions on resources with side effects are done via POST requests. Their HTTP path ends with the underscore prefixed action name. For example `POST /resources/users/{id}/_unlock`.
|
||||
|
||||
For a full proto example, have a look at the [ZITADELActions service](#zitadelactions).
|
||||
|
||||
## Reusable Resources
|
||||
|
||||
Reusable resources are like standard resources but can be reused in multiple contexts.
|
||||
For example, an external identity provider can be defined once on the instance.
|
||||
Each organization within this instance can then choose to use this identity provider or not.
|
||||
|
||||
Additionally to the methods described for standard resources, reusable have the following capabilities:
|
||||
|
||||
Reusable resources have the same behavior as standard resources with the following additions:
|
||||
|
||||
- Reusable resources can be created in a given context level (system, instance, org).
|
||||
- For requests, that require a resource ID, no request context is needed.
|
||||
- Reusable resources are available in child contexts, even if their state is *inactive*.
|
||||
- The child context can control if an inherited resource should be active or inactive for itself using a state policy.
|
||||
- In child contexts, the state policy of a reused resource is *inherit* by default and can be changed to *activate*, *deactivate* or back to *inherit*.
|
||||
- In child contexts, a reused resources configuration is read-only.
|
||||
- Child contexts can read at least the following properties of reused resources:
|
||||
- ID
|
||||
- name
|
||||
- description
|
||||
- state
|
||||
- the state policy in the child context
|
||||
- sequence
|
||||
- last changed date
|
||||
- parent context
|
||||
- state in the immediate parent context.
|
||||
- By default, search queries for reused resources return all resources from the given contexts, all inherited resources and all resources defined in all children contexts.
|
||||
|
||||
Typically, a new resource is first designed and implemented as a non-reusable resource.
|
||||
If the community sees a benefit in reusing the resource in multiple contexts, reusability is added to the resource.
|
||||
|
||||
For a full proto example, have a look at the [ZITADELIdentityProviders service](#zitadelidentityproviders).
|
||||
|
||||
## Resource Services
|
||||
|
||||
All resource services by default support the following CRUD operations [as described above](#standard-resources-behavior).
|
||||
|
||||
- Create
|
||||
- Read (get, search)
|
||||
- Patch (partially update, success on no changes)
|
||||
- Delete
|
||||
|
||||
### ZITADELActions
|
||||
|
||||
- Standard CRUD methods for Targets
|
||||
- Standard CRUD methods for Executions except the PutExecution method replaces the CreateExecution and PatchExecution methods
|
||||
|
||||
Additional to the standard CRUD methods:
|
||||
|
||||
- ListAvailableExecutionServices
|
||||
- ListAvailableExecutionMethods
|
||||
- ListAvailableExecutionFunctions
|
||||
|
||||
\<details><summary>action_service.proto</summary>
|
||||
<CodeBlock language="protobuf">{ActionServiceProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>action_target.proto</summary>
|
||||
<CodeBlock language="protobuf">{ActionTargetProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>action_execution.proto</summary>
|
||||
<CodeBlock language="protobuf">{ActionExecutionProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>action_query.proto</summary>
|
||||
<CodeBlock language="protobuf">{ActionSearchProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
### ZITADELUsers
|
||||
|
||||
Standard CRUD methods
|
||||
|
||||
### ZITADELUserSchemas
|
||||
|
||||
Standard CRUD methods
|
||||
|
||||
### ZITADELIdentityProviders
|
||||
|
||||
- Standard CRUD and methods for all IDPs
|
||||
- Resources have additional properties for reusability capabilities.
|
||||
|
||||
\<details><summary>idp_service.proto</summary>
|
||||
<CodeBlock language="protobuf">{IDPServiceProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>idp.proto</summary>
|
||||
<CodeBlock language="protobuf">{IDPProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>idp_search.proto</summary>
|
||||
<CodeBlock language="protobuf">{IDPSearchProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>idp_gitlab.proto</summary>
|
||||
<CodeBlock language="protobuf">{IDPGitLabProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>object.proto</summary>
|
||||
<CodeBlock language="protobuf">{ObjectProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>resource_object.proto</summary>
|
||||
<CodeBlock language="protobuf">{ResourceObjectProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
### ZITADELInstances
|
||||
|
||||
Additional to the standard CRUD methods:
|
||||
|
||||
- Limit (partial update of block and audit log retention)
|
||||
- BulkLimit (partial update of block and audit log retention for multiple instances)
|
||||
|
||||
### ZITADELOrganizations
|
||||
|
||||
Additional to the standard CRUD methods:
|
||||
|
||||
- SetAsInstanceDefault
|
||||
- GetInstanceDefault
|
||||
|
||||
### ZITADELDomains
|
||||
|
||||
Additional to the standard CRUD methods:
|
||||
|
||||
- SetAsPrimary
|
||||
- Validate
|
||||
|
||||
### ZITADELSessions
|
||||
|
||||
Standard CRUD methods
|
||||
|
||||
### ZITADELProjects
|
||||
|
||||
Standard CRUD methods
|
||||
|
||||
### ZITADELApps
|
||||
|
||||
Standard CRUD methods
|
||||
|
||||
### ZITADELMemberships
|
||||
|
||||
The given context defines the organization, instance or system where the membership is created.
|
||||
The context and the user ID together are unique.
|
||||
|
||||
Additional to the standard CRUD methods:
|
||||
|
||||
- ListAvailableRoles (context-aware)
|
||||
|
||||
### ZITADELGrants
|
||||
|
||||
- Standard CRUD methods for project grants
|
||||
- Standard CRUD methods for user grants
|
||||
- Standard CRUD methods for roles
|
||||
|
||||
### ZITADELSMTPProviders
|
||||
|
||||
Standard CRUD methods
|
||||
|
||||
### ZITADELSMSProviders
|
||||
|
||||
Standard CRUD methods
|
||||
|
||||
## Settings
|
||||
|
||||
Settings have no identity (ID) and are always context-aware.
|
||||
They also don't have a state like active or inactive.
|
||||
They only have properties that can be set and queried.
|
||||
These properties are inherited to from parent-contexts (instance) to child-contexts (organization).
|
||||
|
||||
Settings behave like this:
|
||||
|
||||
- Setting and retrieving settings is always context-aware. By default, the context is the instance discovered by the requests *Host* header.
|
||||
- All settings properties can be partially overridden in child-contexts.
|
||||
- All settings properties can be partially reset in child-contexts, so their values default to the parent contexts property values.
|
||||
- All settings properties returned by queries contain the value and if it is inherited, the context where it is inherited from.
|
||||
|
||||
For a full proto example, have a look at the [ZITADELLanguageSettings service](#zitadellanguagesettings).
|
||||
|
||||
## Settings Services
|
||||
|
||||
### ZITADELLanguageSettings
|
||||
|
||||
Default language, restricted languages, supported languages
|
||||
|
||||
\<details><summary>language_service.proto</summary>
|
||||
<CodeBlock language="protobuf">{LanguageServiceProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>language.proto</summary>
|
||||
<CodeBlock language="protobuf">{LanguageProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>object.proto</summary>
|
||||
<CodeBlock language="protobuf">{ObjectProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
\<details><summary>settings_object.proto</summary>
|
||||
<CodeBlock language="protobuf">{SettingsObjectProto}</CodeBlock>
|
||||
\</details>
|
||||
|
||||
### ZITADELTextSettings
|
||||
|
||||
Key-value pairs for localized login texts, previously known as login texts
|
||||
|
||||
### ZITADELBrandingSettings
|
||||
|
||||
Predefined branding settings and custom key-value pairs, previously known as label policy or branding settings
|
||||
|
||||
### ZITADELLoginSettings
|
||||
|
||||
Previously known as login policy
|
||||
|
||||
### ZITADELLockoutSettings
|
||||
|
||||
Previously known as lockout policy
|
||||
|
||||
### ZITADELPasswordSettings
|
||||
|
||||
Previously known as password complexity policy
|
||||
|
||||
### ZITADELHelpSettings
|
||||
|
||||
Previously known as legal and support settings or privacy policy
|
||||
|
||||
### ZITADELDomainSettings
|
||||
|
||||
Previously known as domain policy
|
||||
|
||||
### ZITADELFeatureSettings
|
||||
|
||||
Feature toggles
|
||||
|
||||
Also contains disallow public org registrations on system and instance level.
|
||||
|
||||
### ZITADELTemplatesSettings
|
||||
|
||||
HTML and text templates for fully customizable emails and sms
|
||||
|
||||
### ZITADELSecretSettings
|
||||
|
||||
Replaces secret generators
|
||||
|
||||
## API Release Policy
|
||||
|
||||
- Defined but not yet implemented APIs are subject to change without further notice.
|
||||
- Once an API definition is implemented, it is released as *Preview* and is available for testing.
|
||||
- When a *Preview* API is tested enough so the concepts are proven to work, a new *Beta* API is released.
|
||||
- When an API is feature-complete and stable enough, a new *GA* (General Availability) API is released.
|
||||
- In all stages, changes to already implemented APIs are done in a backwards-compatible way, if possible.
|
||||
- When we release a new stage for an API, we deprecate the previous stage and keep it available for a smooth transition.
|
||||
|
||||
## Preview APIs
|
||||
|
||||
These APIs are ready for testing and feedback.
|
||||
Beware, they don't yet follow all the rules defined above.
|
||||
|
||||
<DocCardList />
|
@ -45,7 +45,7 @@ Go to your instance settings and then click on the Tab **Events** to open the Ev
|
||||
Since everything that is available in Console can also be called with our APIs, you can access all events and audit data trough our APIs:
|
||||
|
||||
- [Event API Guide](/docs/guides/integrate/zitadel-apis/event-api)
|
||||
- [API Documentation](/docs/category/apis/resources/admin/events)
|
||||
- [API Documentation](/docs/apis/resources/admin/events)
|
||||
|
||||
Access to the API is possible with a [Service User](/docs/guides/integrate/service-users/authenticate-service-users) account, allowing you to integrate the events with your own business logic.
|
||||
|
||||
|
@ -35,6 +35,6 @@ In some use cases, external user grants are a simple way to allow users access t
|
||||
|
||||
## References
|
||||
|
||||
* [API reference for user grants](/docs/category/apis/resources/mgmt/user-grants)
|
||||
* [API reference for user grants](/docs/apis/resources/mgmt/user-grants)
|
||||
* [How to manage user grants through ZITADEL's console](/docs/guides/manage/console/roles#authorizations)
|
||||
* [More about multi-tenancy with ZITADEL](https://zitadel.com/blog/multi-tenancy-with-organizations)
|
||||
|
@ -75,4 +75,4 @@ To address this, ZITADEL provides generic templates that enable connection to vi
|
||||
|
||||
* [Detailed integration guide for many identity providers](/guides/integrate/identity-providers/introduction)
|
||||
* [Setup identity providers with Console](/guides/manage/console/default-settings#identity-providers)
|
||||
* [Configure identity providers with the ZITADEL API](/docs/category/apis/resources/mgmt/identity-providers)
|
||||
* [Configure identity providers with the ZITADEL API](/docs/apis/resources/mgmt/identity-providers)
|
||||
|
@ -25,4 +25,4 @@ Ensure the configuration of application settings is limited to authorized users
|
||||
## References
|
||||
|
||||
- [Configure Applications in the Console](../../guides/manage/console/applications)
|
||||
- [ZITADEL API: Applications](/docs/category/apis/resources/mgmt/applications)
|
||||
- [ZITADEL API: Applications](/docs/apis/resources/mgmt/applications)
|
||||
|
@ -78,5 +78,5 @@ You can use organization metadata or your own business logic to describe a hiera
|
||||
## References
|
||||
|
||||
- [Manage users in the Console](../../guides/manage/console/users)
|
||||
- [ZITADEL APIs: Users](/docs/category/apis/resources/mgmt/users)
|
||||
- [ZITADEL APIs: Users](/docs/apis/resources/mgmt/users)
|
||||
- [User onboarding and registration](/docs/guides/integrate/onboarding)
|
||||
|
@ -21,7 +21,7 @@ We recommend that you use [Authorization Code](/apis/openidoauth/grant-types#aut
|
||||
|
||||
A redirect URL is a URL in your application where ZITADEL redirects the user after they have authenticated. Set your url to the domain the proxy will be deployed to or use the default one `http://127.0.0.1:4180/oauth2/callback`.
|
||||
|
||||
> If you are following along with the sample project you downloaded from our templates, you should set the Allowed Callback URL to <http://localhost:4200/auth/callback>. You will also have to set dev mode to `true` as this will enable unsecure http for the moment.
|
||||
> If you are following along with the sample project you downloaded from our templates, you should set the Allowed Callback URL to `http://localhost:4200/auth/callback`. You will also have to set dev mode to `true` as this will enable unsecure http for the moment.
|
||||
|
||||
If you want to redirect the users back to a route on your application after they have logged out, add an optional redirect in the post redirectURI field.
|
||||
|
||||
@ -32,7 +32,7 @@ Continue and Create the application.
|
||||
After successful app creation a popup will appear showing you your clientID as well as a secret.
|
||||
Copy your client ID and Secrets as it will be needed in the next step.
|
||||
|
||||
> Note: You will be able to regenerate the secret at a later time if you loose it.
|
||||
> Note: You will be able to regenerate the secret at a later time if you lose it.
|
||||
|
||||
## OAuth 2.0 Proxy Setup
|
||||
|
||||
|
1
docs/docs/examples/imports/_setup_pylon.mdx
Normal file
1
docs/docs/examples/imports/_setup_pylon.mdx
Normal file
@ -0,0 +1 @@
|
||||
You have to install Pylon as described in [their documentation](https://pylon.cronit.io/docs/installation/).
|
@ -25,7 +25,7 @@ We recommend that you use [Proof Key for Code Exchange (PKCE)](/apis/openidoauth
|
||||
The Redirect URIs field tells ZITADEL where it's allowed to redirect users after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
|
||||
The Post-logout redirect send the users back to a route on your application after they have logged out.
|
||||
|
||||
> If you are following along with the [example](https://github.com/zitadel/zitadel-angular), set the dev mode to `true`, the Redirect URIs to <http://localhost:4200/auth/callback> and Post redirect URI to <http://localhost:4200/signedout>.
|
||||
> If you are following along with the [example](https://github.com/zitadel/zitadel-angular), set the dev mode to `true`, the Redirect URIs to `http://localhost:4200/auth/callback` and Post redirect URI to `http://localhost:4200/signedout`.
|
||||
|
||||
Continue and create the application.
|
||||
|
||||
|
@ -28,7 +28,7 @@ We recommend that you use [Proof Key for Code Exchange (PKCE)](/apis/openidoauth
|
||||
The Redirect URIs field tells ZITADEL where it's allowed to redirect users after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
|
||||
The Post-logout redirect send the users back to a route on your application after they have logged out.
|
||||
|
||||
> If you are following along with the [example](https://github.com/zitadel/zitadel-go), set the dev mode to `true`, the Redirect URIs to <http://localhost:8089/auth/callback> and Post-logout redirect URI to <http://localhost:8089/>.
|
||||
> If you are following along with the [example](https://github.com/zitadel/zitadel-go), set the dev mode to `true`, the Redirect URIs to `http://localhost:8089/auth/callback` and Post-logout redirect URI to [http://localhost:8089/](http://localhost:8089/)>.
|
||||
|
||||

|
||||
|
||||
|
@ -162,7 +162,7 @@ java \
|
||||
-jar web/target/web-0.0.2-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
If you then visit on <http://localhost:18080/webapp> you should directly be redirected to your ZITADEL instance.
|
||||
If you then visit on [http://localhost:18080/webapp](http://localhost:18080/webapp) you should directly be redirected to your ZITADEL instance.
|
||||
After login with your existing user you will be presented the profile page:
|
||||
|
||||

|
||||
|
@ -22,7 +22,7 @@ First we need to create an organization that holds the Vendor's users, projects
|
||||
|
||||
### Vendor Organization
|
||||
|
||||
Navigate to `https://{YourDomain}.zitadel.cloud/ui/console/orgs` (replace {YourDomain}), and click on the button "New".
|
||||
Navigate to `https://{YourDomain}.zitadel.cloud/ui/console/orgs` (replace \{YourDomain}), and click on the button "New".
|
||||
Toggle the setting "Use your personal account as organization owner".
|
||||
|
||||
Enter the name `Demo-Vendor`, and click "Create". Then click on that organization.
|
||||
|
@ -41,7 +41,7 @@ Select `CODE` in the next step. This makes sure you still get a secret. Note tha
|
||||
|
||||
With the Redirect URIs field, you tell ZITADEL where it is allowed to redirect users to after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
|
||||
|
||||
> If you are following along with the [example](https://github.com/zitadel/zitadel-angular), set dev mode to `true` and the Redirect URIs to <http://localhost:3000/api/auth/callback/zitadel>.
|
||||
> If you are following along with the [example](https://github.com/zitadel/zitadel-angular), set dev mode to `true` and the Redirect URIs to `http://localhost:3000/api/auth/callback/zitadel`.
|
||||
|
||||
If you want to redirect the users back to a route on your application after they have logged out, add an optional redirect in the Post Logout URIs field.
|
||||
|
||||
|
@ -18,7 +18,7 @@ Before we can start building our application, we have to do a few configuration
|
||||
|
||||
### Project roles
|
||||
|
||||
The Example expects [user roles](guides/integrate/retrieve-user-roles) to be returned after login.
|
||||
The Example expects [user roles](/docs/guides/integrate/retrieve-user-roles) to be returned after login.
|
||||
Symfony uses `ROLE_USER` format.
|
||||
The application will take care of upper-casing and prefixing for us.
|
||||
Inside ZITADEL, you can use regular lower-case role names without prefixes, if you prefer.
|
||||
|
304
docs/docs/examples/secure-api/pylon.mdx
Normal file
304
docs/docs/examples/secure-api/pylon.mdx
Normal file
@ -0,0 +1,304 @@
|
||||
---
|
||||
title: ZITADEL with Pylon
|
||||
sidebar_label: Pylon
|
||||
---
|
||||
|
||||
import AppJWT from "../imports/_app_jwt.mdx";
|
||||
import ServiceuserJWT from "../imports/_serviceuser_jwt.mdx";
|
||||
import ServiceuserRole from "../imports/_serviceuser_role.mdx";
|
||||
import SetupPylon from "../imports/_setup_pylon.mdx";
|
||||
|
||||
This integration guide demonstrates the recommended way to incorporate ZITADEL into your Pylon service.
|
||||
It explains how to check the token validity in the API and how to check for permissions.
|
||||
|
||||
By the end of this guide, your application will have three different endpoint which are public, private(valid token) and private-scoped(valid token with specific role).
|
||||
|
||||
## ZITADEL setup
|
||||
|
||||
Before we can start building our application, we have to do a few configuration steps in ZITADEL Console.
|
||||
|
||||
### Create application
|
||||
|
||||
<AppJWT />
|
||||
|
||||
### Create Serviceuser
|
||||
|
||||
<ServiceuserJWT />
|
||||
|
||||
### Give Serviceuser an authorization
|
||||
|
||||
<ServiceuserRole />
|
||||
|
||||
### Prerequisites
|
||||
|
||||
At the end you should have the following for the API:
|
||||
|
||||
- Issuer, something like `https://example.zitadel.cloud` or `http://localhost:8080`
|
||||
- `.json`-key-file for the API, from the application
|
||||
- ID of the project
|
||||
|
||||
And the following from the Serviceuser:
|
||||
|
||||
- `.json`-key-file from the serviceuser
|
||||
|
||||
## Setup new Pylon service
|
||||
|
||||
### Setup Pylon
|
||||
|
||||
<SetupPylon />
|
||||
|
||||
### Creating a new project
|
||||
|
||||
To create a new Pylon project, run the following command:
|
||||
|
||||
```bash
|
||||
pylon new my-pylon-project
|
||||
```
|
||||
|
||||
This will create a new directory called `my-pylon-project` with a basic Pylon project structure.
|
||||
|
||||
### Project structure
|
||||
|
||||
Pylon projects are structured as follows:
|
||||
|
||||
```
|
||||
my-pylon-project/
|
||||
├── .pylon/
|
||||
├── src/
|
||||
│ ├── index.ts
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
```
|
||||
|
||||
- `.pylon/`: Contains the production build of your project.
|
||||
- `src/`: Contains the source code of your project.
|
||||
- `src/index.ts`: The entry point of your Pylon service.
|
||||
- `package.json`: The npm package configuration file.
|
||||
- `tsconfig.json`: The TypeScript configuration file.
|
||||
|
||||
### Basic example
|
||||
|
||||
Here's an example of a basic Pylon service:
|
||||
|
||||
```ts
|
||||
import { defineService } from "@getcronit/pylon";
|
||||
|
||||
export default defineService({
|
||||
Query: {
|
||||
sum: (a: number, b: number) => a + b,
|
||||
},
|
||||
Mutation: {
|
||||
divide: (a: number, b: number) => a / b,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Secure the API
|
||||
|
||||
### Add ZITADEL info to the service
|
||||
|
||||
1. Create a `.env` file in the root folder of your project and add the following configuration:
|
||||
|
||||
```bash
|
||||
AUTH_ISSUER='URL to the zitadel instance'
|
||||
AUTH_PROJECT_ID='ID of the project'
|
||||
```
|
||||
|
||||
It should look something like this:
|
||||
|
||||
```bash
|
||||
AUTH_ISSUER='https://example.zitadel.cloud'
|
||||
AUTH_PROJECT_ID='250719519163548112'
|
||||
```
|
||||
|
||||
2. Copy the `.json`-key-file that you downloaded from the ZITADEL Console into the root folder of your project and rename it to `key.json`.
|
||||
|
||||
### Auth
|
||||
|
||||
Pylon provides a auth module and a decorator to check the validity of the token and the permissions.
|
||||
|
||||
- `auth.initialize()`: Initializes the authentication middleware.
|
||||
- `auth.require()` : Middleware to check if the token is valid.
|
||||
- `auth.require({roles: ['role']})`: Middleware to check if the token is valid and has the specified roles.
|
||||
- `requireAuth()`: Decorator to check if the token is valid.
|
||||
- `requireAuth({roles: ['role']})`: Decorator to check if the token is valid and has the specified roles.
|
||||
|
||||
### Build the Pylon service
|
||||
|
||||
Now we will create a new Pylon service with the following endpoints:
|
||||
|
||||
- `/api/public`: Public endpoint
|
||||
- `/api/private`: Private endpoint
|
||||
- `/api/private-scoped`: Private endpoint with specific role
|
||||
- `/graphql`: GraphQL endpoint
|
||||
- Query: `me`: Private endpoint that returns the current user and the messages if the role is `read:messages`
|
||||
- Query: `info`: Public endpoint
|
||||
|
||||
### Create the service
|
||||
|
||||
The following code demonstrates how to create a Pylon service with the required endpoints, it must be added to the `src/index.ts` file of your project:
|
||||
|
||||
```ts
|
||||
import {
|
||||
defineService,
|
||||
PylonAPI,
|
||||
auth,
|
||||
requireAuth,
|
||||
getContext,
|
||||
ServiceError,
|
||||
} from "@getcronit/pylon";
|
||||
|
||||
class User {
|
||||
id: string;
|
||||
name: string;
|
||||
#messages: string[];
|
||||
|
||||
constructor(id: string, name: string, messages: string[]) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.#messages = messages;
|
||||
}
|
||||
|
||||
@requireAuth({ roles: ["read:messages"] })
|
||||
async messages() {
|
||||
return this.#messages;
|
||||
}
|
||||
|
||||
static users: User[] = [];
|
||||
|
||||
@requireAuth()
|
||||
static async me() {
|
||||
const ctx = getContext();
|
||||
const id = ctx.get("auth")!.sub;
|
||||
|
||||
const user = User.users.find((user) => user.id === id);
|
||||
|
||||
if (!user) {
|
||||
throw new ServiceError("User not found", {
|
||||
statusCode: 404,
|
||||
code: "USER_NOT_FOUND",
|
||||
});
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
@requireAuth()
|
||||
static async create() {
|
||||
const ctx = getContext();
|
||||
|
||||
const auth = ctx.get("auth")!;
|
||||
|
||||
// Check if the user already exists
|
||||
|
||||
if (User.users.find((user) => user.id === auth.sub)) {
|
||||
throw new ServiceError("User already exists", {
|
||||
statusCode: 400,
|
||||
code: "USER_ALREADY_EXISTS",
|
||||
});
|
||||
}
|
||||
|
||||
const user = new User(auth.sub, auth.username || "unknown", [
|
||||
"Welcome to Pylon with ZITADEL!",
|
||||
]);
|
||||
|
||||
User.users.push(user);
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
export default defineService({
|
||||
Query: {
|
||||
me: User.me,
|
||||
info: () => "Public Data",
|
||||
},
|
||||
Mutation: {
|
||||
createUser: User.create,
|
||||
},
|
||||
});
|
||||
|
||||
export const configureApp: PylonAPI["configureApp"] = (app) => {
|
||||
// Initialize the authentication middleware
|
||||
app.use("*", auth.initialize());
|
||||
|
||||
// Automatically try to create a user for each request for demonstration purposes
|
||||
app.use(async (_, next) => {
|
||||
try {
|
||||
await User.create();
|
||||
} catch {
|
||||
// Ignore errors
|
||||
// Fail silently if the user already exists
|
||||
}
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
app.get("/api/info", (c) => {
|
||||
return new Response("Public Data");
|
||||
});
|
||||
|
||||
// The `auth.require()` middleware is optional here, as the `User.me` method already checks for it.
|
||||
app.get("/api/me", auth.require(), async (c) => {
|
||||
const user = await User.me();
|
||||
|
||||
return c.json(user);
|
||||
});
|
||||
|
||||
// A role check for `read:messages` is not required here, as the `user.messages` method already checks for it.
|
||||
app.get("/api/me/messages", auth.require(), async (c) => {
|
||||
const user = await User.me();
|
||||
|
||||
// This will throw an error if the user does not have the `read:messages` role
|
||||
return c.json(await user.messages());
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
### Call the API
|
||||
|
||||
To call the API you need an access token, which is then verified by ZITADEL.
|
||||
Please follow [this guide here](/docs/guides/integrate/token-introspection/private-key-jwt#get-an-access-token), ignoring the first step as we already have the `.json`-key-file from the serviceaccount.
|
||||
|
||||
:::info
|
||||
You can also create a PAT for the serviceuser and use it to test the API. For this, follow [this guide](/docs/guides/integrate/service-users/personal-access-token#create-a-service-user-with-a-pat).
|
||||
:::
|
||||
|
||||
Optionally set the token as an environment variable:
|
||||
|
||||
```
|
||||
export TOKEN='MtjHodGy4zxKylDOhg6kW90WeEQs2q...'
|
||||
```
|
||||
|
||||
Now you have to start the Pylon service:
|
||||
|
||||
```bash
|
||||
bun run develop
|
||||
```
|
||||
|
||||
With the access token, you can then do the following calls:
|
||||
|
||||
1. GraphQL:
|
||||
|
||||
```
|
||||
curl -H "Authorization: Bearer $TOKEN" -G http://localhost:3000/graphql --data-urlencode 'query={ info }'
|
||||
curl -H "Authorization: Bearer $TOKEN" -G http://localhost:3000/graphql --data-urlencode 'query={ me { id name } }'
|
||||
curl -H "Authorization: Bearer $TOKEN" -G http://localhost:3000/graphql --data-urlencode 'query={ me { id name messages } }'
|
||||
|
||||
```
|
||||
|
||||
You can also visit the GraphQL playground at `http://localhost:3000/graphql` and execute the queries there.
|
||||
|
||||
2. Routes:
|
||||
|
||||
```
|
||||
curl -H "Authorization: Bearer $TOKEN" -X GET http://localhost:3000/api/info
|
||||
curl -H "Authorization: Bearer $TOKEN" -X GET http://localhost:3000/api/me
|
||||
curl -H "Authorization: Bearer $TOKEN" -X GET http://localhost:3000/api/me/messages
|
||||
```
|
||||
|
||||
## Completion
|
||||
|
||||
Congratulations! You have successfully integrated your Pylon with ZITADEL!
|
||||
|
||||
If you get stuck, consider checking out their [documentation](https://pylon.cronit.io/). If you face issues, contact Pylon or raise an issue on [GitHub](https://github.com/getcronit/pylon/issues).
|
@ -177,5 +177,5 @@ Deciding whether to configure an external Identity Provider (IdP) at the organiz
|
||||
## References
|
||||
|
||||
- [Identity brokering in ZITADEL](/docs/concepts/features/identity-brokering)
|
||||
- [The ZITADEL API reference for managing external IdPs](/docs/category/apis/resources/admin/identity-providers)
|
||||
- [Handle external logins in a custom login UI](/docs/guides/integrate/login-ui/external-login)
|
||||
- [The ZITADEL API reference for managing external IdPs](/docs/apis/resources/admin/identity-providers)
|
||||
- [Handle external logins in a custom login UI](/docs/guides/integrate/login-ui/external-login)
|
||||
|
@ -26,7 +26,7 @@ You will have to paste it in the Keycloak Client later.
|
||||
|
||||
### Register a new client
|
||||
|
||||
1. Login to your Keycloak account and go to the clients list: <$KEYCLOAK-DOMAIN/auth/admin/$REALM/console/#/$REALM/clients>
|
||||
1. Login to your Keycloak account and go to the clients list: `$KEYCLOAK-DOMAIN/auth/admin/$REALM/console/#/$REALM/clients`
|
||||
2. Click on "Create Client"
|
||||
3. Choose OpenID Connect as Client Type and give your client an ID
|
||||
4. Enable Client authentication and the standard flow and direct access grants as authentication flow
|
||||
|
@ -23,7 +23,7 @@ import TestSetup from './_test_setup.mdx';
|
||||
2. Add your App Name, your Company Page and a Logo
|
||||
3. Add "Sign In with LinkedIn using OpenID Connect" by clicking "Request access"
|
||||
4. Go to the Auth Settings of the App and add the following URL to the "Authorized redirect URLs"
|
||||
- {your-domain}/ui/login/login/externalidp/callback
|
||||
- `{your_domain}/ui/login/login/externalidp/callback`
|
||||
- Example redirect url for the domain `https://acme.zitadel.cloud` would look like this: `https://acme.zitadel.cloud/ui/login/login/externalidp/callback`
|
||||
5. Verify the app as your company
|
||||
6. In the Auth - OAuth 2.0 scopes section you should see `openid`, `profile` and `email` listed
|
||||
|
@ -44,7 +44,7 @@ All the necessary configuration is contained in the metadata which has to be exc
|
||||
### Download metadata
|
||||
|
||||
Normally, you would need to download the ServiceProvider metadata from ZITADEL to upload to the IdentityProvider.
|
||||
They are available under [https://{CUSTOMDOMAIN}/idps/{ID of the provider in ZITADEL}/saml/metadata], but this step can be skipped due to the fact that MockSAML is only for testing purposes.
|
||||
They are available under `https://${CUSTOMDOMAIN}/idps/\{ID of the provider in ZITADEL}/saml/metadata`, but this step can be skipped due to the fact that MockSAML is only for testing purposes.
|
||||
|
||||
### Activate IdP
|
||||
|
||||
|
@ -27,7 +27,7 @@ You will have to paste it in the OKTA application later.
|
||||
|
||||
### Register a new client
|
||||
|
||||
1. Login to your OKTA Account and go to the applications list: <OKTA-DOMAIN/admin/apps/active>
|
||||
1. Login to your OKTA Account and go to the applications list: `OKTA-DOMAIN/admin/apps/active^
|
||||
2. Click on "Create App Integration" and choose "OIDC - OpenID Connect"
|
||||
3. Choose Web application as Application type and give a name
|
||||
4. [Paste the ZITADEL Callback URL you copied before](#open-the-generic-oidc-provider-template) to the Sign-in redirect URIs
|
||||
@ -65,7 +65,6 @@ ZITADEL ensures that at least the `openid`-scope is always sent.
|
||||
|
||||
<TestSetup loginscreen="your OKTA login"/>
|
||||
|
||||
<!-- TODO: Image highlights Google -->
|
||||

|
||||
|
||||

|
||||
|
@ -41,7 +41,7 @@ After you created the SAML SP in ZITADEL, you can copy the URLs you need to conf
|
||||
|
||||
### Register a new client
|
||||
|
||||
1. Log in to your OKTA Account and go to the applications list: <OKTA-DOMAIN/admin/apps/active>
|
||||
1. Log in to your OKTA Account and go to the applications list: `OKTA-DOMAIN/admin/apps/active`
|
||||
2. Click on "Create App Integration" and choose "SAML 2.0"
|
||||
3. Give the application a name
|
||||
4. Click on the ZITADEL URLs that your SAML IDP shows since you created it in ZITADEL and paste them accordingly:
|
||||
|
@ -12,6 +12,13 @@ sidebar_label: Username and Password
|
||||
First, we create a new user with a username and password. In the example below we add a user with profile data, a verified email address, and a password.
|
||||
[Create User Documentation](/apis/resources/user_service/user-service-add-human-user)
|
||||
|
||||
### Custom Fields
|
||||
|
||||
If you have custom fields you like to add to your users that are not provided by ZITADEL, you can add them to the metadata.
|
||||
Metadata are key value pairs you can use for additional user data.
|
||||
These fields can also be included in the token of the user, so you have access to it all the time.
|
||||
Read more about the metadata [here](/docs/guides/manage/customize/user-metadata)
|
||||
|
||||
### Request
|
||||
|
||||
```bash
|
||||
|
@ -26,7 +26,7 @@ ZITADEL does have multiple possibilities to achieve that process.
|
||||
## Onboard customers through the ZITADEL Management Console
|
||||
|
||||
Each ZITADEL instance does automatically bring a management console with it. The [console](/docs/guides/manage/console/overview) can be used to manage all your resources through a UI.
|
||||
You can access it by calling the following URL: $CUSTOM-DOMAIN/ui/
|
||||
You can access it by calling the following URL: `${CUSTOM-DOMAIN}/ui/`
|
||||
Make sure that your admins have a [Manager role](/docs/guides/manage/console/managers) with permissions on an instance level such as "INSTANCE_OWNER"
|
||||
|
||||
### Create a customer
|
||||
@ -139,7 +139,7 @@ If you want to start automating the process of onboarding your customers the fol
|
||||
### Built-in register organization form
|
||||
|
||||
A basic form that allows a customer to enter an organization name and a user account is hosted on the following URL:
|
||||
{custom-domain}/ui/login/register/org
|
||||
`{custom-domain}/ui/login/register/org`
|
||||
|
||||
When a user registers through this form, an organization and a user are created.
|
||||
The user will automatically get the role "ORG_OWNER" withing ZITADEL and is able to manage the whole organization.
|
||||
|
@ -102,7 +102,7 @@ Please follow the configuration guides for the needed providers: [Let Users Logi
|
||||
|
||||
import OrgLoginDescription from "./_org_login_description.mdx";
|
||||
|
||||
<OrgLoginDescription name="OrgLodinDescription" />
|
||||
<OrgLoginDescription name="OrgLoginDescription" />
|
||||
|
||||
### Build your own registration form
|
||||
|
||||
@ -117,8 +117,11 @@ We do have a guide series on how to build your own login ui, which also includes
|
||||
|
||||
You can find all the guides here: [Build your own login UI](/docs/guides/integrate/login-ui)
|
||||
|
||||
The create user request also allows you to add metadata (key, value) to the user.
|
||||
#### Custom fields
|
||||
|
||||
The [create user request](/docs/apis/resources/user_service/user-service-add-human-user) also allows you to add [metadata](/docs/guides/manage/customize/user-metadata) (key, value) to the user.
|
||||
This gives you the possibility to collect additional data from your users during the registration process and store it directly to the user in ZITADEL.
|
||||
Those metadata can also directly be included in the [token](/docs/guides/manage/customize/user-metadata#use-tokens-to-get-user-metadata) of the user.
|
||||
We recommend storing business relevant data in the database of your application, and only authentication and authorization relevant data in ZITADEL to follow the separation of concern pattern.
|
||||
|
||||
#### Registration with Organization External Identity Provider
|
||||
|
@ -18,8 +18,8 @@ Follow the links below to assign roles to your users.
|
||||
|
||||
- [Add application roles via the ZITADEL Console](/docs/guides/manage/console/roles)
|
||||
- [Add manager roles via the ZITADEL Console](/docs/guides/manage/console/managers)
|
||||
- [Add application roles via the ZITADEL Management API](/docs/category/apis/resources/mgmt/project-roles)
|
||||
- [Add manager roles to users via the ZITADEL Management API](/category/apis/resources/mgmt/members)
|
||||
- [Add application roles via the ZITADEL Management API](/docs/apis/resources/mgmt/project-roles)
|
||||
- [Add manager roles to users via the ZITADEL Management API](/docs/apis/resources/mgmt/members)
|
||||
|
||||
## Retrieve roles
|
||||
|
||||
@ -210,7 +210,7 @@ https://github.com/zitadel/actions/blob/main/examples/custom_roles.js
|
||||
Now we will use the auth API to retrieve roles from a logged in user using the user’s token
|
||||
The base URL is: **https://$ZITADEL_DOMAIN/auth/v1**
|
||||
|
||||
Let’s start with a user who has multiple roles in different organizations in a multi-tenanted set up. You can use the logged in user’s token or the machine user’s token to retrieve the authorizations using the [APIs listed under user authorizations/grants in the auth API](/docs/category/apis/resources/auth/user-authorizations-grants).
|
||||
Let’s start with a user who has multiple roles in different organizations in a multi-tenanted set up. You can use the logged in user’s token or the machine user’s token to retrieve the authorizations using the [APIs listed under user authorizations/grants in the auth API](/docs/apis/resources/auth/user-authorizations-grants).
|
||||
|
||||
**Scope used:** `openid urn:zitadel:iam:org:project:id:zitadel:aud`
|
||||
|
||||
@ -394,7 +394,7 @@ Now we will use the management API to retrieve user roles under an admin user.
|
||||
|
||||
The base URL is: **https://$CUSTOM-DOMAIN/management/v1**
|
||||
|
||||
In [APIs listed under user grants in the management API](/docs/category/apis/resources/mgmt/user-grants), you will see that you can use the management API to retrieve and modify user grants. The two API paths that we are interested in to fetch user roles are given below.
|
||||
In [APIs listed under user grants in the management API](/docs/apis/resources/mgmt/user-grants), you will see that you can use the management API to retrieve and modify user grants. The two API paths that we are interested in to fetch user roles are given below.
|
||||
|
||||
**Scope used:** `openid urn:zitadel:iam:org:project:id:zitadel:aud`
|
||||
|
||||
|
@ -127,7 +127,7 @@ However, [client credentials authentication](./client-credentials.md) might be c
|
||||
## Further resources
|
||||
|
||||
* Read about the [different methods to authenticate service users](./authenticate-service-users)
|
||||
* [Service User API reference](/docs/category/apis/resources/mgmt/user-machine)
|
||||
* [Service User API reference](/docs/apis/resources/mgmt/user-machine)
|
||||
* [OIDC JWT with private key](/docs/apis/openidoauth/authn-methods#jwt-with-private-key) authentication method reference
|
||||
* [Access ZITADEL APIs](../zitadel-apis/access-zitadel-apis)
|
||||
* Validate access tokens with [token introspection with private key jwt](../token-introspection/private-key-jwt.mdx)
|
||||
|
@ -100,7 +100,7 @@ By following these steps and adhering to security best practices, you can effect
|
||||
## Notes
|
||||
|
||||
* Read about the [different methods to authenticate service users](./authenticate-service-users)
|
||||
* [Service User API reference](/docs/category/apis/resources/mgmt/user-machine)
|
||||
* [Service User API reference](/docs/apis/resources/mgmt/user-machine)
|
||||
* [OIDC client secret basic](/docs/apis/openidoauth/authn-methods#client-secret-basic) authentication method reference
|
||||
* [Access ZITADEL APIs](../zitadel-apis/access-zitadel-apis)
|
||||
* Validate access tokens with [token introspection with basic auth](../token-introspection/basic-auth)
|
||||
|
@ -36,9 +36,9 @@ For Identity Provider select "Other provider" and enter a Directory Name.
|
||||
Follow the wizard.
|
||||
Fill in the following information:
|
||||
|
||||
- `Identity provider Entity ID`: {your_instance_domain}/saml/v2/metadata
|
||||
- `Identity provider SSO URL`: {your_instance_domain}/saml/v2/SSO
|
||||
- `Public x509 certificate`: You need to download and paste the value of the certificate from {your_instance_domain}/saml/v2/certificate
|
||||
- `Identity provider Entity ID`: \{your_instance_domain}/saml/v2/metadata
|
||||
- `Identity provider SSO URL`: \{your_instance_domain}/saml/v2/SSO
|
||||
- `Public x509 certificate`: You need to download and paste the value of the certificate from \{your_instance_domain}/saml/v2/certificate
|
||||
|
||||

|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user