mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 21:47:23 +00:00
fix: keep user idp links (#7079)
* login * auth methods * NewIDPUserLinksActiveQuery * use has_login_policy projection * fix unit tests * docs * keep old user links projection * fix tests * cleanup * cleanup comments * test idp links are not removed * idempotent auth method test * idempotent auth method test
This commit is contained in:
parent
2c4e7070ea
commit
c3e6257d68
@ -1,2 +1,5 @@
|
||||
Once you created the provider, it is listed in the providers overview.
|
||||
Activate it by selecting the tick with the tooltip *set as available*.
|
||||
Activate it by selecting the tick with the tooltip *set as available*.
|
||||
|
||||
If you deactivate a provider, your users with links to it will not be able to authenticate anymore.
|
||||
You can reactivate it and the logins will work again.
|
@ -7,9 +7,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/idp"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/user"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
@ -61,19 +59,7 @@ func (s *Server) AddIDPToLoginPolicy(ctx context.Context, req *admin_pb.AddIDPTo
|
||||
}
|
||||
|
||||
func (s *Server) RemoveIDPFromLoginPolicy(ctx context.Context, req *admin_pb.RemoveIDPFromLoginPolicyRequest) (*admin_pb.RemoveIDPFromLoginPolicyResponse, error) {
|
||||
idpQuery, err := query.NewIDPUserLinkIDPIDSearchQuery(req.IdpId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idps, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{
|
||||
Queries: []query.SearchQuery{idpQuery},
|
||||
}, true)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
objectDetails, err := s.command.RemoveIDPProviderFromDefaultLoginPolicy(ctx, &domain.IDPProvider{IDPConfigID: req.IdpId}, user.ExternalIDPViewsToExternalIDPs(idps.Links)...)
|
||||
objectDetails, err := s.command.RemoveIDPProviderFromDefaultLoginPolicy(ctx, &domain.IDPProvider{IDPConfigID: req.IdpId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -7,9 +7,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/idp"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/user"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
|
||||
)
|
||||
|
||||
@ -94,21 +92,7 @@ func (s *Server) AddIDPToLoginPolicy(ctx context.Context, req *mgmt_pb.AddIDPToL
|
||||
|
||||
func (s *Server) RemoveIDPFromLoginPolicy(ctx context.Context, req *mgmt_pb.RemoveIDPFromLoginPolicyRequest) (*mgmt_pb.RemoveIDPFromLoginPolicyResponse, error) {
|
||||
orgID := authz.GetCtxData(ctx).OrgID
|
||||
idpQuery, err := query.NewIDPUserLinkIDPIDSearchQuery(req.IdpId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resourceOwnerQuery, err := query.NewIDPUserLinksResourceOwnerSearchQuery(orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userLinks, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{
|
||||
Queries: []query.SearchQuery{idpQuery, resourceOwnerQuery},
|
||||
}, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectDetails, err := s.command.RemoveIDPFromLoginPolicy(ctx, orgID, &domain.IDPProvider{IDPConfigID: req.IdpId}, user.ExternalIDPViewsToExternalIDPs(userLinks.Links)...)
|
||||
objectDetails, err := s.command.RemoveIDPFromLoginPolicy(ctx, orgID, &domain.IDPProvider{IDPConfigID: req.IdpId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -13,11 +13,14 @@ import (
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/grpc"
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/idp"
|
||||
mgmt "github.com/zitadel/zitadel/pkg/grpc/management"
|
||||
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
|
||||
user "github.com/zitadel/zitadel/pkg/grpc/user/v2beta"
|
||||
@ -1063,12 +1066,27 @@ func TestServer_ListAuthenticationMethodTypes(t *testing.T) {
|
||||
ClientSecret: "client_secret",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Tester.Client.Mgmt.AddCustomLoginPolicy(CTX, &mgmt.AddCustomLoginPolicyRequest{})
|
||||
require.Condition(t, func() bool {
|
||||
code := status.Convert(err).Code()
|
||||
return code == codes.AlreadyExists || code == codes.OK
|
||||
})
|
||||
_, err = Tester.Client.Mgmt.AddIDPToLoginPolicy(CTX, &mgmt.AddIDPToLoginPolicyRequest{
|
||||
IdpId: provider.GetId(),
|
||||
OwnerType: idp.IDPOwnerType_IDP_OWNER_TYPE_ORG,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
idpLink, err := Tester.Client.UserV2.AddIDPLink(CTX, &user.AddIDPLinkRequest{UserId: userMultipleAuth, IdpLink: &user.IDPLink{
|
||||
IdpId: provider.GetId(),
|
||||
UserId: "external-id",
|
||||
UserName: "displayName",
|
||||
}})
|
||||
require.NoError(t, err)
|
||||
// This should not remove the user IDP links
|
||||
_, err = Tester.Client.Mgmt.RemoveIDPFromLoginPolicy(CTX, &mgmt.RemoveIDPFromLoginPolicyRequest{
|
||||
IdpId: provider.GetId(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
|
@ -382,7 +382,7 @@ func (l *Login) migrateExternalUserID(r *http.Request, authReq *domain.AuthReque
|
||||
return previousIDMatched, l.command.MigrateUserIDP(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID, externalUser.IDPConfigID, previousID, externalUserID)
|
||||
}
|
||||
|
||||
// handleExternalUserAuthenticated maps the IDP user, checks for a corresponding externalID
|
||||
// handleExternalUserAuthenticated maps the IDP user, checks for a corresponding externalID and that the IDP is allowed
|
||||
func (l *Login) handleExternalUserAuthenticated(
|
||||
w http.ResponseWriter,
|
||||
r *http.Request,
|
||||
@ -393,6 +393,11 @@ func (l *Login) handleExternalUserAuthenticated(
|
||||
callback func(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest),
|
||||
) {
|
||||
externalUser := mapIDPUserToExternalUser(user, provider.ID)
|
||||
// ensure the linked IDP is added to the login policy
|
||||
if err := l.authRepo.SelectExternalIDP(r.Context(), authReq.ID, provider.ID, authReq.AgentID); err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
// check and fill in local linked user
|
||||
externalErr := l.authRepo.CheckExternalUserLogin(setContext(r.Context(), ""), authReq.ID, authReq.AgentID, externalUser, domain.BrowserInfoFromRequest(r), false)
|
||||
if externalErr != nil && !zerrors.IsNotFound(externalErr) {
|
||||
|
@ -163,7 +163,7 @@ func (c *Commands) RemoveDefaultIDPConfig(ctx context.Context, idpID string, idp
|
||||
events = append(events, userEvents...)
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&NewOrgIdentityProviderWriteModel(idpProvider.AggregateID, idpID).WriteModel)
|
||||
orgEvents := c.removeIDPFromLoginPolicy(ctx, orgAgg, idpID, true)
|
||||
orgEvents := c.removeIDPFromLoginPolicy(ctx, orgAgg, idpID, true, externalIDPs...)
|
||||
events = append(events, orgEvents...)
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ func (c *Commands) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, idpPr
|
||||
return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider, cascadeExternalIDPs ...*domain.UserIDPLink) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) (*domain.ObjectDetails, error) {
|
||||
if !idpProvider.IsValid() {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INSTANCE-66m9s", "Errors.IAM.LoginPolicy.IDP.Invalid")
|
||||
}
|
||||
@ -89,7 +89,7 @@ func (c *Commands) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context,
|
||||
}
|
||||
|
||||
instanceAgg := InstanceAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
|
||||
events := c.removeIDPProviderFromDefaultLoginPolicy(ctx, instanceAgg, idpProvider, false, cascadeExternalIDPs...)
|
||||
events := c.removeIDPProviderFromDefaultLoginPolicy(ctx, instanceAgg, idpProvider, false)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/policy"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
@ -458,9 +457,8 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
provider *domain.IDPProvider
|
||||
cascadeExternalIDPs []*domain.UserIDPLink
|
||||
ctx context.Context
|
||||
provider *domain.IDPProvider
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -707,89 +705,6 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
provider: &domain.IDPProvider{
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
cascadeExternalIDPs: []*domain.UserIDPLink{
|
||||
{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remove provider with external idps, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewIdentityProviderAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"config1",
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"config1", "", "externaluser1"),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
instance.NewIdentityProviderRemovedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"config1"),
|
||||
user.NewUserIDPLinkCascadeRemovedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"config1", "externaluser1"),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &domain.IDPProvider{
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
cascadeExternalIDPs: []*domain.UserIDPLink{
|
||||
{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
ExternalUserID: "externaluser1",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -803,7 +718,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.RemoveIDPProviderFromDefaultLoginPolicy(tt.args.ctx, tt.args.provider, tt.args.cascadeExternalIDPs...)
|
||||
got, err := r.RemoveIDPProviderFromDefaultLoginPolicy(tt.args.ctx, tt.args.provider)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ func (c *Commands) AddIDPToLoginPolicy(ctx context.Context, resourceOwner string
|
||||
return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveIDPFromLoginPolicy(ctx context.Context, resourceOwner string, idpProvider *domain.IDPProvider, cascadeExternalIDPs ...*domain.UserIDPLink) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) RemoveIDPFromLoginPolicy(ctx context.Context, resourceOwner string, idpProvider *domain.IDPProvider) (*domain.ObjectDetails, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "Org-M0fs9", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
@ -203,7 +203,7 @@ func (c *Commands) RemoveIDPFromLoginPolicy(ctx context.Context, resourceOwner s
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
|
||||
events := c.removeIDPFromLoginPolicy(ctx, orgAgg, idpProvider.IDPConfigID, false, cascadeExternalIDPs...)
|
||||
events := c.removeIDPFromLoginPolicy(ctx, orgAgg, idpProvider.IDPConfigID, false)
|
||||
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
if err != nil {
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/repository/policy"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
@ -1006,10 +1005,9 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
provider *domain.IDPProvider
|
||||
cascadeExternalIDPs []*domain.UserIDPLink
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
provider *domain.IDPProvider
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -1238,7 +1236,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remove provider external idp not found, ok",
|
||||
name: "remove provider from login policy, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
@ -1290,93 +1288,6 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
Name: "name",
|
||||
Type: domain.IdentityProviderTypeOrg,
|
||||
},
|
||||
cascadeExternalIDPs: []*domain.UserIDPLink{
|
||||
{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remove provider with external idps, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIdentityProviderAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
domain.IdentityProviderTypeOrg,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"config1", "", "externaluser1"),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
org.NewIdentityProviderRemovedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
),
|
||||
user.NewUserIDPLinkCascadeRemovedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"config1", "externaluser1",
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: &domain.IDPProvider{
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
cascadeExternalIDPs: []*domain.UserIDPLink{
|
||||
{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
ExternalUserID: "externaluser1",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -1390,7 +1301,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.RemoveIDPFromLoginPolicy(tt.args.ctx, tt.args.resourceOwner, tt.args.provider, tt.args.cascadeExternalIDPs...)
|
||||
got, err := r.RemoveIDPFromLoginPolicy(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: Невалиден външен IDP
|
||||
IDPConfigNotExisting: Невалиден доставчик на IDP за тази организация
|
||||
NotAllowed: Външен IDP не е разрешен в тази организация
|
||||
NotAllowed: Външен IDP не е разрешен
|
||||
MinimumExternalIDPNeeded: Трябва да се добави поне един IDP
|
||||
AlreadyExists: Външен IDP вече е зает
|
||||
NotFound: Външен IDP не е намерен
|
||||
|
@ -143,7 +143,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: Externí IDP je neplatné
|
||||
IDPConfigNotExisting: Konfigurace poskytovatele IDP je pro tuto organizaci neplatná
|
||||
NotAllowed: Externí IDP není v této organizaci povoleno
|
||||
NotAllowed: Externí IDP není povolen
|
||||
MinimumExternalIDPNeeded: Musí být přidán alespoň jeden IDP
|
||||
AlreadyExists: Externí IDP již obsazeno
|
||||
NotFound: Externí IDP nenalezeno
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: Externer IDP ungültig
|
||||
IDPConfigNotExisting: IDP Provider ungültig für diese Organisation
|
||||
NotAllowed: Externer IDP ist auf dieser Organisation nicht erlaubt.
|
||||
NotAllowed: Externer IDP nicht erlaubt
|
||||
MinimumExternalIDPNeeded: Mindestens ein IDP muss hinzugefügt werden.
|
||||
AlreadyExists: External IDP ist bereits vergeben
|
||||
NotFound: Externer IDP nicht gefunden
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: External IDP invalid
|
||||
IDPConfigNotExisting: IDP provider invalid for this organization
|
||||
NotAllowed: External IDP not allowed on this organization
|
||||
NotAllowed: External IDP not allowed
|
||||
MinimumExternalIDPNeeded: At least one IDP must be added
|
||||
AlreadyExists: External IDP already taken
|
||||
NotFound: External IDP not found
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: IDP externo no válido
|
||||
IDPConfigNotExisting: Proveedor IDP no válido para esta organización
|
||||
NotAllowed: IDP externo no permitido para esta organización
|
||||
NotAllowed: IDP externo no permitido
|
||||
MinimumExternalIDPNeeded: Al menos de añadirse un IDP
|
||||
AlreadyExists: IDP externo ya cogido
|
||||
NotFound: IDP no encontrado
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: IDP Externer invalide
|
||||
IDPConfigNotExisting: Le fournisseur IDP n'est pas valide pour cette organisation
|
||||
NotAllowed: IDP externe non autorisé pour cette organisation
|
||||
NotAllowed: IDP externe non autorisé
|
||||
MinimumExternalIDPNeeded: Au moins un IDP doit être ajouté
|
||||
AlreadyExists: External IDP déjà pris
|
||||
NotFound: IDP externe non trouvé
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: IDP esterno non valido
|
||||
IDPConfigNotExisting: IDP non valido per questa organizzazione
|
||||
NotAllowed: IDP esterno non consentito su questa organizzazione
|
||||
NotAllowed: IDP esterno non consentito
|
||||
MinimumExternalIDPNeeded: Almeno un IDP deve essere aggiunto
|
||||
AlreadyExists: IDP esterno già preso
|
||||
NotFound: IDP esterno non trovato
|
||||
|
@ -136,7 +136,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: 無効な外部IDPです
|
||||
IDPConfigNotExisting: この組織はIDPプロバイダーが無効です
|
||||
NotAllowed: この組織では外部IDPが許可されていません
|
||||
NotAllowed: 外部IDPは許可されていません
|
||||
MinimumExternalIDPNeeded: 少なくとも1つのIDPを追加する必要があります
|
||||
AlreadyExists: 外部IDPはすでに使用されています
|
||||
NotFound: 外部IDPが見つかりません
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: Невалиден надворешен IDP
|
||||
IDPConfigNotExisting: IDP не е валиден за оваа организација
|
||||
NotAllowed: Надворешниоте IDP не е дозволен на оваа организација
|
||||
NotAllowed: Надворешниот IDP не е дозволен
|
||||
MinimumExternalIDPNeeded: Мора да се додаде најмалку еден надворешен IDP
|
||||
AlreadyExists: Надворешниот IDP е веќе зафатен
|
||||
NotFound: Надворешниот IDP не е пронајден
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: Externe IDP ongeldig
|
||||
IDPConfigNotExisting: IDP provider ongeldig voor deze organisatie
|
||||
NotAllowed: Externe IDP niet toegestaan op deze organisatie
|
||||
NotAllowed: Externe IDP niet toegestaan
|
||||
MinimumExternalIDPNeeded: Er moet minstens één IDP worden toegevoegd
|
||||
AlreadyExists: Externe IDP al ingenomen
|
||||
NotFound: Externe IDP niet gevonden
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: Nieprawidłowy IDP zewnętrzny
|
||||
IDPConfigNotExisting: Dostawca IDP jest nieprawidłowy dla tej organizacji
|
||||
NotAllowed: IDP zewnętrzne nie jest dozwolone w tej organizacji
|
||||
NotAllowed: IDP zewnętrzne nie jest dozwolone
|
||||
MinimumExternalIDPNeeded: Przynajmniej jeden IDP musi być dodany
|
||||
AlreadyExists: IDP zewnętrzne już istnieje
|
||||
NotFound: IDP zewnętrzne nie znaleziony
|
||||
|
@ -143,7 +143,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: IDP externo inválido
|
||||
IDPConfigNotExisting: Provedor de IDP inválido para esta organização
|
||||
NotAllowed: IDP externo não permitido nesta organização
|
||||
NotAllowed: IDP externo não permitido
|
||||
MinimumExternalIDPNeeded: Pelo menos um IDP deve ser adicionado
|
||||
AlreadyExists: IDP externo já está em uso
|
||||
NotFound: IDP externo não encontrado
|
||||
|
@ -143,7 +143,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: Внешний идентификационный номер недействителен.
|
||||
IDPConfigNotExisting: Поставщик МВУ недействителен для этой организации.
|
||||
NotAllowed: Внешний IDP не разрешен в этой организации.
|
||||
NotAllowed: Внешний IDP не разрешен
|
||||
MinimumExternalIDPNeeded: Необходимо добавить хотя бы одного ВПЛ.
|
||||
AlreadyExists: Внешнее ВПЛ уже занято
|
||||
NotFound: Внешний IDP не найден
|
||||
|
@ -144,7 +144,7 @@ Errors:
|
||||
ExternalIDP:
|
||||
Invalid: 外部 IDP 无效
|
||||
IDPConfigNotExisting: IDP 提供者对此组织无效
|
||||
NotAllowed: 此组织不允许外部 IDP
|
||||
NotAllowed: 外部 IDP 不允许
|
||||
MinimumExternalIDPNeeded: 必须添加至少一个 IDP
|
||||
AlreadyExists: 外部 IDP 已存在
|
||||
NotFound: 未找到外部 IDP
|
||||
|
Loading…
x
Reference in New Issue
Block a user