fix: review changes

This commit is contained in:
Stefan Benz
2024-10-01 17:21:44 +02:00
parent 3a5c51ab45
commit 693ddc4721
23 changed files with 242 additions and 144 deletions

View File

@@ -5,6 +5,7 @@ package user_test
import (
"context"
"testing"
"time"
"github.com/brianvoe/gofakeit/v6"
"github.com/stretchr/testify/assert"
@@ -192,7 +193,9 @@ func TestServer_AddPersonalAccessToken(t *testing.T) {
OrgId: orgResp.GetOrganizationId(),
},
},
PersonalAccessToken: &user.SetPersonalAccessToken{},
PersonalAccessToken: &user.SetPersonalAccessToken{
ExpirationDate: timestamppb.New(time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC)),
},
},
res: res{
want: &resource_object.Details{
@@ -205,7 +208,7 @@ func TestServer_AddPersonalAccessToken(t *testing.T) {
},
},
{
name: "pat add, generated, ok",
name: "pat add, expirationdate invalid",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.AddPersonalAccessTokenRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
@@ -218,17 +221,11 @@ func TestServer_AddPersonalAccessToken(t *testing.T) {
OrgId: orgResp.GetOrganizationId(),
},
},
PersonalAccessToken: &user.SetPersonalAccessToken{},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
PersonalAccessToken: &user.SetPersonalAccessToken{
ExpirationDate: timestamppb.New(time.Date(2020, time.December, 31, 23, 59, 59, 0, time.UTC)),
},
},
wantErr: true,
},
}
for _, tt := range tests {

View File

@@ -5,6 +5,7 @@ package user_test
import (
"context"
"testing"
"time"
"github.com/brianvoe/gofakeit/v6"
"github.com/stretchr/testify/assert"
@@ -16,6 +17,8 @@ import (
user "github.com/zitadel/zitadel/pkg/grpc/resources/user/v3alpha"
)
var publicKeyExample = []byte("-----BEGIN PUBLIC KEY-----\nMIICITANBgkqhkiG9w0BAQEFAAOCAg4AMIICCQKCAgB5tWxwCGRloCqvpgI2ZXPl\nxQ+WZbQPuHTqAxwbXbsKOJoAAq16iHmzriLKpqVDxRUXqTH3cY0P0A1IZbCBB2gG\nyq3Lk08sR5ute+MEQ+QibX2qpk+mccRr+eP6B1otcyBWxRhZ/YtWphDpZ4GCb4oN\nAzTIebU0ztlu1OOnDDSEEhwScu2LhG40bx4hVU8XNgIqEjxiR61J89vfZpCmn0Rl\nsqYvmX9sqtqPokdsKl3LPItRyDAJMG0uhwwGKsHffDNeLDZN1OCZE/ZS7USarJQH\nbtGeqFQKsCL33xsKbNL+QjnAhqHW09bMdwofJvlwYLfL0rGJQr5aVCaERAfKAOE6\npy0nVkEJsRLxvdx/ZbTtZdCBk/LiznkE1xp9J02obQ+kWHtdUYxM1OSJqPRGQpbS\nZTxurdBQ43gRjO07iWNV9CB0i6QN2GtDBmHVb48i6aPdA++uJqnPYzy46FWA3KMA\nSlxiZ1RDcGH+fN9uklC2cwAurctAxed3Me2RYGdxl813udeV4Ef3qaiV2dix/pKA\nvN1KIfPTpTdULCDBLjtaAYflJ2WYXHeWMJMMC4oJc3bcKpA4mWjZibZ3pSGX/STQ\nXwHUtKsGlrVBSeqjjILVpH+2G0rusrqkGOlPKN+qOIsnwJf9x47v+xEw1slqdDWm\n+x3gc+8m9oowCcq20OeNTQIDAQAB\n-----END PUBLIC KEY-----")
func TestServer_AddPublicKey(t *testing.T) {
t.Parallel()
instance := integration.NewInstance(CTX)
@@ -60,7 +63,7 @@ func TestServer_AddPublicKey(t *testing.T) {
},
},
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_GeneratedKey{GeneratedKey: &user.GeneratedKey{}},
Type: &user.SetPublicKey_GenerateKey{GenerateKey: &user.GenerateKey{}},
},
},
wantErr: true,
@@ -80,7 +83,7 @@ func TestServer_AddPublicKey(t *testing.T) {
},
},
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_GeneratedKey{GeneratedKey: &user.GeneratedKey{}},
Type: &user.SetPublicKey_GenerateKey{GenerateKey: &user.GenerateKey{}},
},
},
wantErr: true,
@@ -105,6 +108,26 @@ func TestServer_AddPublicKey(t *testing.T) {
},
wantErr: true,
},
{
name: "publickey add, publickey invalid format",
ctx: instance.WithAuthorization(CTX, integration.UserTypeLogin),
dep: func(req *user.AddPublicKeyRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
return nil
},
req: &user.AddPublicKeyRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_PublicKey{PublicKey: &user.ProvidedPublicKey{PublicKey: []byte("invalid")}},
},
},
wantErr: true,
},
{
name: "publickey add, user not existing in org",
ctx: isolatedIAMOwnerCTX,
@@ -120,7 +143,7 @@ func TestServer_AddPublicKey(t *testing.T) {
},
},
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_GeneratedKey{GeneratedKey: &user.GeneratedKey{}},
Type: &user.SetPublicKey_GenerateKey{GenerateKey: &user.GenerateKey{}},
},
},
wantErr: true,
@@ -136,7 +159,7 @@ func TestServer_AddPublicKey(t *testing.T) {
},
Id: "notexisting",
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_GeneratedKey{GeneratedKey: &user.GeneratedKey{}},
Type: &user.SetPublicKey_GenerateKey{GenerateKey: &user.GenerateKey{}},
},
},
wantErr: true,
@@ -156,7 +179,7 @@ func TestServer_AddPublicKey(t *testing.T) {
},
},
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_GeneratedKey{GeneratedKey: &user.GeneratedKey{}},
Type: &user.SetPublicKey_PublicKey{PublicKey: &user.ProvidedPublicKey{PublicKey: publicKeyExample}},
},
},
res: res{
@@ -179,7 +202,7 @@ func TestServer_AddPublicKey(t *testing.T) {
},
req: &user.AddPublicKeyRequest{
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_GeneratedKey{GeneratedKey: &user.GeneratedKey{}},
Type: &user.SetPublicKey_PublicKey{PublicKey: &user.ProvidedPublicKey{PublicKey: publicKeyExample}},
},
},
res: res{
@@ -192,6 +215,27 @@ func TestServer_AddPublicKey(t *testing.T) {
},
},
},
{
name: "publickey add, expirationdate invalid",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.AddPublicKeyRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
return nil
},
req: &user.AddPublicKeyRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
PublicKey: &user.SetPublicKey{
ExpirationDate: timestamppb.New(time.Date(2020, time.December, 31, 23, 59, 59, 0, time.UTC)),
Type: &user.SetPublicKey_PublicKey{PublicKey: &user.ProvidedPublicKey{PublicKey: publicKeyExample}},
},
},
wantErr: true,
},
{
name: "publickey add, expirationdate, ok",
ctx: isolatedIAMOwnerCTX,
@@ -207,7 +251,8 @@ func TestServer_AddPublicKey(t *testing.T) {
},
},
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_PublicKey{PublicKey: &user.ProvidedPublicKey{PublicKey: []byte(gofakeit.BitcoinPrivateKey())}},
ExpirationDate: timestamppb.New(time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC)),
Type: &user.SetPublicKey_PublicKey{PublicKey: &user.ProvidedPublicKey{PublicKey: publicKeyExample}},
},
},
res: res{
@@ -235,7 +280,7 @@ func TestServer_AddPublicKey(t *testing.T) {
},
},
PublicKey: &user.SetPublicKey{
Type: &user.SetPublicKey_GeneratedKey{GeneratedKey: &user.GeneratedKey{}},
Type: &user.SetPublicKey_GenerateKey{GenerateKey: &user.GenerateKey{}},
},
},
res: res{
@@ -301,7 +346,7 @@ func TestServer_DeletePublicKey(t *testing.T) {
dep: func(req *user.RemovePublicKeyRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
publickeyResp := instance.AddAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), []byte(gofakeit.BitcoinPrivateKey()))
publickeyResp := instance.AddAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), publicKeyExample)
req.PublicKeyId = publickeyResp.GetPublicKeyId()
return nil
},
@@ -320,7 +365,7 @@ func TestServer_DeletePublicKey(t *testing.T) {
dep: func(req *user.RemovePublicKeyRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
publickeyResp := instance.AddAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), []byte(gofakeit.BitcoinPrivateKey()))
publickeyResp := instance.AddAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), publicKeyExample)
req.PublicKeyId = publickeyResp.GetPublicKeyId()
return nil
},
@@ -396,7 +441,7 @@ func TestServer_DeletePublicKey(t *testing.T) {
dep: func(req *user.RemovePublicKeyRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
publickeyResp := instance.AddAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), []byte(gofakeit.BitcoinPrivateKey()))
publickeyResp := instance.AddAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), publicKeyExample)
req.PublicKeyId = publickeyResp.GetPublicKeyId()
return nil
},
@@ -423,7 +468,7 @@ func TestServer_DeletePublicKey(t *testing.T) {
dep: func(req *user.RemovePublicKeyRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
resp := instance.AddAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, []byte(gofakeit.BitcoinPrivateKey()))
resp := instance.AddAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, publicKeyExample)
req.PublicKeyId = resp.GetPublicKeyId()
instance.RemoveAuthenticatorPublicKey(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, req.PublicKeyId)
return nil

