Merge remote-tracking branch 'origin/main' into next

This commit is contained in:
Stefan Benz 2024-10-11 11:16:54 +02:00
commit 55b1188dd0
No known key found for this signature in database
GPG Key ID: 071AA751ED4F9D31
147 changed files with 8094 additions and 1896 deletions

View File

@ -2,6 +2,7 @@ name: Bug Report
description: "Create a bug report to help us improve ZITADEL."
title: "[Bug]: "
labels: ["bug"]
type: Bug
body:
- type: markdown
attributes:

View File

@ -25,15 +25,11 @@ type NewEventsTable struct {
}
func (mig *NewEventsTable) Execute(ctx context.Context, _ eventstore.Event) error {
migrations, err := newEventsTable.ReadDir("14/" + mig.dbClient.Type())
if err != nil {
return err
}
// if events already exists events2 is created during a setup job
var count int
err = mig.dbClient.QueryRow(
err := mig.dbClient.QueryRowContext(ctx,
func(row *sql.Row) error {
if err = row.Scan(&count); err != nil {
if err := row.Scan(&count); err != nil {
return err
}
return row.Err()
@ -43,16 +39,15 @@ func (mig *NewEventsTable) Execute(ctx context.Context, _ eventstore.Event) erro
if err != nil || count == 1 {
return err
}
for _, migration := range migrations {
stmt, err := readStmt(newEventsTable, "14", mig.dbClient.Type(), migration.Name())
if err != nil {
return err
}
stmt = strings.ReplaceAll(stmt, "{{.username}}", mig.dbClient.Username())
logging.WithFields("migration", mig.String(), "file", migration.Name()).Debug("execute statement")
_, err = mig.dbClient.ExecContext(ctx, stmt)
statements, err := readStatements(newEventsTable, "14", mig.dbClient.Type())
if err != nil {
return err
}
for _, stmt := range statements {
stmt.query = strings.ReplaceAll(stmt.query, "{{.username}}", mig.dbClient.Username())
logging.WithFields("file", stmt.file, "migration", mig.String()).Info("execute statement")
_, err = mig.dbClient.ExecContext(ctx, stmt.query)
if err != nil {
return err
}

View File

@ -21,19 +21,13 @@ type CurrentProjectionState struct {
}
func (mig *CurrentProjectionState) Execute(ctx context.Context, _ eventstore.Event) error {
migrations, err := currentProjectionState.ReadDir("15/" + mig.dbClient.Type())
statements, err := readStatements(currentProjectionState, "15", mig.dbClient.Type())
if err != nil {
return err
}
for _, migration := range migrations {
stmt, err := readStmt(currentProjectionState, "15", mig.dbClient.Type(), migration.Name())
if err != nil {
return err
}
logging.WithFields("file", migration.Name(), "migration", mig.String()).Info("execute statement")
_, err = mig.dbClient.ExecContext(ctx, stmt)
for _, stmt := range statements {
logging.WithFields("file", stmt.file, "migration", mig.String()).Info("execute statement")
_, err = mig.dbClient.ExecContext(ctx, stmt.query)
if err != nil {
return err
}

37
cmd/setup/34.go Normal file
View File

@ -0,0 +1,37 @@
package setup
import (
"context"
_ "embed"
"fmt"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/eventstore"
)
var (
//go:embed 34/cockroach/34_cache_schema.sql
addCacheSchemaCockroach string
//go:embed 34/postgres/34_cache_schema.sql
addCacheSchemaPostgres string
)
type AddCacheSchema struct {
dbClient *database.DB
}
func (mig *AddCacheSchema) Execute(ctx context.Context, _ eventstore.Event) (err error) {
switch mig.dbClient.Type() {
case "cockroach":
_, err = mig.dbClient.ExecContext(ctx, addCacheSchemaCockroach)
case "postgres":
_, err = mig.dbClient.ExecContext(ctx, addCacheSchemaPostgres)
default:
err = fmt.Errorf("add cache schema: unsupported db type %q", mig.dbClient.Type())
}
return err
}
func (mig *AddCacheSchema) String() string {
return "34_add_cache_schema"
}

View File

@ -0,0 +1,27 @@
create schema if not exists cache;
create table if not exists cache.objects (
cache_name varchar not null,
id uuid not null default gen_random_uuid(),
created_at timestamptz not null default now(),
last_used_at timestamptz not null default now(),
payload jsonb not null,
primary key(cache_name, id)
);
create table if not exists cache.string_keys(
cache_name varchar not null check (cache_name <> ''),
index_id integer not null check (index_id > 0),
index_key varchar not null check (index_key <> ''),
object_id uuid not null,
primary key (cache_name, index_id, index_key),
constraint fk_object
foreign key(cache_name, object_id)
references cache.objects(cache_name, id)
on delete cascade
);
create index if not exists string_keys_object_id_idx
on cache.string_keys (cache_name, object_id); -- for delete cascade

View File

@ -0,0 +1,29 @@
create schema if not exists cache;
create unlogged table if not exists cache.objects (
cache_name varchar not null,
id uuid not null default gen_random_uuid(),
created_at timestamptz not null default now(),
last_used_at timestamptz not null default now(),
payload jsonb not null,
primary key(cache_name, id)
)
partition by list (cache_name);
create unlogged table if not exists cache.string_keys(
cache_name varchar not null check (cache_name <> ''),
index_id integer not null check (index_id > 0),
index_key varchar not null check (index_key <> ''),
object_id uuid not null,
primary key (cache_name, index_id, index_key),
constraint fk_object
foreign key(cache_name, object_id)
references cache.objects(cache_name, id)
on delete cascade
)
partition by list (cache_name);
create index if not exists string_keys_object_id_idx
on cache.string_keys (cache_name, object_id); -- for delete cascade

39
cmd/setup/35.go Normal file
View File

@ -0,0 +1,39 @@
package setup
import (
"context"
"embed"
"fmt"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/eventstore"
)
var (
//go:embed 35/*.sql
addPositionToEsWmIndex embed.FS
)
type AddPositionToIndexEsWm struct {
dbClient *database.DB
}
func (mig *AddPositionToIndexEsWm) Execute(ctx context.Context, _ eventstore.Event) error {
statements, err := readStatements(addPositionToEsWmIndex, "35", "")
if err != nil {
return err
}
for _, stmt := range statements {
logging.WithFields("file", stmt.file, "migration", mig.String()).Info("execute statement")
if _, err := mig.dbClient.ExecContext(ctx, stmt.query); err != nil {
return fmt.Errorf("%s %s: %w", mig.String(), stmt.file, err)
}
}
return nil
}
func (mig *AddPositionToIndexEsWm) String() string {
return "35_add_position_to_index_es_wm"
}

View File

@ -0,0 +1,2 @@
CREATE INDEX CONCURRENTLY IF NOT EXISTS es_wm_temp
ON eventstore.events2 (instance_id, aggregate_id, aggregate_type, event_type, "position");

View File

@ -0,0 +1 @@
DROP INDEX IF EXISTS eventstore.es_wm;

View File

@ -0,0 +1 @@
ALTER INDEX eventstore.es_wm_temp RENAME TO es_wm;

View File

@ -90,36 +90,38 @@ func MustNewConfig(v *viper.Viper) *Config {
}
type Steps struct {
s1ProjectionTable *ProjectionTable
s2AssetsTable *AssetTable
FirstInstance *FirstInstance
s5LastFailed *LastFailed
s6OwnerRemoveColumns *OwnerRemoveColumns
s7LogstoreTables *LogstoreTables
s8AuthTokens *AuthTokenIndexes
CorrectCreationDate *CorrectCreationDate
s12AddOTPColumns *AddOTPColumns
s13FixQuotaProjection *FixQuotaConstraints
s14NewEventsTable *NewEventsTable
s15CurrentStates *CurrentProjectionState
s16UniqueConstraintsLower *UniqueConstraintToLower
s17AddOffsetToUniqueConstraints *AddOffsetToCurrentStates
s18AddLowerFieldsToLoginNames *AddLowerFieldsToLoginNames
s19AddCurrentStatesIndex *AddCurrentSequencesIndex
s20AddByUserSessionIndex *AddByUserIndexToSession
s21AddBlockFieldToLimits *AddBlockFieldToLimits
s22ActiveInstancesIndex *ActiveInstanceEvents
s23CorrectGlobalUniqueConstraints *CorrectGlobalUniqueConstraints
s24AddActorToAuthTokens *AddActorToAuthTokens
s25User11AddLowerFieldsToVerifiedEmail *User11AddLowerFieldsToVerifiedEmail
s26AuthUsers3 *AuthUsers3
s27IDPTemplate6SAMLNameIDFormat *IDPTemplate6SAMLNameIDFormat
s28AddFieldTable *AddFieldTable
s29FillFieldsForProjectGrant *FillFieldsForProjectGrant
s30FillFieldsForOrgDomainVerified *FillFieldsForOrgDomainVerified
s31AddAggregateIndexToFields *AddAggregateIndexToFields
s32AddAuthSessionID *AddAuthSessionID
s1ProjectionTable *ProjectionTable
s2AssetsTable *AssetTable
FirstInstance *FirstInstance
s5LastFailed *LastFailed
s6OwnerRemoveColumns *OwnerRemoveColumns
s7LogstoreTables *LogstoreTables
s8AuthTokens *AuthTokenIndexes
CorrectCreationDate *CorrectCreationDate
s12AddOTPColumns *AddOTPColumns
s13FixQuotaProjection *FixQuotaConstraints
s14NewEventsTable *NewEventsTable
s15CurrentStates *CurrentProjectionState
s16UniqueConstraintsLower *UniqueConstraintToLower
s17AddOffsetToUniqueConstraints *AddOffsetToCurrentStates
s18AddLowerFieldsToLoginNames *AddLowerFieldsToLoginNames
s19AddCurrentStatesIndex *AddCurrentSequencesIndex
s20AddByUserSessionIndex *AddByUserIndexToSession
s21AddBlockFieldToLimits *AddBlockFieldToLimits
s22ActiveInstancesIndex *ActiveInstanceEvents
s23CorrectGlobalUniqueConstraints *CorrectGlobalUniqueConstraints
s24AddActorToAuthTokens *AddActorToAuthTokens
s25User11AddLowerFieldsToVerifiedEmail *User11AddLowerFieldsToVerifiedEmail
s26AuthUsers3 *AuthUsers3
s27IDPTemplate6SAMLNameIDFormat *IDPTemplate6SAMLNameIDFormat
s28AddFieldTable *AddFieldTable
s29FillFieldsForProjectGrant *FillFieldsForProjectGrant
s30FillFieldsForOrgDomainVerified *FillFieldsForOrgDomainVerified
s31AddAggregateIndexToFields *AddAggregateIndexToFields
s32AddAuthSessionID *AddAuthSessionID
s33SMSConfigs3TwilioAddVerifyServiceSid *SMSConfigs3TwilioAddVerifyServiceSid
s34AddCacheSchema *AddCacheSchema
s35AddPositionToIndexEsWm *AddPositionToIndexEsWm
}
func MustNewSteps(v *viper.Viper) *Steps {

View File

@ -5,6 +5,7 @@ import (
"embed"
_ "embed"
"net/http"
"path/filepath"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@ -162,6 +163,8 @@ func Setup(ctx context.Context, config *Config, steps *Steps, masterKey string)
steps.s31AddAggregateIndexToFields = &AddAggregateIndexToFields{dbClient: esPusherDBClient}
steps.s32AddAuthSessionID = &AddAuthSessionID{dbClient: esPusherDBClient}
steps.s33SMSConfigs3TwilioAddVerifyServiceSid = &SMSConfigs3TwilioAddVerifyServiceSid{dbClient: esPusherDBClient}
steps.s34AddCacheSchema = &AddCacheSchema{dbClient: queryDBClient}
steps.s35AddPositionToIndexEsWm = &AddPositionToIndexEsWm{dbClient: esPusherDBClient}
err = projection.Create(ctx, projectionDBClient, eventstoreClient, config.Projections, nil, nil, nil)
logging.OnError(err).Fatal("unable to start projections")
@ -204,6 +207,8 @@ func Setup(ctx context.Context, config *Config, steps *Steps, masterKey string)
steps.s26AuthUsers3,
steps.s29FillFieldsForProjectGrant,
steps.s30FillFieldsForOrgDomainVerified,
steps.s34AddCacheSchema,
steps.s35AddPositionToIndexEsWm,
} {
mustExecuteMigration(ctx, eventstoreClient, step, "migration failed")
}
@ -243,11 +248,41 @@ func mustExecuteMigration(ctx context.Context, eventstoreClient *eventstore.Even
logging.WithFields("name", step.String()).OnError(err).Fatal(errorMsg)
}
// readStmt reads a single file from the embedded FS,
// under the folder/typ/filename path.
// Typ describes the database dialect and may be omitted if no
// dialect specific migration is specified.
func readStmt(fs embed.FS, folder, typ, filename string) (string, error) {
stmt, err := fs.ReadFile(folder + "/" + typ + "/" + filename)
stmt, err := fs.ReadFile(filepath.Join(folder, typ, filename))
return string(stmt), err
}
type statement struct {
file string
query string
}
// readStatements reads all files from the embedded FS,
// under the folder/type path.
// Typ describes the database dialect and may be omitted if no
// dialect specific migration is specified.
func readStatements(fs embed.FS, folder, typ string) ([]statement, error) {
basePath := filepath.Join(folder, typ)
dir, err := fs.ReadDir(basePath)
if err != nil {
return nil, err
}
statements := make([]statement, len(dir))
for i, file := range dir {
statements[i].file = file.Name()
statements[i].query, err = readStmt(fs, folder, typ, file.Name())
if err != nil {
return nil, err
}
}
return statements, nil
}
func initProjections(
ctx context.Context,
eventstoreClient *eventstore.Eventstore,

View File

@ -87,6 +87,6 @@
"prettier": "^3.1.1",
"prettier-plugin-organize-imports": "^4.0.0",
"protractor": "~7.0.0",
"typescript": "^5.1.6"
"typescript": "5.1"
}
}

View File

@ -16,6 +16,7 @@ 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 localeHu from '@angular/common/locales/hu';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { MatNativeDateModule } from '@angular/material/core';
import { MatDialogModule } from '@angular/material/dialog';
@ -105,6 +106,8 @@ registerLocaleData(localeNl);
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/nl.json'));
registerLocaleData(localeSv);
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/sv.json'));
registerLocaleData(localeHu);
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/hu.json'));
export class WebpackTranslateLoader implements TranslateLoader {
getTranslation(lang: string): Observable<any> {

View File

@ -198,8 +198,10 @@ export class ProviderSamlSpComponent {
req.setId(this.provider?.id || this.justCreated$.value);
req.setName(this.name?.value);
if (this.metadataXml?.value) {
req.setMetadataUrl('');
req.setMetadataXml(this.metadataXml?.value);
} else {
req.setMetadataXml('');
req.setMetadataUrl(this.metadataUrl?.value);
}
req.setWithSignedRequest(this.withSignedRequest?.value);
@ -210,7 +212,6 @@ export class ProviderSamlSpComponent {
req.setTransientMappingAttributeName(this.transientMapping?.value);
req.setProviderOptions(this.options);
console.log(req);
this.loading = true;
this.service
.updateSAMLProvider(req)
@ -234,8 +235,10 @@ export class ProviderSamlSpComponent {
: new AdminAddSAMLProviderRequest();
req.setName(this.name?.value);
if (this.metadataXml?.value) {
req.setMetadataUrl('');
req.setMetadataXml(this.metadataXml?.value);
} else {
req.setMetadataXml('');
req.setMetadataUrl(this.metadataUrl?.value);
}
req.setProviderOptions(this.options);

View File

@ -15,6 +15,7 @@ export const supportedLanguages = [
'ru',
'nl',
'sv',
'hu',
];
export const supportedLanguagesRegexp: RegExp = /de|en|es|fr|id|it|ja|pl|zh|bg|pt|mk|cs|ru|nl|sv/;
export const supportedLanguagesRegexp: RegExp = /de|en|es|fr|id|it|ja|pl|zh|bg|pt|mk|cs|ru|nl|sv|hu/;
export const fallbackLanguage: string = 'en';

View File

@ -1382,7 +1382,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1383,7 +1383,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1383,7 +1383,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1383,7 +1383,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1384,7 +1384,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1383,7 +1383,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

File diff suppressed because it is too large Load Diff

View File

@ -1261,7 +1261,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1383,7 +1383,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1383,7 +1383,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1384,7 +1384,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1382,7 +1382,8 @@
"cs": "Čeština",
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska"
"sv": "Svenska",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1382,7 +1382,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1384,7 +1384,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1427,7 +1427,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1387,7 +1387,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

View File

@ -1383,7 +1383,8 @@
"ru": "Русский",
"nl": "Nederlands",
"sv": "Svenska",
"id": "Bahasa Indonesia"
"id": "Bahasa Indonesia",
"hu": "Magyar"
}
},
"SMTP": {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
---
title: Actions v2 example execution locally
title: Test Actions Locally
---
In this guide, you will create a ZITADEL execution and target. After a user is created through the API, the target is called.
@ -52,7 +52,7 @@ What happens here is only a target which prints out the received request, which
As you see in the example above the target is created with HTTP and port '8090' and if we want to use it as webhook, the target can be created as follows:
[Create a target](/apis/resources/action_service_v3/action-service-create-target)
[Create a target](/apis/resources/action_service_v3/zitadel-actions-create-target)
```shell
curl -L -X POST 'https://$CUSTOM-DOMAIN/v3alpha/targets' \
@ -75,7 +75,7 @@ Save the returned ID to set in the execution.
To call the target just created before, with the intention to print the request used for user creation by the user V2 API, we define an execution with a method condition.
[Set an execution](/apis/resources/action_service_v3/action-service-set-execution)
[Set an execution](/apis/resources/action_service_v3/zitadel-actions-set-execution)
```shell
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v3alpha/executions' \
@ -116,7 +116,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \
}'
```
Should print out something like, also described under [Sent information Request](./introduction#sent-information-request):
Should print out something like, also described under [Sent information Request](./usage#sent-information-request):
```shell
{
"fullMethod": "/zitadel.user.v2.UserService/AddHumanUser",

View File

@ -1,8 +1,19 @@
---
title: Actions V2
title: Using Actions
---
This page describes the options you have when defining ZITADEL Actions V2.
The Action API provides a flexible mechanism for customizing and extending the functionality of ZITADEL. By allowing you to define targets and executions, you can implement custom workflows triggered on an API requests and responses, events or specific functions.
**How it works:**
- Create Target
- Set Execution with condition and target
- Custom Code will be triggered and executed
**Use Cases:**
- User Management: Automate provisioning user data to external systems when users are crreated, updated or deleted.
- Security: Implement IP blocking or rate limiting based on API usage patterns.
- Extend Workflows: Automatically setup resources in your application, when a new organization in ZITADEL is created.
- Token extension: Add custom claims to the tokens.
## Endpoints
@ -51,7 +62,7 @@ There are different types of Targets:
`InterruptOnError` means that the Execution gets interrupted if any of the calls return with a status code >= 400, and the next Target will not be called anymore.
The API documentation to create a target can be found [here](/apis/resources/action_service_v3/action-service-create-target)
The API documentation to create a target can be found [here](/apis/resources/action_service_v3/zitadel-actions-create-target)
## Execution
@ -65,7 +76,7 @@ The condition can be defined for 4 types of processes:
- `Functions`, handling specific functionality in the logic of ZITADEL
- `Events`, after a specific event happened and was stored in ZITADEL
The API documentation to set an Execution can be found [here](/apis/resources/action_service_v3/action-service-set-execution)
The API documentation to set an Execution can be found [here](/apis/resources/action_service_v3/zitadel-actions-set-execution)
### Condition Best Match
@ -147,19 +158,19 @@ For Request and Response there are 3 levels the condition can be defined:
- `All`, handling any request or response under the ZITADEL API
The available conditions can be found under:
- [All available Methods](/apis/resources/action_service_v3/action-service-list-execution-methods), for example `/zitadel.user.v2.UserService/AddHumanUser`
- [All available Services](/apis/resources/action_service_v3/action-service-list-execution-services), for example `zitadel.user.v2.UserService`
- [All available Methods](/apis/resources/action_service_v3/zitadel-actions-list-execution-methods), for example `/zitadel.user.v2.UserService/AddHumanUser`
- [All available Services](/apis/resources/action_service_v3/zitadel-actions-list-execution-services), for example `zitadel.user.v2.UserService`
### Condition for Functions
Replace the current Actions with the following flows:
- [Internal Authentication](../actions/internal-authentication)
- [External Authentication](../actions/external-authentication)
- [Complement Token](../actions/complement-token)
- [Customize SAML Response](../actions/customize-samlresponse)
- [Internal Authentication](/apis/actions/internal-authentication)
- [External Authentication](/apis/actions/external-authentication)
- [Complement Token](/apis/actions/complement-token)
- [Customize SAML Response](/apis/actions/customize-samlresponse)
The available conditions can be found under [all available Functions](/apis/resources/action_service_v3/action-service-list-execution-functions).
The available conditions can be found under [all available Functions](/apis/resources/action_service_v3/zitadel-actions-list-execution-functions).
### Condition for Events

View File

@ -303,7 +303,6 @@ For easy copying to your reverse proxy configuration, here is the list of URL pa
/saml/v2/
/oauth/v2/
/device
/oidc/v1/
/.well-known/openid-configuration
/openapi/
/idps/callback

View File

@ -219,10 +219,11 @@ Send your `client_id` and `client_secret` as parameters in the body:
</TabItem>
<TabItem value="none">
Send your `code_verifier` for us to recompute the `code_challenge` of the authorization request.
Send your `client_id` and `code_verifier` for us to recompute the `code_challenge` of the authorization request.
| Parameter | Description |
| ------------- | ------------------------------------------------------------ |
| client_id | client_id of the application |
| code_verifier | code_verifier previously used to generate the code_challenge |
</TabItem>

View File

@ -50,6 +50,7 @@ ZITADEL is available in the following languages
- Russian (ru)
- Dutch (nl)
- Swedish (sv)
- Hungarian (hu)
A language is displayed based on your agent's language header.
If a users language header doesn't match any of the supported or [restricted](#restrict-languages) languages, the instances default language will be used.

View File

@ -31,7 +31,7 @@ LATEST=$(curl -i https://github.com/zitadel/zitadel/releases/latest | grep locat
## Run ZITADEL
```bash
ZITADEL_DATABASE_POSTGRES_HOST=localhost 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=root ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable ZITADEL_EXTERNALSECURE=false zitadel start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled
ZITADEL_DATABASE_POSTGRES_HOST=localhost 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=root ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD=postgres ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable ZITADEL_EXTERNALSECURE=false zitadel start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled
```
<DefaultUser components={props.components} />

View File

@ -43,7 +43,7 @@ LATEST=$(curl -i https://github.com/zitadel/zitadel/releases/latest | grep locat
## Run ZITADEL
```bash
ZITADEL_DATABASE_POSTGRES_HOST=localhost 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=$(whoami) ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable ZITADEL_EXTERNALSECURE=false zitadel start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled
ZITADEL_DATABASE_POSTGRES_HOST=localhost 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=$(whoami) ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD=postgres ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable ZITADEL_EXTERNALSECURE=false zitadel start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled
```
<DefaultUser components={props.components} />

View File

@ -7,7 +7,7 @@ http {
http2 on;
location / {
grpc_pass grpc://zitadel-disabled-tls:8080;
grpc_set_header Host $host:$server_port;
grpc_set_header Host $host;
}
}
}

View File

@ -9,7 +9,7 @@ http {
ssl_certificate_key /etc/certs/selfsigned.key;
location / {
grpc_pass grpcs://zitadel-enabled-tls:8080;
grpc_set_header Host $host:$server_port;
grpc_set_header Host $host;
}
}
}

View File

@ -9,7 +9,7 @@ http {
ssl_certificate_key /etc/certs/selfsigned.key;
location / {
grpc_pass grpc://zitadel-external-tls:8080;
grpc_set_header Host $host:$server_port;
grpc_set_header Host $host;
}
}
}

View File

@ -745,10 +745,20 @@ module.exports = {
slug: "/apis/resources/action_service_v3",
description:
"This API is intended to manage custom executions and targets (previously known as actions) in a ZITADEL instance.\n" +
"The version 3 of actions provide much more options to customize ZITADELs behaviour than previous action versions.\n" +
"Also, v3 actions are available instance-wide, whereas previous actions had to be managed for each organization individually\n" +
"ZITADEL doesn't restrict the implementation languages, tooling and runtime for v3 action executions anymore.\n" +
"Instead, it calls external endpoints which are implemented and maintained by action v3 users.\n" +
"\n" +
"This project is in Preview state. It can AND will continue breaking until the services provide the same functionality as the current actions.",
},
items: require("./docs/apis/resources/action_service_v3/sidebar.ts"),
items: [{
type: "doc",
id: "apis/actions/v3/usage",
}, {
type: "doc",
id: "apis/actions/v3/testing-locally",
}].concat(require("./docs/apis/resources/action_service_v3/sidebar.ts")),
},
{
type: "category",
@ -815,12 +825,6 @@ module.exports = {
"apis/actions/objects",
],
},
{
type: "category",
label: "Actions V2",
collapsed: false,
items: ["apis/actionsv2/introduction", "apis/actionsv2/execution-local"],
},
{
type: "doc",
label: "gRPC Status Codes",

View File

@ -24,6 +24,8 @@
{ "source": "/docs/apis/auth/:slug*", "destination": "/docs/apis/resources/auth/:slug*", "permanent": true },
{ "source": "/docs/apis/system/:slug*", "destination": "/docs/apis/resources/system/:slug*", "permanent": true },
{ "source": "/docs/apis/admin/:slug*", "destination": "/docs/apis/resources/admin/:slug*", "permanent": true },
{ "source": "/docs/apis/actionsv2/introduction", "destination": "/docs/apis/actions/v3/usage", "permanent": true },
{ "source": "/docs/apis/actionsv2/execution-local", "destination": "/docs/apis/actions/v3/testing-locally", "permanent": true },
{ "source": "/docs/guides/integrate/human-users", "destination": "/docs/guides/integrate/login", "permanent": true },
{ "source": "/docs/guides/solution-scenarios/device-authorization", "destination": "/docs/guides/integrate/login/oidc/device-authorization", "permanent": true },
{ "source": "/docs/guides/integrate/oauth-recommended-flows", "destination": "/docs/guides/integrate/login/oidc/oauth-recommended-flows", "permanent": true },

9
go.mod
View File

@ -38,7 +38,7 @@ require (
github.com/h2non/gock v1.2.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/improbable-eng/grpc-web v0.15.0
github.com/jackc/pgx/v5 v5.6.0
github.com/jackc/pgx/v5 v5.7.0
github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52
github.com/jinzhu/gorm v1.9.16
github.com/k3a/html2text v1.2.1
@ -49,6 +49,7 @@ require (
github.com/muhlemmer/gu v0.3.1
github.com/muhlemmer/httpforwarded v0.1.0
github.com/nicksnyder/go-i18n/v2 v2.4.0
github.com/pashagolub/pgxmock/v4 v4.3.0
github.com/pquerna/otp v1.4.0
github.com/rakyll/statik v0.1.7
github.com/rs/cors v1.11.0
@ -76,12 +77,12 @@ require (
go.opentelemetry.io/otel/sdk/metric v1.28.0
go.opentelemetry.io/otel/trace v1.28.0
go.uber.org/mock v0.4.0
golang.org/x/crypto v0.25.0
golang.org/x/crypto v0.27.0
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
golang.org/x/net v0.26.0
golang.org/x/oauth2 v0.22.0
golang.org/x/sync v0.8.0
golang.org/x/text v0.17.0
golang.org/x/text v0.18.0
google.golang.org/api v0.187.0
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094
google.golang.org/grpc v1.65.0
@ -169,7 +170,7 @@ require (
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jonboulle/clockwork v0.4.0
github.com/klauspost/compress v1.17.9 // indirect

18
go.sum
View File

@ -400,10 +400,10 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.0 h1:FG6VLIdzvAPhnYqP14sQ2xhFLkiUQHCs6ySqO91kF4g=
github.com/jackc/pgx/v5 v5.7.0/go.mod h1:awP1KNnjylvpxHuHP63gzjhnGkI1iw+PMoIwvoleN/8=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52 h1:jny9eqYPwkG8IVy7foUoRjQmFLcArCSz+uPsL6KS0HQ=
@ -567,6 +567,8 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pashagolub/pgxmock/v4 v4.3.0 h1:DqT7fk0OCK6H0GvqtcMsLpv8cIwWqdxWgfZNLeHCb/s=
github.com/pashagolub/pgxmock/v4 v4.3.0/go.mod h1:9VoVHXwS3XR/yPtKGzwQvwZX1kzGB9sM8SviDcHDa3A=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
@ -791,8 +793,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
@ -932,8 +934,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=

View File

@ -42,6 +42,8 @@ func TestMain(m *testing.M) {
}
func TestServer_AddOrganization(t *testing.T) {
t.Parallel()
idpResp := Instance.AddGenericOAuthProvider(CTX, Instance.DefaultOrg.Id)
tests := []struct {

View File

@ -26,6 +26,8 @@ type orgAttr struct {
}
func TestServer_ListOrganizations(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *org.ListOrganizationsRequest
@ -37,6 +39,38 @@ func TestServer_ListOrganizations(t *testing.T) {
want *org.ListOrganizationsResponse
wantErr bool
}{
{
name: "list org by default, ok",
args: args{
CTX,
&org.ListOrganizationsRequest{
Queries: []*org.SearchQuery{
DefaultOrganizationQuery(),
},
},
nil,
},
want: &org.ListOrganizationsResponse{
Details: &object.ListDetails{
TotalResult: 1,
Timestamp: timestamppb.Now(),
},
SortingColumn: 0,
Result: []*org.Organization{
{
Id: Instance.DefaultOrg.Id,
Name: Instance.DefaultOrg.Name,
PrimaryDomain: Instance.DefaultOrg.PrimaryDomain,
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
Details: &object.Details{
Sequence: Instance.DefaultOrg.Details.Sequence,
ChangeDate: Instance.DefaultOrg.Details.ChangeDate,
ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner,
},
},
},
},
},
{
name: "list org by id, ok, multiple",
args: args{
@ -401,6 +435,12 @@ func TestServer_ListOrganizations(t *testing.T) {
}
}
func DefaultOrganizationQuery() *org.SearchQuery {
return &org.SearchQuery{Query: &org.SearchQuery_DefaultQuery{
DefaultQuery: &org.DefaultOrganizationQuery{},
}}
}
func OrganizationIdQuery(resourceowner string) *org.SearchQuery {
return &org.SearchQuery{Query: &org.SearchQuery_IdQuery{
IdQuery: &org.OrganizationIDQuery{

View File

@ -3,6 +3,7 @@ package org
import (
"context"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/query"
@ -11,7 +12,7 @@ import (
)
func (s *Server) ListOrganizations(ctx context.Context, req *org.ListOrganizationsRequest) (*org.ListOrganizationsResponse, error) {
queries, err := listOrgRequestToModel(req)
queries, err := listOrgRequestToModel(ctx, req)
if err != nil {
return nil, err
}
@ -25,9 +26,9 @@ func (s *Server) ListOrganizations(ctx context.Context, req *org.ListOrganizatio
}, nil
}
func listOrgRequestToModel(req *org.ListOrganizationsRequest) (*query.OrgSearchQueries, error) {
func listOrgRequestToModel(ctx context.Context, req *org.ListOrganizationsRequest) (*query.OrgSearchQueries, error) {
offset, limit, asc := object.ListQueryToQuery(req.Query)
queries, err := orgQueriesToQuery(req.Queries)
queries, err := orgQueriesToQuery(ctx, req.Queries)
if err != nil {
return nil, err
}
@ -42,10 +43,10 @@ func listOrgRequestToModel(req *org.ListOrganizationsRequest) (*query.OrgSearchQ
}, nil
}
func orgQueriesToQuery(queries []*org.SearchQuery) (_ []query.SearchQuery, err error) {
func orgQueriesToQuery(ctx context.Context, queries []*org.SearchQuery) (_ []query.SearchQuery, err error) {
q := make([]query.SearchQuery, len(queries))
for i, query := range queries {
q[i], err = orgQueryToQuery(query)
q[i], err = orgQueryToQuery(ctx, query)
if err != nil {
return nil, err
}
@ -53,7 +54,7 @@ func orgQueriesToQuery(queries []*org.SearchQuery) (_ []query.SearchQuery, err e
return q, nil
}
func orgQueryToQuery(orgQuery *org.SearchQuery) (query.SearchQuery, error) {
func orgQueryToQuery(ctx context.Context, orgQuery *org.SearchQuery) (query.SearchQuery, error) {
switch q := orgQuery.Query.(type) {
case *org.SearchQuery_DomainQuery:
return query.NewOrgDomainSearchQuery(object.TextMethodToQuery(q.DomainQuery.Method), q.DomainQuery.Domain)
@ -63,6 +64,8 @@ func orgQueryToQuery(orgQuery *org.SearchQuery) (query.SearchQuery, error) {
return query.NewOrgStateSearchQuery(orgStateToDomain(q.StateQuery.State))
case *org.SearchQuery_IdQuery:
return query.NewOrgIDSearchQuery(q.IdQuery.Id)
case *org.SearchQuery_DefaultQuery:
return query.NewOrgIDSearchQuery(authz.GetInstance(ctx).DefaultOrganisationID())
default:
return nil, zerrors.ThrowInvalidArgument(nil, "ORG-vR9nC", "List.Query.Invalid")
}

View File

@ -13,11 +13,13 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/integration"
object "github.com/zitadel/zitadel/pkg/grpc/object/v2"
user "github.com/zitadel/zitadel/pkg/grpc/user/v2"
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
)
func TestServer_SetEmail(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
tests := []struct {
@ -144,6 +146,8 @@ func TestServer_SetEmail(t *testing.T) {
}
func TestServer_ResendEmailCode(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
verifiedUserID := Instance.CreateHumanUserVerified(CTX, Instance.DefaultOrg.Id, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId()
@ -245,6 +249,8 @@ func TestServer_ResendEmailCode(t *testing.T) {
}
func TestServer_VerifyEmail(t *testing.T) {
t.Parallel()
userResp := Instance.CreateHumanUser(CTX)
tests := []struct {
name string

View File

@ -19,6 +19,8 @@ import (
)
func TestServer_AddIDPLink(t *testing.T) {
t.Parallel()
idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id)
type args struct {
ctx context.Context
@ -99,6 +101,8 @@ func TestServer_AddIDPLink(t *testing.T) {
}
func TestServer_ListIDPLinks(t *testing.T) {
t.Parallel()
orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("ListIDPLinks%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
instanceIdpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id)
@ -258,6 +262,8 @@ func TestServer_ListIDPLinks(t *testing.T) {
}
func TestServer_RemoveIDPLink(t *testing.T) {
t.Parallel()
orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("ListIDPLinks%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
instanceIdpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id)

View File

@ -15,6 +15,8 @@ import (
)
func TestServer_AddOTPSMS(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -121,6 +123,8 @@ func TestServer_AddOTPSMS(t *testing.T) {
}
func TestServer_RemoveOTPSMS(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -187,6 +191,8 @@ func TestServer_RemoveOTPSMS(t *testing.T) {
}
func TestServer_AddOTPEmail(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -295,6 +301,8 @@ func TestServer_AddOTPEmail(t *testing.T) {
}
func TestServer_RemoveOTPEmail(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)

View File

@ -19,6 +19,8 @@ import (
)
func TestServer_RegisterPasskey(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
reg, err := Client.CreatePasskeyRegistrationLink(CTX, &user.CreatePasskeyRegistrationLinkRequest{
UserId: userID,
@ -139,6 +141,8 @@ func TestServer_RegisterPasskey(t *testing.T) {
}
func TestServer_VerifyPasskeyRegistration(t *testing.T) {
t.Parallel()
userID, pkr := userWithPasskeyRegistered(t)
attestationResponse, err := Instance.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions())
@ -215,6 +219,8 @@ func TestServer_VerifyPasskeyRegistration(t *testing.T) {
}
func TestServer_CreatePasskeyRegistrationLink(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
type args struct {
@ -348,6 +354,8 @@ func passkeyVerify(t *testing.T, userID string, pkr *user.RegisterPasskeyRespons
}
func TestServer_RemovePasskey(t *testing.T) {
t.Parallel()
userIDWithout := Instance.CreateHumanUser(CTX).GetUserId()
userIDRegistered, pkrRegistered := userWithPasskeyRegistered(t)
userIDVerified, passkeyIDVerified := userWithPasskeyVerified(t)
@ -453,6 +461,8 @@ func TestServer_RemovePasskey(t *testing.T) {
}
func TestServer_ListPasskeys(t *testing.T) {
t.Parallel()
userIDWithout := Instance.CreateHumanUser(CTX).GetUserId()
userIDRegistered, _ := userWithPasskeyRegistered(t)
userIDVerified, passkeyIDVerified := userWithPasskeyVerified(t)

View File

@ -12,11 +12,13 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/integration"
object "github.com/zitadel/zitadel/pkg/grpc/object/v2"
user "github.com/zitadel/zitadel/pkg/grpc/user/v2"
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
)
func TestServer_RequestPasswordReset(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
tests := []struct {
@ -104,6 +106,8 @@ func TestServer_RequestPasswordReset(t *testing.T) {
}
func TestServer_SetPassword(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.SetPasswordRequest

View File

@ -14,11 +14,13 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/integration"
object "github.com/zitadel/zitadel/pkg/grpc/object/v2"
user "github.com/zitadel/zitadel/pkg/grpc/user/v2"
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
)
func TestServer_SetPhone(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
tests := []struct {
@ -122,6 +124,8 @@ func TestServer_SetPhone(t *testing.T) {
}
func TestServer_ResendPhoneCode(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
verifiedUserID := Instance.CreateHumanUserVerified(CTX, Instance.DefaultOrg.Id, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId()
@ -196,6 +200,8 @@ func TestServer_ResendPhoneCode(t *testing.T) {
}
func TestServer_VerifyPhone(t *testing.T) {
t.Parallel()
userResp := Instance.CreateHumanUser(CTX)
tests := []struct {
name string
@ -248,6 +254,8 @@ func TestServer_VerifyPhone(t *testing.T) {
}
func TestServer_RemovePhone(t *testing.T) {
t.Parallel()
userResp := Instance.CreateHumanUser(CTX)
failResp := Instance.CreateHumanUserNoPhone(CTX)
otherUser := Instance.CreateHumanUser(CTX).GetUserId()

View File

@ -19,6 +19,8 @@ import (
)
func TestServer_GetUserByID(t *testing.T) {
t.Parallel()
orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("GetUserByIDOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
type args struct {
ctx context.Context
@ -187,6 +189,8 @@ func TestServer_GetUserByID(t *testing.T) {
}
func TestServer_GetUserByID_Permission(t *testing.T) {
t.Parallel()
timeNow := time.Now().UTC()
newOrgOwnerEmail := fmt.Sprintf("%d@permission.get.com", timeNow.UnixNano())
newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("GetHuman%d", time.Now().UnixNano()), newOrgOwnerEmail)
@ -329,6 +333,8 @@ type userAttr struct {
}
func TestServer_ListUsers(t *testing.T) {
t.Parallel()
orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("ListUsersOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
userResp := Instance.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listusers.com", time.Now().UnixNano()))
type args struct {

View File

@ -18,6 +18,8 @@ import (
)
func TestServer_RegisterTOTP(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -104,6 +106,8 @@ func TestServer_RegisterTOTP(t *testing.T) {
}
func TestServer_VerifyTOTPRegistration(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -207,6 +211,8 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) {
}
func TestServer_RemoveTOTP(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)

View File

@ -17,6 +17,8 @@ import (
)
func TestServer_RegisterU2F(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
otherUser := Instance.CreateHumanUser(CTX).GetUserId()
@ -106,6 +108,8 @@ func TestServer_RegisterU2F(t *testing.T) {
}
func TestServer_VerifyU2FRegistration(t *testing.T) {
t.Parallel()
ctx, userID, pkr := ctxFromNewUserWithRegisteredU2F(t)
attestationResponse, err := Instance.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions())
@ -211,6 +215,8 @@ func ctxFromNewUserWithVerifiedU2F(t *testing.T) (context.Context, string, strin
}
func TestServer_RemoveU2F(t *testing.T) {
t.Parallel()
userIDWithout := Instance.CreateHumanUser(CTX).GetUserId()
ctxRegistered, userIDRegistered, pkrRegistered := ctxFromNewUserWithRegisteredU2F(t)
_, userIDVerified, u2fVerified := ctxFromNewUserWithVerifiedU2F(t)

View File

@ -18,9 +18,11 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/integration"
"github.com/zitadel/zitadel/pkg/grpc/auth"
"github.com/zitadel/zitadel/pkg/grpc/idp"
mgmt "github.com/zitadel/zitadel/pkg/grpc/management"
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
user_v1 "github.com/zitadel/zitadel/pkg/grpc/user"
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
)
@ -50,6 +52,8 @@ func TestMain(m *testing.M) {
}
func TestServer_AddHumanUser(t *testing.T) {
t.Parallel()
idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id)
type args struct {
ctx context.Context
@ -672,6 +676,8 @@ func TestServer_AddHumanUser(t *testing.T) {
}
func TestServer_AddHumanUser_Permission(t *testing.T) {
t.Parallel()
newOrgOwnerEmail := fmt.Sprintf("%d@permission.com", time.Now().UnixNano())
newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("AddHuman%d", time.Now().UnixNano()), newOrgOwnerEmail)
type args struct {
@ -865,6 +871,8 @@ func TestServer_AddHumanUser_Permission(t *testing.T) {
}
func TestServer_UpdateHumanUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.UpdateHumanUserRequest
@ -1221,6 +1229,8 @@ func TestServer_UpdateHumanUser(t *testing.T) {
}
func TestServer_UpdateHumanUser_Permission(t *testing.T) {
t.Parallel()
newOrgOwnerEmail := fmt.Sprintf("%d@permission.update.com", time.Now().UnixNano())
newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("UpdateHuman%d", time.Now().UnixNano()), newOrgOwnerEmail)
newUserID := newOrg.CreatedAdmins[0].GetUserId()
@ -1304,6 +1314,8 @@ func TestServer_UpdateHumanUser_Permission(t *testing.T) {
}
func TestServer_LockUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.LockUserRequest
@ -1412,6 +1424,8 @@ func TestServer_LockUser(t *testing.T) {
}
func TestServer_UnLockUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.UnlockUserRequest
@ -1520,6 +1534,8 @@ func TestServer_UnLockUser(t *testing.T) {
}
func TestServer_DeactivateUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.DeactivateUserRequest
@ -1628,6 +1644,8 @@ func TestServer_DeactivateUser(t *testing.T) {
}
func TestServer_ReactivateUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.ReactivateUserRequest
@ -1736,6 +1754,8 @@ func TestServer_ReactivateUser(t *testing.T) {
}
func TestServer_DeleteUser(t *testing.T) {
t.Parallel()
projectResp, err := Instance.CreateProject(CTX)
require.NoError(t, err)
type args struct {
@ -1835,6 +1855,8 @@ func TestServer_DeleteUser(t *testing.T) {
}
func TestServer_StartIdentityProviderIntent(t *testing.T) {
t.Parallel()
idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id)
orgIdpResp := Instance.AddOrgGenericOAuthProvider(CTX, Instance.DefaultOrg.Id)
orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("NotDefaultOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
@ -2099,6 +2121,8 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) {
/*
func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
t.Parallel()
idpID := Instance.AddGenericOAuthProvider(t, CTX)
intentID := Instance.CreateIntent(t, CTX, idpID)
successfulID, token, changeDate, sequence := Instance.CreateSuccessfulOAuthIntent(t, CTX, idpID, "", "id")
@ -2358,7 +2382,37 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
}
*/
func ctxFromNewUserWithRegisteredPasswordlessLegacy(t *testing.T) (context.Context, string, *auth.AddMyPasswordlessResponse) {
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
ctx := integration.WithAuthorizationToken(CTX, sessionToken)
pkr, err := Instance.Client.Auth.AddMyPasswordless(ctx, &auth.AddMyPasswordlessRequest{})
require.NoError(t, err)
require.NotEmpty(t, pkr.GetKey())
return ctx, userID, pkr
}
func ctxFromNewUserWithVerifiedPasswordlessLegacy(t *testing.T) (context.Context, string) {
ctx, userID, pkr := ctxFromNewUserWithRegisteredPasswordlessLegacy(t)
attestationResponse, err := Instance.WebAuthN.CreateAttestationResponseData(pkr.GetKey().GetPublicKey())
require.NoError(t, err)
_, err = Instance.Client.Auth.VerifyMyPasswordless(ctx, &auth.VerifyMyPasswordlessRequest{
Verification: &user_v1.WebAuthNVerification{
TokenName: "Mickey",
PublicKeyCredential: attestationResponse,
},
})
require.NoError(t, err)
return ctx, userID
}
func TestServer_ListAuthenticationMethodTypes(t *testing.T) {
t.Parallel()
userIDWithoutAuth := Instance.CreateHumanUser(CTX).GetUserId()
userIDWithPasskey := Instance.CreateHumanUser(CTX).GetUserId()
@ -2395,6 +2449,9 @@ func TestServer_ListAuthenticationMethodTypes(t *testing.T) {
})
require.NoError(t, err)
_, userLegacyID := ctxFromNewUserWithVerifiedPasswordlessLegacy(t)
require.NoError(t, err)
type args struct {
ctx context.Context
req *user.ListAuthenticationMethodTypesRequest
@ -2435,6 +2492,81 @@ func TestServer_ListAuthenticationMethodTypes(t *testing.T) {
},
},
},
{
name: "with auth (passkey) with domain",
args: args{
CTX,
&user.ListAuthenticationMethodTypesRequest{
UserId: userIDWithPasskey,
DomainQuery: &user.DomainQuery{
Domain: Instance.Domain,
},
},
},
want: &user.ListAuthenticationMethodTypesResponse{
Details: &object.ListDetails{
TotalResult: 1,
},
AuthMethodTypes: []user.AuthenticationMethodType{
user.AuthenticationMethodType_AUTHENTICATION_METHOD_TYPE_PASSKEY,
},
},
},
{
name: "with auth (passkey) with wrong domain",
args: args{
CTX,
&user.ListAuthenticationMethodTypesRequest{
UserId: userIDWithPasskey,
DomainQuery: &user.DomainQuery{
Domain: "notexistent",
},
},
},
want: &user.ListAuthenticationMethodTypesResponse{
Details: &object.ListDetails{
TotalResult: 0,
},
},
},
{
name: "with auth (passkey) with legacy",
args: args{
CTX,
&user.ListAuthenticationMethodTypesRequest{
UserId: userLegacyID,
DomainQuery: &user.DomainQuery{
Domain: "notexistent",
},
},
},
want: &user.ListAuthenticationMethodTypesResponse{
Details: &object.ListDetails{
TotalResult: 0,
},
},
},
{
name: "with auth (passkey) with legacy included",
args: args{
CTX,
&user.ListAuthenticationMethodTypesRequest{
UserId: userLegacyID,
DomainQuery: &user.DomainQuery{
Domain: "notexistent",
IncludeWithoutDomain: true,
},
},
},
want: &user.ListAuthenticationMethodTypesResponse{
Details: &object.ListDetails{
TotalResult: 1,
},
AuthMethodTypes: []user.AuthenticationMethodType{
user.AuthenticationMethodType_AUTHENTICATION_METHOD_TYPE_PASSKEY,
},
},
},
{
name: "multiple auth",
args: args{
@ -2453,6 +2585,47 @@ func TestServer_ListAuthenticationMethodTypes(t *testing.T) {
},
},
},
{
name: "multiple auth with domain",
args: args{
CTX,
&user.ListAuthenticationMethodTypesRequest{
UserId: userMultipleAuth,
DomainQuery: &user.DomainQuery{
Domain: Instance.Domain,
},
},
},
want: &user.ListAuthenticationMethodTypesResponse{
Details: &object.ListDetails{
TotalResult: 2,
},
AuthMethodTypes: []user.AuthenticationMethodType{
user.AuthenticationMethodType_AUTHENTICATION_METHOD_TYPE_PASSKEY,
user.AuthenticationMethodType_AUTHENTICATION_METHOD_TYPE_IDP,
},
},
},
{
name: "multiple auth with wrong domain",
args: args{
CTX,
&user.ListAuthenticationMethodTypesRequest{
UserId: userMultipleAuth,
DomainQuery: &user.DomainQuery{
Domain: "notexistent",
},
},
},
want: &user.ListAuthenticationMethodTypesResponse{
Details: &object.ListDetails{
TotalResult: 1,
},
AuthMethodTypes: []user.AuthenticationMethodType{
user.AuthenticationMethodType_AUTHENTICATION_METHOD_TYPE_IDP,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -2480,6 +2653,8 @@ func TestServer_ListAuthenticationMethodTypes(t *testing.T) {
}
func TestServer_CreateInviteCode(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.CreateInviteCodeRequest
@ -2610,6 +2785,8 @@ func TestServer_CreateInviteCode(t *testing.T) {
}
func TestServer_ResendInviteCode(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.ResendInviteCodeRequest
@ -2698,6 +2875,8 @@ func TestServer_ResendInviteCode(t *testing.T) {
}
func TestServer_VerifyInviteCode(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.VerifyInviteCodeRequest

View File

@ -587,7 +587,7 @@ func (s *Server) checkIntentToken(token string, intentID string) error {
}
func (s *Server) ListAuthenticationMethodTypes(ctx context.Context, req *user.ListAuthenticationMethodTypesRequest) (*user.ListAuthenticationMethodTypesResponse, error) {
authMethods, err := s.query.ListUserAuthMethodTypes(ctx, req.GetUserId(), true)
authMethods, err := s.query.ListUserAuthMethodTypes(ctx, req.GetUserId(), true, req.GetDomainQuery().GetIncludeWithoutDomain(), req.GetDomainQuery().GetDomain())
if err != nil {
return nil, err
}

View File

@ -18,6 +18,8 @@ import (
)
func TestServer_SetEmail(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
tests := []struct {
@ -144,6 +146,8 @@ func TestServer_SetEmail(t *testing.T) {
}
func TestServer_ResendEmailCode(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
verifiedUserID := Instance.CreateHumanUserVerified(CTX, Instance.DefaultOrg.Id, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId()
@ -245,6 +249,8 @@ func TestServer_ResendEmailCode(t *testing.T) {
}
func TestServer_VerifyEmail(t *testing.T) {
t.Parallel()
userResp := Instance.CreateHumanUser(CTX)
tests := []struct {
name string

View File

@ -15,6 +15,8 @@ import (
)
func TestServer_AddOTPSMS(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -121,6 +123,8 @@ func TestServer_AddOTPSMS(t *testing.T) {
}
func TestServer_RemoveOTPSMS(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -187,6 +191,8 @@ func TestServer_RemoveOTPSMS(t *testing.T) {
}
func TestServer_AddOTPEmail(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -295,6 +301,8 @@ func TestServer_AddOTPEmail(t *testing.T) {
}
func TestServer_RemoveOTPEmail(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)

View File

@ -18,6 +18,8 @@ import (
)
func TestServer_RegisterPasskey(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
reg, err := Client.CreatePasskeyRegistrationLink(CTX, &user.CreatePasskeyRegistrationLinkRequest{
UserId: userID,
@ -138,6 +140,8 @@ func TestServer_RegisterPasskey(t *testing.T) {
}
func TestServer_VerifyPasskeyRegistration(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
reg, err := Client.CreatePasskeyRegistrationLink(CTX, &user.CreatePasskeyRegistrationLinkRequest{
UserId: userID,
@ -226,6 +230,8 @@ func TestServer_VerifyPasskeyRegistration(t *testing.T) {
}
func TestServer_CreatePasskeyRegistrationLink(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
type args struct {

View File

@ -17,6 +17,8 @@ import (
)
func TestServer_RequestPasswordReset(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
tests := []struct {
@ -104,6 +106,8 @@ func TestServer_RequestPasswordReset(t *testing.T) {
}
func TestServer_SetPassword(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.SetPasswordRequest

View File

@ -19,6 +19,8 @@ import (
)
func TestServer_SetPhone(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
tests := []struct {
@ -122,6 +124,8 @@ func TestServer_SetPhone(t *testing.T) {
}
func TestServer_ResendPhoneCode(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
verifiedUserID := Instance.CreateHumanUserVerified(CTX, Instance.DefaultOrg.Id, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId()
@ -196,6 +200,8 @@ func TestServer_ResendPhoneCode(t *testing.T) {
}
func TestServer_VerifyPhone(t *testing.T) {
t.Parallel()
userResp := Instance.CreateHumanUser(CTX)
tests := []struct {
name string
@ -248,6 +254,8 @@ func TestServer_VerifyPhone(t *testing.T) {
}
func TestServer_RemovePhone(t *testing.T) {
t.Parallel()
userResp := Instance.CreateHumanUser(CTX)
failResp := Instance.CreateHumanUserNoPhone(CTX)
otherUser := Instance.CreateHumanUser(CTX).GetUserId()

View File

@ -28,6 +28,8 @@ func detailsV2ToV2beta(obj *object.Details) *object_v2beta.Details {
}
func TestServer_GetUserByID(t *testing.T) {
t.Parallel()
orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("GetUserByIDOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
type args struct {
ctx context.Context
@ -196,6 +198,8 @@ func TestServer_GetUserByID(t *testing.T) {
}
func TestServer_GetUserByID_Permission(t *testing.T) {
t.Parallel()
timeNow := time.Now().UTC()
newOrgOwnerEmail := fmt.Sprintf("%d@permission.get.com", timeNow.UnixNano())
newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("GetHuman%d", time.Now().UnixNano()), newOrgOwnerEmail)
@ -338,6 +342,8 @@ type userAttr struct {
}
func TestServer_ListUsers(t *testing.T) {
t.Parallel()
orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("ListUsersOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
userResp := Instance.CreateHumanUserVerified(IamCTX, orgResp.OrganizationId, fmt.Sprintf("%d@listusers.com", time.Now().UnixNano()))
type args struct {

View File

@ -18,6 +18,8 @@ import (
)
func TestServer_RegisterTOTP(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -104,6 +106,8 @@ func TestServer_RegisterTOTP(t *testing.T) {
}
func TestServer_VerifyTOTPRegistration(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)
@ -212,6 +216,8 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) {
}
func TestServer_RemoveTOTP(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)

View File

@ -17,6 +17,8 @@ import (
)
func TestServer_RegisterU2F(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
otherUser := Instance.CreateHumanUser(CTX).GetUserId()
@ -106,6 +108,8 @@ func TestServer_RegisterU2F(t *testing.T) {
}
func TestServer_VerifyU2FRegistration(t *testing.T) {
t.Parallel()
userID := Instance.CreateHumanUser(CTX).GetUserId()
Instance.RegisterUserPasskey(CTX, userID)
_, sessionToken, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userID)

View File

@ -50,6 +50,8 @@ func TestMain(m *testing.M) {
}
func TestServer_AddHumanUser(t *testing.T) {
t.Parallel()
idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id)
type args struct {
ctx context.Context
@ -631,6 +633,8 @@ func TestServer_AddHumanUser(t *testing.T) {
}
func TestServer_AddHumanUser_Permission(t *testing.T) {
t.Parallel()
newOrgOwnerEmail := fmt.Sprintf("%d@permission.com", time.Now().UnixNano())
newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("AddHuman%d", time.Now().UnixNano()), newOrgOwnerEmail)
type args struct {
@ -824,6 +828,8 @@ func TestServer_AddHumanUser_Permission(t *testing.T) {
}
func TestServer_UpdateHumanUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.UpdateHumanUserRequest
@ -1180,6 +1186,8 @@ func TestServer_UpdateHumanUser(t *testing.T) {
}
func TestServer_UpdateHumanUser_Permission(t *testing.T) {
t.Parallel()
newOrgOwnerEmail := fmt.Sprintf("%d@permission.update.com", time.Now().UnixNano())
newOrg := Instance.CreateOrganization(IamCTX, fmt.Sprintf("UpdateHuman%d", time.Now().UnixNano()), newOrgOwnerEmail)
newUserID := newOrg.CreatedAdmins[0].GetUserId()
@ -1263,6 +1271,8 @@ func TestServer_UpdateHumanUser_Permission(t *testing.T) {
}
func TestServer_LockUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.LockUserRequest
@ -1371,6 +1381,8 @@ func TestServer_LockUser(t *testing.T) {
}
func TestServer_UnLockUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.UnlockUserRequest
@ -1479,6 +1491,8 @@ func TestServer_UnLockUser(t *testing.T) {
}
func TestServer_DeactivateUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.DeactivateUserRequest
@ -1587,6 +1601,8 @@ func TestServer_DeactivateUser(t *testing.T) {
}
func TestServer_ReactivateUser(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
req *user.ReactivateUserRequest
@ -1695,6 +1711,8 @@ func TestServer_ReactivateUser(t *testing.T) {
}
func TestServer_DeleteUser(t *testing.T) {
t.Parallel()
projectResp, err := Instance.CreateProject(CTX)
require.NoError(t, err)
type args struct {
@ -1794,6 +1812,8 @@ func TestServer_DeleteUser(t *testing.T) {
}
func TestServer_AddIDPLink(t *testing.T) {
t.Parallel()
idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id)
type args struct {
ctx context.Context
@ -1874,6 +1894,8 @@ func TestServer_AddIDPLink(t *testing.T) {
}
func TestServer_StartIdentityProviderIntent(t *testing.T) {
t.Parallel()
idpResp := Instance.AddGenericOAuthProvider(IamCTX, Instance.DefaultOrg.Id)
orgIdpID := Instance.AddOrgGenericOAuthProvider(CTX, Instance.DefaultOrg.Id)
orgResp := Instance.CreateOrganization(IamCTX, fmt.Sprintf("NotDefaultOrg%d", time.Now().UnixNano()), fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
@ -2138,6 +2160,8 @@ func TestServer_StartIdentityProviderIntent(t *testing.T) {
/*
func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
t.Parallel()
idpID := Instance.AddGenericOAuthProvider(t, CTX)
intentID := Instance.CreateIntent(t, CTX, idpID)
successfulID, token, changeDate, sequence := Instance.CreateSuccessfulOAuthIntent(t, CTX, idpID.Id, "", "id")
@ -2398,6 +2422,8 @@ func TestServer_RetrieveIdentityProviderIntent(t *testing.T) {
*/
func TestServer_ListAuthenticationMethodTypes(t *testing.T) {
t.Parallel()
userIDWithoutAuth := Instance.CreateHumanUser(CTX).GetUserId()
userIDWithPasskey := Instance.CreateHumanUser(CTX).GetUserId()

View File

@ -590,7 +590,7 @@ func (s *Server) checkIntentToken(token string, intentID string) error {
}
func (s *Server) ListAuthenticationMethodTypes(ctx context.Context, req *user.ListAuthenticationMethodTypesRequest) (*user.ListAuthenticationMethodTypesResponse, error) {
authMethods, err := s.query.ListUserAuthMethodTypes(ctx, req.GetUserId(), true)
authMethods, err := s.query.ListUserAuthMethodTypes(ctx, req.GetUserId(), true, false, "")
if err != nil {
return nil, err
}

View File

@ -72,7 +72,7 @@ func (l *Login) handleMailVerification(w http.ResponseWriter, r *http.Request) {
}
func (l *Login) checkUserNoFirstFactor(ctx context.Context, userID string) bool {
authMethods, err := l.query.ListUserAuthMethodTypes(setUserContext(ctx, userID, ""), userID, false)
authMethods, err := l.query.ListUserAuthMethodTypes(setUserContext(ctx, userID, ""), userID, false, false, "")
if err != nil {
logging.WithFields("userID", userID).OnError(err).Warn("unable to load user's auth methods for mail verification")
return false

View File

@ -259,6 +259,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Пол
Female: Женски пол
Male: Мъжки
@ -299,6 +300,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Правила и условия
TosConfirm: Приемам
TosLinkText: TOS
@ -368,6 +370,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Упълномощаване на устройството
UserCode:

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Pohlaví
Female: Žena
Male: Muž
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Obchodní podmínky
TosConfirm: Souhlasím s
TosLinkText: obchodními podmínkami
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Autorizace zařízení
UserCode:

View File

@ -262,6 +262,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Geschlecht
Female: weiblich
Male: männlich
@ -303,6 +304,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Allgemeine Geschäftsbedingungen und Datenschutz
TosConfirm: Ich akzeptiere die
TosLinkText: AGB
@ -378,6 +380,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Gerät verbinden
UserCode:

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Gender
Female: Female
Male: Male
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Terms and conditions
TosConfirm: I accept the
TosLinkText: TOS
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Device Authorization
UserCode:

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Género
Female: Mujer
Male: Hombre
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Términos y condiciones
TosConfirm: Acepto los
TosLinkText: TDS
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
Footer:
PoweredBy: Powered By

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Genre
Female: Femme
Male: Homme
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Termes et conditions
TosConfirm: J'accepte les
TosLinkText: TOS
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Autorisation de l'appareil

View File

@ -0,0 +1,477 @@
Login:
Title: Üdv újra itt!
Description: Add meg a bejelentkezési adataidat.
TitleLinking: Felhasználó összekapcsolása bejelentkezéssel
DescriptionLinking: Add meg a bejelentkezési adataidat a külső felhasználó összekapcsolásához.
LoginNameLabel: Bejelentkezési név
UsernamePlaceHolder: felhasználónév
LoginnamePlaceHolder: felhasználónév@domain
ExternalUserDescription: Jelentkezz be külső felhasználóval.
MustBeMemberOfOrg: A felhasználónak az {{.OrgName}} szervezet tagjának kell lennie.
RegisterButtonText: Regisztráció
NextButtonText: Következő
LDAP:
Title: Bejelentkezés
Description: Add meg a bejelentkezési adataidat.
LoginNameLabel: Bejelentkezési név
PasswordLabel: Jelszó
NextButtonText: Következő
SelectAccount:
Title: Fiók kiválasztása
Description: Használd a fiókodat
TitleLinking: Fiók kiválasztása a felhasználó összekapcsolásához
DescriptionLinking: Válaszd ki a fiókodat, hogy összekapcsold a külső felhasználóddal.
OtherUser: Másik felhasználó
SessionState0: aktív
SessionState1: Kijelentkezve
MustBeMemberOfOrg: A felhasználónak a {{.OrgName}} szervezet tagjának kell lennie.
Password:
Title: Jelszó
Description: Add meg a bejelentkezési adataidat.
PasswordLabel: Jelszó
MinLength: Legalább
MinLengthp2: karakter hosszúnak kell lennie.
MaxLength: Kevesebb, mint 70 karakter hosszúnak kell lennie.
HasUppercase: Tartalmaznia kell egy nagybetűt.
HasLowercase: Tartalmaznia kell egy kisbetűt.
HasNumber: Tartalmaznia kell egy számot.
HasSymbol: Tartalmaznia kell egy szimbólumot.
Confirmation: A jelszó megerősítése egyezik.
ResetLinkText: Jelszó visszaállítása
BackButtonText: Vissza
NextButtonText: Következő
UsernameChange:
Title: Felhasználónév megváltoztatása
Description: Állítsd be az új felhasználóneved
UsernameLabel: Felhasználónév
CancelButtonText: Mégse
NextButtonText: Következő
UsernameChangeDone:
Title: Felhasználónév megváltoztatva
Description: A felhasználóneved sikeresen megváltozott.
NextButtonText: Következő
InitPassword:
Title: Jelszó beállítása
Description: Kaptál egy kódot, amit az alábbi űrlapon meg kell adnod az új jelszavad beállításához.
CodeLabel: Kód
NewPasswordLabel: Új jelszó
NewPasswordConfirmLabel: Jelszó megerősítése
ResendButtonText: Kód újraküldése
NextButtonText: Következő
InitPasswordDone:
Title: Jelszó beállítva
Description: A jelszót sikeresen beállítottad
NextButtonText: Következő
CancelButtonText: Mégse
InitUser:
Title: Felhasználó aktiválása
Description: Igazold az e-mailed az alábbi kóddal és állítsd be a jelszavad.
CodeLabel: Kód
NewPasswordLabel: Új jelszó
NewPasswordConfirm: Jelszó megerősítése
NextButtonText: Következő
ResendButtonText: Kód újraküldése
InitUserDone:
Title: Felhasználó aktiválva
Description: Az email ellenőrzése sikeres volt és a jelszó beállítása megtörtént
NextButtonText: Következő
CancelButtonText: Mégsem
InviteUser:
Title: Felhasználó aktiválása
Description: Ellenőrizd az emailed az alábbi kóddal és állítsd be a jelszavad.
CodeLabel: Kód
NewPasswordLabel: Új jelszó
NewPasswordConfirm: Jelszó megerősítése
NextButtonText: Következő
ResendButtonText: Kód újraküldése
InitMFAPrompt:
Title: 2-faktoros beállítás
Description: A 2-faktoros hitelesítés további biztonságot nyújt a felhasználói fiókodhoz. Ez biztosítja, hogy csak te férhetsz hozzá a fiókodhoz.
Provider0: Hitelesítő alkalmazás (pl. Google/Microsoft Authenticator, Authy)
Provider1: Eszközfüggő (pl. FaceID, Windows Hello, Ujjlenyomat)
Provider3: OTP SMS
Provider4: OTP Email
NextButtonText: Következő
SkipButtonText: Kihagyás
InitMFAOTP:
Title: 2-faktoros ellenőrzés
Description: Hozd létre a 2-faktorodat. Töltsd le az authenticator appot, ha még nincs.
OTPDescription: Olvasd be a kódot az authenticator appoddal (pl. Google/Microsoft Authenticator, Authy), vagy másold be a titkos kódot és írd be a generált kódot alulra.
SecretLabel: Titkos
CodeLabel: Kód
NextButtonText: Következő
CancelButtonText: Mégsem
InitMFAOTPSMS:
Title: Kétfaktoros hitelesítés
DescriptionPhone: Hozd létre a kétfaktoros hitelesítést. Add meg a telefonszámod a hitelesítéshez.
DescriptionCode: Hozd létre a kétfaktoros hitelesítést. Add meg a kapott kódot a telefonszámod hitelesítéséhez.
PhoneLabel: Telefon
CodeLabel: Kód
EditButtonText: Szerkesztés
ResendButtonText: Kód újraküldése
NextButtonText: Tovább
InitMFAU2F:
Title: Biztonsági kulcs hozzáadása
Description: A biztonsági kulcs egy olyan hitelesítési módszer, amely beépíthető a telefonodba, használható Bluetooth-szal vagy közvetlenül a számítógéped USB-portjához csatlakoztatható.
TokenNameLabel: A biztonsági kulcs / eszköz neve
NotSupported: A WebAuthN nem támogatott a böngésződben. Kérlek, győződj meg róla, hogy a legújabb verziót használod, vagy használj egy másik böngészőt (pl. Chrome, Safari, Firefox)
RegisterTokenButtonText: Biztonsági kulcs hozzáadása
ErrorRetry: Próbáld újra, hozz létre egy új kihívást, vagy válassz egy másik módszert.
InitMFADone:
Title: 2-faktoros hitelesítés igazolva
Description: Szuper! Sikeresen beállítottad a 2-faktoros hitelesítést, és így sokkal biztonságosabbá tetted a fiókodat. A faktort minden bejelentkezéskor meg kell adni.
NextButtonText: Következő
CancelButtonText: Mégse
MFAProvider:
Provider0: Hitelesítő alkalmazás (pl. Google/Microsoft Authenticator, Authy)
Provider1: Eszközfüggő (pl. FaceID, Windows Hello, Ujjlenyomat)
Provider3: OTP SMS
Provider4: OTP Email
ChooseOther: vagy válassz egy másik lehetőséget
VerifyMFAOTP:
Title: Kétlépcsős azonosítás ellenőrzése
Description: Ellenőrizd a második azonosítódat
CodeLabel: Kód
NextButtonText: Következő
VerifyOTP:
Title: Kétlépcsős azonosítás ellenőrzése
Description: Ellenőrizd a második azonosítódat
CodeLabel: Kód
ResendButtonText: Kód újraküldése
NextButtonText: Következő
VerifyMFAU2F:
Title: Kétlépcsős hitelesítés
Description: Hitelesítsd a kétlépcsős ellenőrzést a regisztrált eszközzel (például FaceID, Windows Hello, ujjlenyomat)
NotSupported: A böngésződ nem támogatja a WebAuthN-t. Győződj meg róla, hogy a legújabb verziót használod, vagy válts egy támogatott böngészőre (Chrome, Safari, Firefox)
ErrorRetry: Próbáld újra, készíts új kérést vagy válassz másik módszert.
ValidateTokenButtonText: Kétlépcsős hitelesítés ellenőrzése
Passwordless:
Title: Jelszó nélküli bejelentkezés
Description: Jelentkezz be az eszközöd által biztosított hitelesítési módszerekkel, mint például FaceID, Windows Hello vagy ujjlenyomat.
NotSupported: A böngésződ nem támogatja a WebAuthN-t. Kérlek, győződj meg róla, hogy naprakész, vagy használj másikat (például Chrome, Safari, Firefox)
ErrorRetry: Próbáld újra, hozz létre egy új kihívást vagy válassz egy másik módszert.
LoginWithPwButtonText: Bejelentkezés jelszóval
ValidateTokenButtonText: Bejelentkezés jelszó nélküli módszerrel
PasswordlessPrompt:
Title: Jelszó nélküli beállítás
Description: Szeretnéd beállítani a jelszó nélküli bejelentkezést? (Eszközöd hitelesítési módszerei, például FaceID, Windows Hello vagy ujjlenyomat)
DescriptionInit: Be kell állítanod a jelszó nélküli bejelentkezést. Használd a kapott linket az eszközöd regisztrálásához.
PasswordlessButtonText: Használd a jelszó nélküli módszert
NextButtonText: Következő
SkipButtonText: Kihagy
PasswordlessRegistration:
Title: Jelszó nélküli beállítás
Description: Add meg az azonosításodat egy név megadásával (pl. MyMobilePhone, MacBook, stb.), majd kattints a lentebb található 'Register passwordless' gombra.
TokenNameLabel: Az eszköz neve
NotSupported: A böngésződ nem támogatja a WebAuthN-t. Kérjük, győződj meg róla, hogy naprakész, vagy használj egy másik böngészőt (pl. Chrome, Safari, Firefox)
RegisterTokenButtonText: Register passwordless
ErrorRetry: Próbáld újra, hozz létre egy új kihívást, vagy válassz egy másik módszert.
PasswordlessRegistrationDone:
Title: Passwordless beállítás
Description: Az eszközt a passwordless sikeresen hozzáadtad.
DescriptionClose: Most bezárhatod ezt az ablakot.
NextButtonText: Következő
CancelButtonText: Mégse
PasswordChange:
Title: Jelszó megváltoztatása
Description: Változtasd meg a jelszavad. Add meg a régi és az új jelszavad.
ExpiredDescription: A jelszavad lejárt, és meg kell változtatnod. Add meg a régi és az új jelszavad.
OldPasswordLabel: Régi jelszó
NewPasswordLabel: Új jelszó
NewPasswordConfirmLabel: Jelszó megerősítése
CancelButtonText: Mégse
NextButtonText: Következő
Footer: Lábléc
PasswordChangeDone:
Title: Jelszó megváltoztatása
Description: A jelszavad sikeresen megváltozott.
NextButtonText: Tovább
PasswordResetDone:
Title: Jelszó-visszaállítási link elküldve
Description: Ellenőrizd az emailjeidet a jelszó visszaállításához.
NextButtonText: Tovább
EmailVerification:
Title: E-mail megerősítés
Description: Küldtünk neked egy e-mailt a címed megerősítéséhez. Kérjük, írd be a kódot az alábbi űrlapba.
CodeLabel: Kód
NextButtonText: Tovább
ResendButtonText: Kód újraküldése
EmailVerificationDone:
Title: E-mail ellenőrzés
Description: Az e-mail címedet sikeresen ellenőriztük.
NextButtonText: Következő
CancelButtonText: Mégse
LoginButtonText: Bejelentkezés
RegisterOption:
Title: Regisztrációs lehetőségek
Description: Válaszd ki, hogyan szeretnél regisztrálni
RegisterUsernamePasswordButtonText: Felhasználónévvel és jelszóval
ExternalLoginDescription: vagy regisztrálj egy külső felhasználóval
LoginButtonText: Bejelentkezés
RegistrationUser:
Title: Regisztráció
Description: Add meg az adataidat. Az email címed lesz a bejelentkezési neved.
DescriptionOrgRegister: Add meg az adataidat.
EmailLabel: E-mail
UsernameLabel: Felhasználónév
FirstnameLabel: Keresztnév
LastnameLabel: Vezetéknév
LanguageLabel: Nyelv
German: Német
English: Angol
Italian: Olasz
French: Francia
Chinese: Egyszerűsített Kínai
Polish: Lengyel
Japanese: Japán
Spanish: Spanyol
Bulgarian: Bolgár
Portuguese: Portugál
Macedonian: Macedón
Czech: Cseh
Russian: Orosz
Dutch: Holland
Swedish: Svéd
Indonesian: Indonéz
Hungarian: Magyar
GenderLabel: Nem
Female:
Male: Férfi
Diverse: diverz / X
PasswordLabel: Jelszó
PasswordConfirmLabel: Jelszó megerősítése
TosAndPrivacyLabel: Felhasználási feltételek
TosConfirm: Elfogadom a
TosLinkText: Általános Szerződési Feltételeket (ÁSZF)
PrivacyConfirm: Elfogadom a
PrivacyLinkText: adatvédelmi szabályzatot
ExternalLogin: vagy regisztrálj külső felhasználóként
BackButtonText: Bejelentkezés
NextButtonText: Következő
ExternalRegistrationUserOverview:
Title: Külső felhasználói regisztráció
Description: Átvettük a felhasználói adataidat a kiválasztott szolgáltatótól. Most megváltoztathatod vagy kiegészítheted őket.
EmailLabel: E-mail
UsernameLabel: Felhasználónév
FirstnameLabel: Keresztnév
LastnameLabel: Vezetéknév
NicknameLabel: Becenév
PhoneLabel: Telefonszám
LanguageLabel: Nyelv
German: Német
English: Angol
Italian: Olasz
French: Francia
Chinese: Egyszerűsített kínai
Polish: Lengyel
Japanese: Japán
Spanish: Spanyol
Bulgarian: Bolgár
Portuguese: Portugál
Macedonian: Macedón
Czech: Cseh
Russian: Orosz
Dutch: Holland
Swedish: Svéd
Indonesian: Indonéz
Hungarian: Magyar
TosAndPrivacyLabel: Felhasználási feltételek
TosConfirm: Elfogadom a
TosLinkText: TOS
PrivacyConfirm: Elfogadom a
PrivacyLinkText: adatvédelmi nyilatkozatot
ExternalLogin: vagy regisztrálj külső felhasználóval
BackButtonText: Elutasít
NextButtonText: Mentés
RegistrationOrg:
Title: Szervezet regisztráció
Description: Add meg a szervezet nevét és a felhasználói adatokat.
OrgNameLabel: Szervezet neve
EmailLabel: E-mail
UsernameLabel: Felhasználónév
FirstnameLabel: Keresztnév
LastnameLabel: Vezetéknév
PasswordLabel: Jelszó
PasswordConfirmLabel: Jelszó megerősítése
TosAndPrivacyLabel: Felhasználási feltételek
TosConfirm: Elfogadom a
TosLinkText: TOS-t
PrivacyConfirm: Elfogadom a
PrivacyLinkText: adatvédelmi irányelveket
SaveButtonText: Szervezet létrehozása
LoginSuccess:
Title: Sikeres bejelentkezés
AutoRedirectDescription: Automatikusan vissza leszel irányítva az alkalmazásodhoz. Ha nem, kattints az alábbi gombra. Ezután bezárhatod az ablakot.
RedirectedDescription: Most már bezárhatod ezt az ablakot.
NextButtonText: Következő
LogoutDone:
Title: Kijelentkezve
Description: Sikeresen kijelentkeztél.
LoginButtonText: Bejelentkezés
LinkingUserPrompt:
Title: Meglévő felhasználó megtalálva
Description: Szeretnéd összekapcsolni a meglévő fiókodat
LinkButtonText: Összekapcsolás
OtherButtonText: Egyéb lehetőségek
LinkingUsersDone:
Title: Felhasználó összekapcsolása
Description: Felhasználó összekapcsolva.
CancelButtonText: Mégse
NextButtonText: Következő
ExternalNotFound:
Title: Külső felhasználó nem található
Description: Külső felhasználó nem található. Szeretnéd összekapcsolni a felhasználódat vagy automatikusan regisztrálni egy újat?
LinkButtonText: Összekapcsolás
AutoRegisterButtonText: Regisztráció
TosAndPrivacyLabel: Felhasználási feltételek
TosConfirm: Elfogadom a
TosLinkText: SZF-et
PrivacyConfirm: Elfogadom a
PrivacyLinkText: adatvédelmi szabályzatot
German: Német
English: Angol
Italian: Olasz
French: Francia
Chinese: Egyszerűsített kínai
Polish: Lengyel
Japanese: Japán
Spanish: Spanyol
Bulgarian: Bolgár
Portuguese: Portugál
Macedonian: Macedón
Czech: Cseh
Russian: Orosz
Dutch: Holland
Swedish: Svéd
Indonesian: Indonéz
Hungarian: Magyar
DeviceAuth:
Title: Eszköz engedélyezése
UserCode:
Label: Felhasználói kód
Description: Add meg az eszközön megjelenített felhasználói kódot.
ButtonNext: Következő
Action:
Description: Eszköz hozzáférés engedélyezése.
GrantDevice: az eszközhöz való hozzáférést engedélyezed
AccessToScopes: hozzáférés az alábbi tartományokhoz
Button:
Allow: Engedélyez
Deny: Megtagad
Done:
Description: Kész.
Approved: Az eszköz engedélyezése jóváhagyva. Most visszatérhetsz az eszközhöz.
Denied: Az eszköz engedélyezése megtagadva. Most visszatérhetsz az eszközhöz.
Footer:
PoweredBy: Működteti
Tos: Felhasználási feltételek
PrivacyPolicy: Adatvédelmi irányelvek
Help: Segítség
SupportEmail: Támogatási e-mail
SignIn: Jelentkezz be a {{.Provider}} segítségével
Errors:
Internal: Belső hiba történt
AuthRequest:
NotFound: Nem található hitelesítési kérés
UserAgentNotCorresponding: A felhasználói ügynök nem egyezik
UserAgentNotFound: Felhasználói ügynök azonosító nem található
TokenNotFound: Token nem található
RequestTypeNotSupported: A kérés típusa nem támogatott
MissingParameters: Kötelező paraméterek hiányoznak
User:
NotFound: A felhasználó nem található
AlreadyExists: A felhasználó már létezik
Inactive: A felhasználó inaktív
NotFoundOnOrg: A felhasználó nem található a kiválasztott szervezetben
NotAllowedOrg: A felhasználó nem tagja a szükséges szervezetnek
NotMatchingUserID: A felhasználó és az authrequest-ben szereplő felhasználó nem egyezik
UserIDMissing: A felhasználói azonosító üres
Invalid: Érvénytelen felhasználói adatok
DomainNotAllowedAsUsername: A domain már foglalt és nem használható
NotAllowedToLink: A felhasználó számára nem engedélyezett a külső bejelentkezési szolgáltatóval való kapcsolat
Profile:
NotFound: Profil nem található
NotChanged: Profil nem változott
Empty: Profil üres
FirstNameEmpty: A profilban a keresztnév üres
LastNameEmpty: A profilban a vezetéknév üres
IDMissing: Hiányzik a profil azonosító
Email:
NotFound: Email nem található
Invalid: Érvénytelen email
AlreadyVerified: Az email már ellenőrizve van
NotChanged: Az email nem változott
Empty: Az email üres
IDMissing: Az email azonosító hiányzik
Phone:
NotFound: A telefon nem található
Invalid: A telefon érvénytelen
AlreadyVerified: A telefon már ellenőrizve van
Empty: A telefon üres
NotChanged: A telefon nem változott
Address:
NotFound: A cím nem található
NotChanged: A cím nem változott
Username:
AlreadyExists: A felhasználónév már foglalt
Reserved: A felhasználónév már foglalt
Empty: A felhasználónév üres
Password:
ConfirmationWrong: A jelszó megerősítése helytelen
Empty: A jelszó üres
Invalid: A jelszó érvénytelen
InvalidAndLocked: A jelszó érvénytelen és a felhasználó zárolva van, vedd fel a kapcsolatot az adminisztrátoroddal.
NotChanged: Az új jelszó nem lehet azonos a jelenlegi jelszavaddal
UsernameOrPassword:
Invalid: A felhasználónév vagy a jelszó érvénytelen
PasswordComplexityPolicy:
NotFound: A jelszóházirend nem található
MinLength: A jelszó túl rövid
HasLower: A jelszónak kisbetűt kell tartalmaznia
HasUpper: A jelszónak nagybetűt kell tartalmaznia
HasNumber: A jelszónak számot kell tartalmaznia
HasSymbol: A jelszónak szimbólumot kell tartalmaznia
Code:
Expired: A kód lejárt
Invalid: A kód érvénytelen
Empty: A kód üres
CryptoCodeNil: A kriptográfiai kód nil
NotFound: Nem találom a kódot
GeneratorAlgNotSupported: Nem támogatott generáló algoritmus
EmailVerify:
UserIDEmpty: A felhasználói azonosító üres
ExternalData:
CouldNotRead: A külső adatokat nem sikerült helyesen beolvasni
MFA:
NoProviders: Nincsenek elérhető többfaktoros szolgáltatók
OTP:
AlreadyReady: A többfaktoros OTP (OneTimePassword) már be van állítva
NotExisting: A többfaktoros OTP (OneTimePassword) nem létezik
InvalidCode: Érvénytelen kód
NotReady: A többfaktoros OTP (OneTimePassword) nem áll készen
Locked: A felhasználó zárolva van
SomethingWentWrong: Valami elromlott
NotActive: A felhasználó nem aktív
ExternalIDP:
IDPTypeNotImplemented: Az IDP típus nincs megvalósítva
NotAllowed: Az külső bejelentkezési szolgáltató nem engedélyezett
IDPConfigIDEmpty: Az azonosítószolgáltató ID üres
ExternalUserIDEmpty: A külső felhasználói azonosító üres
UserDisplayNameEmpty: A felhasználó megjelenítendő neve üres
NoExternalUserData: Nem érkezett külső felhasználói adat
CreationNotAllowed: Új felhasználó létrehozása nem engedélyezett ezen a szolgáltatón
LinkingNotAllowed: A felhasználó összekapcsolása nem engedélyezett ezen a szolgáltatón
NoOptionAllowed: Sem új felhasználó létrehozása, sem összekapcsolás nem engedélyezett ezen a szolgáltatón. Kérjük, lépj kapcsolatba az adminisztrátoroddal.
GrantRequired: Bejelentkezés nem lehetséges. A felhasználónak legalább egy jogosultsággal kell rendelkeznie az alkalmazáson. Kérlek, lépj kapcsolatba az adminisztrátoroddal.
ProjectRequired: Bejelentkezés nem lehetséges. A felhasználó szervezetének engedélyezve kell lennie a projektre. Kérlek, lépj kapcsolatba az adminisztrátoroddal.
IdentityProvider:
InvalidConfig: Az Identity Provider konfiguráció érvénytelen
IAM:
LockoutPolicy:
NotExisting: A Lockout Policy nem létezik
Org:
LoginPolicy:
RegistrationNotAllowed: A regisztráció nem engedélyezett
DeviceAuth:
NotExisting: A felhasználói kód nem létezik
optional: (opcionális)

View File

@ -233,6 +233,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Jenis kelamin
Female: Perempuan
Male: Pria
@ -342,6 +343,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Otorisasi Perangkat
UserCode:

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Genere
Female: Femminile
Male: Maschile
@ -379,6 +380,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Autorizzazione del dispositivo

View File

@ -255,6 +255,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: 性別
Female: 女性
Male: 男性
@ -296,6 +297,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: 利用規約
TosConfirm: 私は利用規約を承諾します。
TosLinkText: TOS
@ -371,6 +373,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: デバイス認証

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Пол
Female: Женски
Male: Машки
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Правила и услови
TosConfirm: Се согласувам со
TosLinkText: правилата за користење
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Овластување преку уред

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Geslacht
Female: Vrouw
Male: Man
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Nederlands: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Algemene voorwaarden
TosConfirm: Ik accepteer de
TosLinkText: AV
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Apparaat Autorisatie
UserCode:

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Płeć
Female: Kobieta
Male: Mężczyzna
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Warunki i zasady
TosConfirm: Akceptuję
TosLinkText: Warunki korzystania
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Autoryzacja urządzenia

View File

@ -259,6 +259,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Gênero
Female: Feminino
Male: Masculino
@ -300,6 +301,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Termos e condições
TosConfirm: Eu aceito os
TosLinkText: termos de serviço
@ -375,6 +377,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Autorização de dispositivo

View File

@ -262,6 +262,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Пол
Female: Женский
Male: Мужской
@ -303,6 +304,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Условия использования
TosConfirm: Я согласен с
TosLinkText: Пользовательским соглашением
@ -378,6 +380,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Авторизация устройства

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: Kön
Female: Man
Male: Kvinna
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: Användarvillkor
TosConfirm: Jag accepterar
TosLinkText: Användarvillkoren
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: Tillgång från hårdvaruenhet
UserCode:

View File

@ -263,6 +263,7 @@ RegistrationUser:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
GenderLabel: 性别
Female: 女性
Male: 男性
@ -304,6 +305,7 @@ ExternalRegistrationUserOverview:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
TosAndPrivacyLabel: 条款和条款
TosConfirm: 我接受
TosLinkText: 服务条款
@ -379,6 +381,7 @@ ExternalNotFound:
Dutch: Nederlands
Swedish: Svenska
Indonesian: Bahasa Indonesia
Hungarian: Magyar
DeviceAuth:
Title: 设备授权
UserCode:

View File

@ -96,6 +96,8 @@
</option>
<option value="sv" id="sv" {{if (selectedLanguage "sv")}} selected {{end}}>{{t "ExternalNotFound.Swedish"}}
</option>
<option value="hu" id="hu" {{if (selectedLanguage "hu")}} selected {{end}}>{{t "ExternalNotFound.Hungarian"}}
</option>
</select>
</div>
</div>

View File

@ -726,7 +726,7 @@ func (repo *AuthRequestRepo) fillPolicies(ctx context.Context, request *domain.A
request.DefaultTranslations = defaultLoginTranslations
}
if len(request.OrgTranslations) == 0 || request.PolicyOrgID() != orgID {
orgLoginTranslations, err := repo.getLoginTexts(ctx, orgID)
orgLoginTranslations, err := repo.getLoginTexts(ctx, request.PrivateLabelingOrgID(orgID))
if err != nil {
return err
}
@ -785,9 +785,12 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
}
// the user was either not found or not active
// so check if the loginname suffix matches a verified org domain
ok, errDomainDiscovery := repo.checkDomainDiscovery(ctx, request, loginNameInput)
if errDomainDiscovery != nil || ok {
return errDomainDiscovery
// but only if no org was requested (by id or domain)
if request.RequestedOrgID == "" {
ok, errDomainDiscovery := repo.checkDomainDiscovery(ctx, request, loginNameInput)
if errDomainDiscovery != nil || ok {
return errDomainDiscovery
}
}
// let's once again check if the user was just inactive
if user != nil && user.State == int32(domain.UserStateInactive) {

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/database/postgres"
)
// Cache stores objects with a value of type `V`.
@ -55,9 +56,6 @@ type Cache[I, K comparable, V Entry[I, K]] interface {
// Truncate deletes all cached objects.
Truncate(ctx context.Context) error
// Close the cache. Subsequent calls to the cache are not allowed.
Close(ctx context.Context) error
}
// Entry contains a value of type `V` to be cached.
@ -75,8 +73,8 @@ type Entry[I, K comparable] interface {
type CachesConfig struct {
Connectors struct {
Memory MemoryConnectorConfig
// SQL database.Config
Memory MemoryConnectorConfig
Postgres PostgresConnectorConfig
// Redis redis.Config?
}
Instance *CacheConfig
@ -104,3 +102,9 @@ type MemoryConnectorConfig struct {
Enabled bool
AutoPrune AutoPruneConfig
}
type PostgresConnectorConfig struct {
Enabled bool
AutoPrune AutoPruneConfig
Connection postgres.Config
}

View File

@ -109,15 +109,11 @@ func (c *mapCache[I, K, V]) Prune(ctx context.Context) error {
func (c *mapCache[I, K, V]) Truncate(ctx context.Context) error {
for name, index := range c.indexMap {
index.Truncate()
c.logger.DebugContext(ctx, "map cache clear", "index", name)
c.logger.DebugContext(ctx, "map cache truncate", "index", name)
}
return nil
}
func (c *mapCache[I, K, V]) Close(ctx context.Context) error {
return ctx.Err()
}
type index[K comparable, V any] struct {
mutex sync.RWMutex
config *cache.CacheConfig

View File

@ -49,7 +49,6 @@ func Test_mapCache_Get(t *testing.T) {
AddSource: true,
},
})
defer c.Close(context.Background())
obj := &testObject{
id: "id",
names: []string{"foo", "bar"},
@ -112,7 +111,6 @@ func Test_mapCache_Invalidate(t *testing.T) {
AddSource: true,
},
})
defer c.Close(context.Background())
obj := &testObject{
id: "id",
names: []string{"foo", "bar"},
@ -134,7 +132,6 @@ func Test_mapCache_Delete(t *testing.T) {
AddSource: true,
},
})
defer c.Close(context.Background())
obj := &testObject{
id: "id",
names: []string{"foo", "bar"},
@ -168,7 +165,6 @@ func Test_mapCache_Prune(t *testing.T) {
AddSource: true,
},
})
defer c.Close(context.Background())
objects := []*testObject{
{
@ -205,7 +201,6 @@ func Test_mapCache_Truncate(t *testing.T) {
AddSource: true,
},
})
defer c.Close(context.Background())
objects := []*testObject{
{
id: "id1",

View File

@ -19,4 +19,3 @@ func (noop[I, K, V]) Invalidate(context.Context, I, ...K) (err error) { return }
func (noop[I, K, V]) Delete(context.Context, I, ...K) (err error) { return }
func (noop[I, K, V]) Prune(context.Context) (err error) { return }
func (noop[I, K, V]) Truncate(context.Context) (err error) { return }
func (noop[I, K, V]) Close(context.Context) (err error) { return }

View File

@ -0,0 +1,7 @@
create unlogged table if not exists cache.objects_{{ . }}
partition of cache.objects
for values in ('{{ . }}');
create unlogged table if not exists cache.string_keys_{{ . }}
partition of cache.string_keys
for values in ('{{ . }}');

5
internal/cache/pg/delete.sql vendored Normal file
View File

@ -0,0 +1,5 @@
delete from cache.string_keys k
where k.cache_name = $1
and k.index_id = $2
and k.index_key = any($3)
;

19
internal/cache/pg/get.sql vendored Normal file
View File

@ -0,0 +1,19 @@
update cache.objects
set last_used_at = now()
where cache_name = $1
and (
select object_id
from cache.string_keys k
where cache_name = $1
and index_id = $2
and index_key = $3
) = id
and case when $4::interval > '0s'
then created_at > now()-$4::interval -- max age
else true
end
and case when $5::interval > '0s'
then last_used_at > now()-$5::interval -- last use
else true
end
returning payload;

9
internal/cache/pg/invalidate.sql vendored Normal file
View File

@ -0,0 +1,9 @@
delete from cache.objects o
using cache.string_keys k
where k.cache_name = $1
and k.index_id = $2
and k.index_key = any($3)
and o.cache_name = k.cache_name
and o.id = k.object_id
;

Some files were not shown because too many files have changed in this diff Show More