package app import ( "context" "errors" "strings" "testing" "evening_detective_server/internal/modules/processor_jwt" "evening_detective_server/internal/services/device_presence_service" "evening_detective_server/internal/services/game_service" "evening_detective_server/internal/services/screen_service" "evening_detective_server/internal/services/team_service" proto "evening_detective_server/proto" "github.com/google/uuid" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" ) func TestDeviceTransport(t *testing.T) { s := &server{devicePresenceService: device_presence_service.NewDevicePresenceService(true, nil, nil, nil)} ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("x-real-ip", "192.0.2.3", "grpcgateway-user-agent", "test-browser")) req := &proto.DeviceHeartbeatReq{DeviceID: uuid.NewString(), ConnectionID: uuid.NewString()} rsp, err := s.DeviceHeartbeat(ctx, req) if err != nil || !rsp.GetEnabled() || rsp.ServerTime == nil { t.Fatal(rsp, err) } for _, role := range []string{"organizer", "admin", "developer", "author", "user", ""} { t.Run(role, func(t *testing.T) { roleCtx := processor_jwt.ContextWithClaims(ctx, &processor_jwt.JWTClaims{Roles: []string{role}}) devices, err := s.GetDevices(roleCtx, &proto.GetDevicesReq{}) if role == "author" || role == "user" || role == "" { if status.Code(err) != codes.PermissionDenied { t.Fatal(err) } return } if err != nil || len(devices.Devices) != 1 { t.Fatal(devices, err) } connection := devices.Devices[0].Connections[0] if connection.IP != "192.0.2.3" || connection.UserAgent != "test-browser" { t.Fatal(connection) } raw, err := protojson.Marshal(devices) if err != nil { t.Fatal(err) } for _, secret := range []string{"password", "accessToken", "ScreenTokenHash", "email", "URL"} { if strings.Contains(string(raw), secret) { t.Fatal("secret field in response") } } }) } req.DeviceID = "bad" if _, err = s.DeviceHeartbeat(ctx, req); status.Code(err) != codes.InvalidArgument { t.Fatal(err) } s.devicePresenceService = device_presence_service.NewDevicePresenceService(false, nil, nil, nil) rsp, err = s.DeviceHeartbeat(ctx, req) if err != nil || rsp.GetEnabled() { t.Fatal(rsp, err) } raw, err := protojson.Marshal(rsp) if err != nil || !strings.Contains(string(raw), `"enabled":false`) { t.Fatal("disabled flag must be explicit", string(raw), err) } if _, err = s.GetDevices(ctx, &proto.GetDevicesReq{}); status.Code(err) != codes.FailedPrecondition { t.Fatal(err) } } func TestDeviceErrors(t *testing.T) { for _, test := range []struct { err error code codes.Code }{ {context.Canceled, codes.Canceled}, {context.DeadlineExceeded, codes.DeadlineExceeded}, {device_presence_service.ErrInvalid, codes.InvalidArgument}, {device_presence_service.ErrDisabled, codes.FailedPrecondition}, {device_presence_service.ErrPermission, codes.PermissionDenied}, {device_presence_service.ErrUnauthorized, codes.Unauthenticated}, {device_presence_service.ErrFull, codes.ResourceExhausted}, {team_service.ErrTeamNotFound, codes.NotFound}, {game_service.ErrGameNotFound, codes.NotFound}, {screen_service.ErrScreenNotFound, codes.Unauthenticated}, {errors.New("SQL password=secret /private/path"), codes.Internal}, } { err := deviceErrorStatus(test.err) if status.Code(err) != test.code || strings.Contains(err.Error(), "secret") || strings.Contains(err.Error(), "/private") { t.Fatal(err) } } }