View File

@@ -251,29 +251,6 @@ func TestServer_AddUsername(t *testing.T) {
},
},
},
{
name: "username add, already existing",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.AddUsernameRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
username := gofakeit.Username()
instance.AddAuthenticatorUsername(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, username, false)
req.Username.Username = username
return nil
},
req: &user.AddUsernameRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
Username: &user.SetUsername{
IsOrganizationSpecific: false,
},
},
wantErr: true,
},
{
name: "username add, isOrgSpecific, already existing",
ctx: isolatedIAMOwnerCTX,

View File

@@ -37,16 +37,16 @@ func addPublicKeyRequestToAddPublicKey(req *user.AddPublicKeyRequest) *command.A
}
}
func setPublicKeyToAddPublicKey(req *user.SetPublicKey) *command.PublicKey {
if req == nil {
func setPublicKeyToAddPublicKey(set *user.SetPublicKey) *command.PublicKey {
if set == nil {
return nil
}
expDate := time.Time{}
if req.GetExpirationDate() != nil {
expDate = req.GetExpirationDate().AsTime()
if set.GetExpirationDate() != nil {
expDate = set.GetExpirationDate().AsTime()
}
return &command.PublicKey{
PublicKey: req.GetPublicKey().GetPublicKey(),
PublicKey: set.GetPublicKey().GetPublicKey(),
ExpirationDate: expDate,
}
}

View File

@@ -19,6 +19,5 @@ func pushedEventsToObjectDetails(events []eventstore.Event) *domain.ObjectDetail
Sequence: events[len(events)-1].Sequence(),
EventDate: events[len(events)-1].CreatedAt(),
ResourceOwner: events[len(events)-1].Aggregate().ResourceOwner,
ID: events[len(events)-1].Aggregate().ID,
}
}

View File

@@ -210,7 +210,6 @@ func TestCommands_CreateDebugEvents(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "dbg1",
},
},
{
@@ -244,7 +243,6 @@ func TestCommands_CreateDebugEvents(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "dbg1",
},
},
{
@@ -277,7 +275,6 @@ func TestCommands_CreateDebugEvents(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "dbg1",
},
},
{
@@ -327,7 +324,6 @@ func TestCommands_CreateDebugEvents(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "dbg1",
},
},
}

