package server import ( "context" "testing" "time" "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/conflict" apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac" eventservice "code.fbi.h-da.de/danet/gosdn/controller/eventService" "code.fbi.h-da.de/danet/gosdn/controller/rbac" "github.com/bufbuild/protovalidate-go" "github.com/google/uuid" ) func getTestUserServer(t *testing.T) *UserServer { jwtManager := rbac.NewJWTManager("test", time.Second) eventService := eventservice.NewMockEventService() userStore := rbac.NewMemoryUserStore() userService := rbac.NewUserService(userStore, eventService) roleStore := rbac.NewMemoryRoleStore() roleService := rbac.NewRoleService(roleStore, eventService) protoValidator, err := protovalidate.New() if err != nil { panic(err) } s := NewUserServer(jwtManager, userService, protoValidator) err = clearAndCreateAuthTestSetup(userService, roleService) if err != nil { t.Fatalf("%v", err) } return s } func TestUser_CreateUsers(t *testing.T) { type args struct { ctx context.Context request *apb.CreateUsersRequest } tests := []struct { name string args args wantErr bool validationErrors []*validate.Violation }{ { name: "default create users", args: args{ ctx: context.TODO(), request: &apb.CreateUsersRequest{ User: []*apb.User{ { Name: "someUser", Roles: map[string]string{pndID: "userTestRole"}, Password: "password", Token: "", Metadata: &conflict.Metadata{ ResourceVersion: 0, }, }, }, }, }, wantErr: false, }, { name: "create users with too short password should fail", args: args{ ctx: context.TODO(), request: &apb.CreateUsersRequest{ User: []*apb.User{ { Name: "someUser", Roles: map[string]string{pndID: "userTestRole"}, Password: "pass", Token: "", Metadata: &conflict.Metadata{ ResourceVersion: 0, }, }, }, }, }, wantErr: true, validationErrors: []*validate.Violation{ { FieldPath: stringToPointer("user[0].password"), ConstraintId: stringToPointer("string.min_len"), Message: stringToPointer("value length must be at least 5 characters"), }}, }, { name: "create users with too short username should fail", args: args{ ctx: context.TODO(), request: &apb.CreateUsersRequest{ User: []*apb.User{ { Name: "a", Roles: map[string]string{pndID: "userTestRole"}, Password: "password", Token: "", Metadata: &conflict.Metadata{ ResourceVersion: 0, }, }, }, }, }, wantErr: true, validationErrors: []*validate.Violation{ { FieldPath: stringToPointer("user[0].name"), ConstraintId: stringToPointer("string.min_len"), Message: stringToPointer("value length must be at least 3 characters"), }}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := getTestUserServer(t) _, err := s.CreateUsers(tt.args.ctx, tt.args.request) if (err != nil) != tt.wantErr { t.Errorf("User.CreateUsers() error = %v, wantErr %v", err, tt.wantErr) return } if tt.wantErr { assertValidationErrors(t, err, tt.validationErrors) } }) } } func TestUser_GetUser(t *testing.T) { patchLogger(t) type args struct { ctx context.Context request *apb.GetUserRequest } tests := []struct { name string args args want *apb.GetUserResponse wantErr bool validationErrors []*validate.Violation }{ { name: "default get user", args: args{ ctx: context.TODO(), request: &apb.GetUserRequest{ Name: "testAdmin", Id: uuid.Nil.String(), }, }, want: &apb.GetUserResponse{ User: &apb.User{Id: adminID, Name: "testAdmin"}}, wantErr: false, }, { name: "fail get user", args: args{ ctx: context.TODO(), request: &apb.GetUserRequest{ Name: "nope", Id: uuid.Nil.String(), }, }, want: nil, wantErr: true, }, { name: "fail get user due to missing name", args: args{ ctx: context.TODO(), request: &apb.GetUserRequest{ Name: "", Id: uuid.Nil.String(), }, }, want: nil, wantErr: true, validationErrors: []*validate.Violation{ { FieldPath: stringToPointer("name"), ConstraintId: stringToPointer("required"), Message: stringToPointer("value is required"), }}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := getTestUserServer(t) got, err := s.GetUser(tt.args.ctx, tt.args.request) if (err != nil) != tt.wantErr { t.Errorf("User.GetUser() error = %v, wantErr %v", err, tt.wantErr) return } if tt.wantErr { assertValidationErrors(t, err, tt.validationErrors) } if got != nil { if got.User.Name != tt.want.User.Name || got.User.Id != tt.want.User.Id { t.Errorf("User.GetUser() = %v, want %v", got, tt.want) } } else { if got != nil { t.Errorf("User.GetUser() = %v, want %v", got, tt.want) } } }) } } func TestUser_GetUsers(t *testing.T) { type args struct { ctx context.Context request *apb.GetUsersRequest } tests := []struct { name string args args want *apb.GetUsersResponse wantLen int wantErr bool }{ { name: "default get users", args: args{ctx: context.TODO(), request: &apb.GetUsersRequest{}, }, want: &apb.GetUsersResponse{ User: []*apb.User{ {Name: "testAdmin"}, {Name: "testUser"}, {Name: "testRandom"}}, }, wantLen: 3, wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := getTestUserServer(t) got, err := s.GetUsers(tt.args.ctx, tt.args.request) if (err != nil) != tt.wantErr { t.Errorf("User.GetUsers() error = %v, wantErr %v", err, tt.wantErr) return } if got != nil { if len(got.User) != tt.wantLen { t.Errorf("User.GetUsers() = %v, want %v", got, tt.want) } for _, gotU := range got.User { containsExpected := false for _, wantU := range tt.want.User { if gotU.Name == wantU.Name { containsExpected = true break } } if !containsExpected { t.Errorf("User.GetUsers() = %v, want %v", got, tt.want) } } } }) } } func TestUser_UpdateUsers(t *testing.T) { type args struct { ctx context.Context request *apb.UpdateUsersRequest } tests := []struct { name string args args want *apb.UpdateUsersResponse wantErr bool validationErrors []*validate.Violation }{ { name: "default update user", args: args{ctx: context.TODO(), request: &apb.UpdateUsersRequest{User: []*apb.UpdateUser{ { Id: adminID, Name: "sth Else", Metadata: &conflict.Metadata{}, }, }, }, }, want: &apb.UpdateUsersResponse{}, wantErr: false, }, { name: "error update user", args: args{ctx: context.TODO(), request: &apb.UpdateUsersRequest{User: []*apb.UpdateUser{ { Id: uuid.NewString(), Name: "not a user", Metadata: &conflict.Metadata{}, }, }, }, }, want: nil, wantErr: true, }, { name: "update user without name should fail validation", args: args{ctx: context.TODO(), request: &apb.UpdateUsersRequest{User: []*apb.UpdateUser{ { Id: uuid.NewString(), Name: "", Metadata: &conflict.Metadata{}, }, }, }, }, want: nil, wantErr: true, validationErrors: []*validate.Violation{ { FieldPath: stringToPointer("name"), ConstraintId: stringToPointer("required"), Message: stringToPointer("value is required"), }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := getTestUserServer(t) _, err := s.UpdateUsers(tt.args.ctx, tt.args.request) if (err != nil) != tt.wantErr { t.Errorf("User.UpdateUsers() error = %v, wantErr %v", err, tt.wantErr) return } if tt.wantErr { assertValidationErrors(t, err, tt.validationErrors) } }) } } func TestUser_DeleteUsers(t *testing.T) { type args struct { ctx context.Context request *apb.DeleteUsersRequest } tests := []struct { name string args args want *apb.DeleteUsersResponse wantErr bool validationErrors []*validate.Violation }{ { name: "default delete users", args: args{ctx: context.TODO(), request: &apb.DeleteUsersRequest{Username: []string{"testUser"}}, }, want: &apb.DeleteUsersResponse{}, wantErr: false, }, { name: "error delete users for non existing user", args: args{ctx: context.TODO(), request: &apb.DeleteUsersRequest{Username: []string{"no user"}}, }, want: &apb.DeleteUsersResponse{}, wantErr: true, }, { name: "error delete users due to missing name", args: args{ctx: context.TODO(), request: &apb.DeleteUsersRequest{Username: []string{""}}, }, want: &apb.DeleteUsersResponse{}, wantErr: true, validationErrors: []*validate.Violation{ { FieldPath: stringToPointer("name"), ConstraintId: stringToPointer("required"), Message: stringToPointer("value is required"), }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := getTestUserServer(t) _, err := s.DeleteUsers(tt.args.ctx, tt.args.request) if (err != nil) != tt.wantErr { t.Errorf("User.DeleteUsers() error = %v, wantErr %v", err, tt.wantErr) return } if tt.wantErr { assertValidationErrors(t, err, tt.validationErrors) } }) } }