mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 01:47:33 +00:00
feat: apiurls, passwordpolicy, userbyid (#507)
* feat: api doc request * feat: return zitadel docs * feat: return zitadel docs * feat: pw policy min length * feat: pw policy min length * fix: semantic * fix: read missing events on user by id
This commit is contained in:
14
internal/api/grpc/management/zitadel_docs.go
Normal file
14
internal/api/grpc/management/zitadel_docs.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/pkg/grpc/management"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) GetZitadelDocs(ctx context.Context, _ *empty.Empty) (*management.ZitadelDocs, error) {
|
||||
return &management.ZitadelDocs{
|
||||
Issuer: s.systemDefaults.ZitadelDocs.Issuer,
|
||||
DiscoveryEndpoint: s.systemDefaults.ZitadelDocs.DiscoveryEndpoint,
|
||||
}, nil
|
||||
}
|
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
type SystemDefaults struct {
|
||||
DefaultLanguage language.Tag
|
||||
ZitadelDocs ZitadelDocs
|
||||
SecretGenerators SecretGenerators
|
||||
UserVerificationKey *crypto.KeyConfig
|
||||
Multifactors MultifactorConfig
|
||||
@@ -24,6 +25,11 @@ type SystemDefaults struct {
|
||||
Notifications Notifications
|
||||
}
|
||||
|
||||
type ZitadelDocs struct {
|
||||
Issuer string
|
||||
DiscoveryEndpoint string
|
||||
}
|
||||
|
||||
type SecretGenerators struct {
|
||||
PasswordSaltCost int
|
||||
ClientSecretGenerator crypto.GeneratorConfig
|
||||
|
@@ -2,6 +2,7 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
@@ -23,13 +24,19 @@ type UserRepo struct {
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, id string) (*usr_model.UserView, error) {
|
||||
user, err := repo.View.UserByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
user, viewErr := repo.View.UserByID(id)
|
||||
if viewErr != nil && !caos_errs.IsNotFound(viewErr) {
|
||||
return nil, viewErr
|
||||
}
|
||||
events, err := repo.UserEvents.UserEventsByID(ctx, id, user.Sequence)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-PSoc3").WithError(err).Debug("error retrieving new events")
|
||||
if caos_errs.IsNotFound(viewErr) {
|
||||
user = new(model.UserView)
|
||||
}
|
||||
events, esErr := repo.UserEvents.UserEventsByID(ctx, id, user.Sequence)
|
||||
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "EVENT-Lsoj7", "Errors.User.NotFound")
|
||||
}
|
||||
if esErr != nil {
|
||||
logging.Log("EVENT-PSoc3").WithError(esErr).Debug("error retrieving new events")
|
||||
return model.UserToModel(user), nil
|
||||
}
|
||||
userCopy := *user
|
||||
|
@@ -25,6 +25,13 @@ type PasswordComplexityPolicy struct {
|
||||
HasSymbol bool
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) IsValid() error {
|
||||
if p.MinLength == 0 || p.MinLength > 72 {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "MODEL-Lsp0e", "Errors.User.PasswordComplexityPolicy.MinLengthNotAllowed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) Check(password string) error {
|
||||
if p.MinLength != 0 && uint64(len(password)) < p.MinLength {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "MODEL-HuJf6", "Errors.User.PasswordComplexityPolicy.MinLength")
|
||||
|
@@ -30,6 +30,9 @@ func (es *PolicyEventstore) GetPasswordComplexityPolicy(ctx context.Context, id
|
||||
|
||||
func (es *PolicyEventstore) CreatePasswordComplexityPolicy(ctx context.Context, policy *pol_model.PasswordComplexityPolicy) (*pol_model.PasswordComplexityPolicy, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
if err := policy.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
existingPolicy, err := es.GetPasswordComplexityPolicy(ctx, ctxData.OrgID)
|
||||
if err != nil && !caos_errs.IsNotFound(err) {
|
||||
return nil, err
|
||||
@@ -58,6 +61,9 @@ func (es *PolicyEventstore) CreatePasswordComplexityPolicy(ctx context.Context,
|
||||
|
||||
func (es *PolicyEventstore) UpdatePasswordComplexityPolicy(ctx context.Context, policy *pol_model.PasswordComplexityPolicy) (*pol_model.PasswordComplexityPolicy, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
if err := policy.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
existingPolicy, err := es.GetPasswordComplexityPolicy(ctx, ctxData.OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -73,7 +73,6 @@ func TestCreatePasswordComplexityPolicy(t *testing.T) {
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordComplexityPolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -83,13 +82,24 @@ func TestCreatePasswordComplexityPolicy(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "create policy, ok",
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicyNoEvents(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name", MinLength: 8},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name", MinLength: 8},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create policy, no minlength",
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicyNoEvents(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
errFunc: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -97,13 +107,13 @@ func TestCreatePasswordComplexityPolicy(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.CreatePasswordComplexityPolicy(tt.args.ctx, tt.args.policy)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID == "" {
|
||||
if tt.res.errFunc == nil && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Description != tt.res.policy.Description {
|
||||
if tt.res.errFunc == nil && result.Description != tt.res.policy.Description {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.Description, result.Description)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
@@ -119,7 +129,6 @@ func TestUpdatePasswordComplexityPolicy(t *testing.T) {
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordComplexityPolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -132,10 +141,21 @@ func TestUpdatePasswordComplexityPolicy(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicy(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
new: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew", MinLength: 8},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew", MinLength: 8},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create policy, no minlength",
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicyNoEvents(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
},
|
||||
res: res{
|
||||
errFunc: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -143,10 +163,9 @@ func TestUpdatePasswordComplexityPolicy(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicyNoEvents(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
new: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew", MinLength: 8},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
@@ -155,13 +174,13 @@ func TestUpdatePasswordComplexityPolicy(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.UpdatePasswordComplexityPolicy(tt.args.ctx, tt.args.new)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID == "" {
|
||||
if tt.res.errFunc == nil && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Description != tt.res.policy.Description {
|
||||
if tt.res.errFunc == nil && result.Description != tt.res.policy.Description {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.Description, result.Description)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
|
@@ -35,6 +35,7 @@ Errors:
|
||||
PasswordComplexityPolicy:
|
||||
NotFound: Passwort Policy konnte nicht gefunden werden
|
||||
MinLength: Passwort ist zu kurz
|
||||
MinLengthNotAllowed: Angegebene Mindestläng ist nicht erlaubt
|
||||
HasLower: Passwort beinhaltet keinen Kleinbuchstaben
|
||||
HasUpper: Passwort beinhaltet keinen Grossbuchstaben
|
||||
HasNumber: Passwort beinhaltet keine Nummer
|
||||
|
@@ -35,6 +35,7 @@ Errors:
|
||||
PasswordComplexityPolicy:
|
||||
NotFound: Password policy not found
|
||||
MinLength: Password is to short
|
||||
MinLengthNotAllowed: Given minimum length is not allowed
|
||||
HasLower: Password must contain lower case
|
||||
HasUpper: Password must contain upper case
|
||||
HasNumber: Password must contain number
|
||||
|
Reference in New Issue
Block a user