View File

@@ -64,7 +64,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "instance1",
},
},
{
@@ -94,7 +93,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "instance1",
},
},
{
@@ -113,7 +111,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "instance1",
},
},
{
@@ -132,7 +129,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "instance1",
},
},
{
@@ -151,7 +147,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "instance1",
},
},
{
@@ -170,7 +165,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "instance1",
},
},
{
@@ -230,7 +224,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "instance1",
},
},
{
@@ -282,7 +275,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "instance1",
ID: "instance1",
},
},
}

View File

@@ -61,7 +61,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "SYSTEM",
ID: "SYSTEM",
},
},
{
@@ -80,7 +79,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "SYSTEM",
ID: "SYSTEM",
},
},
{
@@ -99,7 +97,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "SYSTEM",
ID: "SYSTEM",
},
},
{
@@ -118,7 +115,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "SYSTEM",
ID: "SYSTEM",
},
},
{
@@ -137,7 +133,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "SYSTEM",
ID: "SYSTEM",
},
},
{
@@ -197,7 +192,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "SYSTEM",
ID: "SYSTEM",
},
},
{
@@ -259,7 +253,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
}},
want: &domain.ObjectDetails{
ResourceOwner: "SYSTEM",
ID: "SYSTEM",
},
},
}

View File

@@ -707,7 +707,7 @@ func (wm *UserV3WriteModel) NewUnlock(ctx context.Context) (_ []eventstore.Comma
}
// can only be unlocked when locked
if !wm.Locked {
return nil, zerrors.ThrowNotFound(nil, "COMMAND-gpBv46Lh9m", "Errors.User.NotFound")
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-gpBv46Lh9m", "Errors.User.NotLocked")
}
if err := wm.checkPermissionStateChange(ctx); err != nil {
return nil, err
@@ -735,7 +735,7 @@ func (wm *UserV3WriteModel) NewActivate(ctx context.Context) (_ []eventstore.Com
}
// can only be activated when inactive
if wm.State != domain.UserStateInactive {
return nil, zerrors.ThrowNotFound(nil, "COMMAND-rQjbBr4J3j", "Errors.User.NotFound")
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-rQjbBr4J3j", "Errors.User.NotInactive")
}
if err := wm.checkPermissionStateChange(ctx); err != nil {
return nil, err

View File

@@ -28,10 +28,22 @@ type PAT struct {
Token string
}
func (wm *PAT) GetExpirationDate() time.Time {
return wm.ExpirationDate
}
func (wm *PAT) SetExpirationDate(date time.Time) {
wm.ExpirationDate = date
}
func (c *Commands) AddPAT(ctx context.Context, add *AddPAT) (*domain.ObjectDetails, error) {
if add.UserID == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-14sGR7lTaj", "Errors.IDMissing")
}
if err := domain.EnsureValidExpirationDate(add.PAT); err != nil {
return nil, err
}
schemauser, err := existingSchemaUser(ctx, c, add.ResourceOwner, add.UserID)
if err != nil {
return nil, err

View File

@@ -113,7 +113,7 @@ func (wm *PATV3WriteModel) NewDelete(ctx context.Context) ([]eventstore.Command,
func (wm *PATV3WriteModel) Exists() error {
if len(wm.Scopes) == 0 {
return zerrors.ThrowNotFound(nil, "TODO", "TODO")
return zerrors.ThrowNotFound(nil, "COMMAND-ur4kxtxIhW", "Errors.User.NotFound")
}
return nil
}
@@ -122,5 +122,5 @@ func (wm *PATV3WriteModel) NotExists() error {
if err := wm.Exists(); err != nil {
return nil
}
return zerrors.ThrowAlreadyExists(nil, "TODO", "TODO")
return zerrors.ThrowAlreadyExists(nil, "COMMAND-iBM2bOhvYH", "Errors.User.AlreadyExists")
}

View File

@@ -26,7 +26,7 @@ func filterPATExisting() expect {
context.Background(),
&authenticator.NewAggregate("pk1", "org1").Aggregate,
"user1",
time.Time{},
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
[]string{"first", "second", "third"},
),
),
@@ -140,6 +140,27 @@ func TestCommands_AddPAT(t *testing.T) {
},
},
},
{
"pat added, expirationDate before now",
fields{
eventstore: expectEventstore(),
},
args{
ctx: authz.NewMockContext("instanceID", "", ""),
user: &AddPAT{
UserID: "user1",
PAT: &PAT{
Scopes: []string{"first", "second", "third"},
ExpirationDate: time.Date(2020, time.December, 31, 23, 59, 59, 0, time.UTC),
},
},
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "DOMAIN-dv3t5", "Errors.AuthNKey.ExpireBeforeNow"))
},
},
},
{
"pat added, ok",
fields{
@@ -152,7 +173,7 @@ func TestCommands_AddPAT(t *testing.T) {
context.Background(),
&authenticator.NewAggregate("pk1", "org1").Aggregate,
"user1",
time.Time{},
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
[]string{"first", "second", "third"},
),
),
@@ -189,7 +210,7 @@ func TestCommands_AddPAT(t *testing.T) {
context.Background(),
&authenticator.NewAggregate("pk1", "org1").Aggregate,
"user1",
time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
[]string{"first", "second", "third"},
),
),
@@ -203,7 +224,7 @@ func TestCommands_AddPAT(t *testing.T) {
user: &AddPAT{
UserID: "user1",
PAT: &PAT{
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
ExpirationDate: time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
Scopes: []string{"first", "second", "third"},
},
},
@@ -308,7 +329,7 @@ func TestCommands_DeletePAT(t *testing.T) {
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "TODO", "TODO"))
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-ur4kxtxIhW", "Errors.User.NotFound"))
},
},
},
@@ -322,7 +343,7 @@ func TestCommands_DeletePAT(t *testing.T) {
context.Background(),
&authenticator.NewAggregate("pk1", "org1").Aggregate,
"user1",
time.Time{},
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
[]string{"first", "second", "third"},
),
),
@@ -343,7 +364,7 @@ func TestCommands_DeletePAT(t *testing.T) {
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "TODO", "TODO"))
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-ur4kxtxIhW", "Errors.User.NotFound"))
},
},
},

View File

@@ -4,6 +4,7 @@ import (
"context"
"time"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/zerrors"
@@ -16,6 +17,13 @@ type AddPublicKey struct {
PublicKey *PublicKey
}
func (wm *AddPublicKey) GetPublicKey() []byte {
if wm.PublicKey == nil {
return nil
}
return wm.PublicKey.PublicKey
}
func (wm *AddPublicKey) GetPrivateKey() []byte {
if wm.PublicKey == nil {
return nil
@@ -23,6 +31,20 @@ func (wm *AddPublicKey) GetPrivateKey() []byte {
return wm.PublicKey.PrivateKey
}
func (wm *AddPublicKey) GetExpirationDate() time.Time {
if wm.PublicKey == nil {
return time.Time{}
}
return wm.PublicKey.GetExpirationDate()
}
func (wm *AddPublicKey) SetExpirationDate(date time.Time) {
if wm.PublicKey == nil {
wm.PublicKey = &PublicKey{}
}
wm.PublicKey.SetExpirationDate(date)
}
type PublicKey struct {
ExpirationDate time.Time
PublicKey []byte
@@ -49,6 +71,15 @@ func (c *Commands) AddPublicKey(ctx context.Context, add *AddPublicKey) (*domain
if add.UserID == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-14sGR7lTaj", "Errors.IDMissing")
}
if publicKey := add.GetPublicKey(); publicKey != nil {
if _, err := crypto.BytesToPublicKey(publicKey); err != nil {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-WdWlhUSVqK", "Errors.User.Machine.Key.Invalid")
}
}
if err := domain.EnsureValidExpirationDate(add.PublicKey); err != nil {
return nil, err
}
schemauser, err := existingSchemaUser(ctx, c, add.ResourceOwner, add.UserID)
if err != nil {
return nil, err

View File

@@ -15,7 +15,6 @@ type PublicKeyV3WriteModel struct {
eventstore.WriteModel
UserID string
ExpirationDate time.Time
PrivateKey []byte
PublicKey []byte
checkPermission domain.PermissionCheck
@@ -114,7 +113,7 @@ func (wm *PublicKeyV3WriteModel) NewDelete(ctx context.Context) ([]eventstore.Co
func (wm *PublicKeyV3WriteModel) Exists() error {
if len(wm.PublicKey) == 0 {
return zerrors.ThrowNotFound(nil, "TODO", "TODO")
return zerrors.ThrowNotFound(nil, "COMMAND-CqNteIqtCt", "Errors.User.NotFound")
}
return nil
}
@@ -123,5 +122,5 @@ func (wm *PublicKeyV3WriteModel) NotExists() error {
if err := wm.Exists(); err != nil {
return nil
}
return zerrors.ThrowAlreadyExists(nil, "TODO", "TODO")
return zerrors.ThrowAlreadyExists(nil, "COMMAND-QkVpJv0DqA", "Errors.User.AlreadyExists")
}

View File

@@ -24,13 +24,15 @@ func filterPublicKeyExisting() expect {
context.Background(),
&authenticator.NewAggregate("pk1", "org1").Aggregate,
"user1",
time.Time{},
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
[]byte("something"),
),
),
)
}
var publicKeyExample = []byte("-----BEGIN PUBLIC KEY-----\nMIICITANBgkqhkiG9w0BAQEFAAOCAg4AMIICCQKCAgB5tWxwCGRloCqvpgI2ZXPl\nxQ+WZbQPuHTqAxwbXbsKOJoAAq16iHmzriLKpqVDxRUXqTH3cY0P0A1IZbCBB2gG\nyq3Lk08sR5ute+MEQ+QibX2qpk+mccRr+eP6B1otcyBWxRhZ/YtWphDpZ4GCb4oN\nAzTIebU0ztlu1OOnDDSEEhwScu2LhG40bx4hVU8XNgIqEjxiR61J89vfZpCmn0Rl\nsqYvmX9sqtqPokdsKl3LPItRyDAJMG0uhwwGKsHffDNeLDZN1OCZE/ZS7USarJQH\nbtGeqFQKsCL33xsKbNL+QjnAhqHW09bMdwofJvlwYLfL0rGJQr5aVCaERAfKAOE6\npy0nVkEJsRLxvdx/ZbTtZdCBk/LiznkE1xp9J02obQ+kWHtdUYxM1OSJqPRGQpbS\nZTxurdBQ43gRjO07iWNV9CB0i6QN2GtDBmHVb48i6aPdA++uJqnPYzy46FWA3KMA\nSlxiZ1RDcGH+fN9uklC2cwAurctAxed3Me2RYGdxl813udeV4Ef3qaiV2dix/pKA\nvN1KIfPTpTdULCDBLjtaAYflJ2WYXHeWMJMMC4oJc3bcKpA4mWjZibZ3pSGX/STQ\nXwHUtKsGlrVBSeqjjILVpH+2G0rusrqkGOlPKN+qOIsnwJf9x47v+xEw1slqdDWm\n+x3gc+8m9oowCcq20OeNTQIDAQAB\n-----END PUBLIC KEY-----")
func TestCommands_AddPublicKey(t *testing.T) {
type fields struct {
eventstore func(t *testing.T) *eventstore.Eventstore
@@ -79,6 +81,9 @@ func TestCommands_AddPublicKey(t *testing.T) {
ctx: authz.NewMockContext("instanceID", "", ""),
user: &AddPublicKey{
UserID: "notexisting",
PublicKey: &PublicKey{
PublicKey: publicKeyExample,
},
},
},
res{
@@ -87,6 +92,30 @@ func TestCommands_AddPublicKey(t *testing.T) {
},
},
},
{
"userschema not existing, error",
fields{
eventstore: expectEventstore(
filterSchemaUserExisting(),
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args{
ctx: authz.NewMockContext("instanceID", "", ""),
user: &AddPublicKey{
UserID: "user1",
PublicKey: &PublicKey{
PublicKey: publicKeyExample,
},
},
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-VLDTtxT3If", "Errors.UserSchema.NotExists"))
},
},
},
{
"no permission, error",
fields{
@@ -103,7 +132,7 @@ func TestCommands_AddPublicKey(t *testing.T) {
user: &AddPublicKey{
UserID: "user1",
PublicKey: &PublicKey{
PublicKey: []byte("something"),
PublicKey: publicKeyExample,
},
},
},
@@ -114,23 +143,43 @@ func TestCommands_AddPublicKey(t *testing.T) {
},
},
{
"userschema not existing, error",
"publickey added, no public key format",
fields{
eventstore: expectEventstore(
filterSchemaUserExisting(),
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
eventstore: expectEventstore(),
},
args{
ctx: authz.NewMockContext("instanceID", "", ""),
user: &AddPublicKey{
UserID: "user1",
PublicKey: &PublicKey{
PublicKey: []byte("something"),
},
},
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-VLDTtxT3If", "Errors.UserSchema.NotExists"))
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "COMMAND-WdWlhUSVqK", "Errors.User.Machine.Key.Invalid"))
},
},
},
{
"publickey added, expirationDate before now",
fields{
eventstore: expectEventstore(),
},
args{
ctx: authz.NewMockContext("instanceID", "", ""),
user: &AddPublicKey{
UserID: "user1",
PublicKey: &PublicKey{
PublicKey: publicKeyExample,
ExpirationDate: time.Date(2020, time.December, 31, 23, 59, 59, 0, time.UTC),
},
},
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "DOMAIN-dv3t5", "Errors.AuthNKey.ExpireBeforeNow"))
},
},
},
@@ -146,8 +195,8 @@ func TestCommands_AddPublicKey(t *testing.T) {
context.Background(),
&authenticator.NewAggregate("pk1", "org1").Aggregate,
"user1",
time.Time{},
[]byte("something"),
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
publicKeyExample,
),
),
),
@@ -159,7 +208,7 @@ func TestCommands_AddPublicKey(t *testing.T) {
user: &AddPublicKey{
UserID: "user1",
PublicKey: &PublicKey{
PublicKey: []byte("something"),
PublicKey: publicKeyExample,
},
},
},
@@ -181,8 +230,8 @@ func TestCommands_AddPublicKey(t *testing.T) {
context.Background(),
&authenticator.NewAggregate("pk1", "org1").Aggregate,
"user1",
time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
[]byte("something"),
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
publicKeyExample,
),
),
),
@@ -194,8 +243,8 @@ func TestCommands_AddPublicKey(t *testing.T) {
user: &AddPublicKey{
UserID: "user1",
PublicKey: &PublicKey{
PublicKey: []byte("something"),
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
PublicKey: publicKeyExample,
ExpirationDate: time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
},
},
},
@@ -296,7 +345,7 @@ func TestCommands_DeletePublicKey(t *testing.T) {
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "TODO", "TODO"))
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-CqNteIqtCt", "Errors.User.NotFound"))
},
},
},
@@ -310,7 +359,7 @@ func TestCommands_DeletePublicKey(t *testing.T) {
context.Background(),
&authenticator.NewAggregate("pk1", "org1").Aggregate,
"user1",
time.Time{},
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
[]byte("something"),
),
),
@@ -331,7 +380,7 @@ func TestCommands_DeletePublicKey(t *testing.T) {
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "TODO", "TODO"))
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-CqNteIqtCt", "Errors.User.NotFound"))
},
},
},

View File

@@ -337,7 +337,7 @@ func TestCommandSide_UnlockSchemaUser(t *testing.T) {
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-gpBv46Lh9m", "Errors.User.NotFound"))
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-gpBv46Lh9m", "Errors.User.NotLocked"))
},
},
},
@@ -758,7 +758,7 @@ func TestCommandSide_ReactivateSchemaUser(t *testing.T) {
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-rQjbBr4J3j", "Errors.User.NotFound"))
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-rQjbBr4J3j", "Errors.User.NotInactive"))
},
},
},

View File

@@ -770,10 +770,16 @@ func TestCommands_CreateSchemaUser(t *testing.T) {
},
Password: &SchemaUserPassword{Password: "password"},
PublicKeys: []*PublicKey{
{PublicKey: []byte("something"), ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC)},
{
PublicKey: []byte("something"),
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
},
},
PATs: []*PAT{
{Scopes: []string{"first", "second", "third"}, ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC)},
{
Scopes: []string{"first", "second", "third"},
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
},
},
},
},

View File

@@ -114,7 +114,7 @@ func (wm *UsernameV3WriteModel) NewDelete(ctx context.Context) ([]eventstore.Com
func (wm *UsernameV3WriteModel) Exists() error {
if wm.Username == "" {
return zerrors.ThrowNotFound(nil, "TODO", "TODO")
return zerrors.ThrowNotFound(nil, "COMMAND-uEii8L6Awp", "Errors.User.NotFound")
}
return nil
}
@@ -123,7 +123,7 @@ func (wm *UsernameV3WriteModel) NotExists() error {
if err := wm.Exists(); err != nil {
return nil
}
return zerrors.ThrowAlreadyExists(nil, "TODO", "TODO")
return zerrors.ThrowAlreadyExists(nil, "COMMAND-rK7ZTzEEGU", "Errors.User.AlreadyExists")
}
func AuthenticatorAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {

View File

@@ -340,7 +340,7 @@ func TestCommands_DeleteUsername(t *testing.T) {
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "TODO", "TODO"))
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-uEii8L6Awp", "Errors.User.NotFound"))
},
},
},
@@ -377,7 +377,7 @@ func TestCommands_DeleteUsername(t *testing.T) {
},
res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "TODO", "TODO"))
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-uEii8L6Awp", "Errors.User.NotFound"))
},
},
},

View File

@@ -20,7 +20,7 @@ type PATCreatedEvent struct {
UserID string `json:"userID"`
ExpirationDate time.Time `json:"expirationDate,omitempty"`
Scopes []string `json:"scopes"`
Scopes []string `json:"scopes,omitempty"`
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
}

View File

@@ -4,50 +4,29 @@ import (
"context"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/user"
)
const (
usernamePrefix = eventPrefix + "username."
UsernameCreatedType = usernamePrefix + "created"
UsernameDeletedType = usernamePrefix + "deleted"
uniqueUsernameType = "username"
)
func NewAddUsernameUniqueConstraint(resourceOwner string, isOrgSpecific bool, username string) *eventstore.UniqueConstraint {
if isOrgSpecific {
return eventstore.NewAddEventUniqueConstraint(
uniqueUsernameType,
resourceOwner+":"+username,
"TODO")
}
return eventstore.NewAddEventUniqueConstraint(
uniqueUsernameType,
username,
"TODO")
return user.NewAddUsernameUniqueConstraint(username, resourceOwner, isOrgSpecific)
}
func NewRemoveUsernameUniqueConstraint(resourceOwner string, isOrgSpecific bool, username string) *eventstore.UniqueConstraint {
if isOrgSpecific {
return eventstore.NewRemoveUniqueConstraint(
uniqueUsernameType,
resourceOwner+":"+username,
)
}
return eventstore.NewRemoveUniqueConstraint(
uniqueUsernameType,
username,
)
return user.NewRemoveUsernameUniqueConstraint(username, resourceOwner, isOrgSpecific)
}
type UsernameCreatedEvent struct {
*eventstore.BaseEvent `json:"-"`
UserID string `json:"userID"`
IsOrgSpecific bool `json:"isOrgSpecific"`
Username string `json:"username"`
IsOrgSpecific bool `json:"isOrgSpecific,omitempty"`
Username string `json:"username,omitempty"`
}
func (e *UsernameCreatedEvent) SetBaseEvent(event *eventstore.BaseEvent) {

View File

@@ -345,17 +345,18 @@ message SetPublicKey {
];
oneof type {
option (validate.required) = true;
// Let ZITADEL generate the key and return the private key.
GeneratedKey generated_key = 2;
// Let ZITADEL send the link to the user via SMS.
GenerateKey generate_key = 2;
// Let ZITADEL use the public key directly, from generated key outside of ZITADEL.
ProvidedPublicKey public_key = 3;
}
}
message GeneratedKey {}
message GenerateKey {}
message ProvidedPublicKey {
// Public key provided to persist.
bytes public_key = 2 [
// Public key provided to persist. Supported formats are defined in RFC2459 with the RSA, DSA, ECDSA, ED25519 and ECDH packages, provided by the X509 Golang package.
optional bytes public_key = 2 [
(validate.rules).bytes = {min_len: 1, max_len: 4048},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {

View File

@@ -208,4 +208,5 @@ enum AuthenticatorType {
AUTHENTICATOR_TYPE_OTP_SMS = 6;
AUTHENTICATOR_TYPE_PUBLIC_KEY = 7;
AUTHENTICATOR_TYPE_IDENTITY_PROVIDER = 8;
AUTHENTICATOR_TYPE_PERSONAL_ACCESS_TOKEN = 9;
}