Преглед на файлове

feat: allowed origin config, various fixes

    fix: floating point time value format
    fix: test concurrency resilience
    fix: scan command reference
    fix: lint
    feat: allow API urls without protocol (use protocol of origin)
    feat: allowed origins environment variable
    feat: limit key fps on development as it's slower
    fix: infinite loop when artists response is undefined
Fela Maslen преди 5 години
родител
ревизия
becaa449ea

+ 11 - 0
gmus-backend/pkg/config/config.go

@@ -7,6 +7,7 @@ import (
 	"os"
 	"path/filepath"
 	"strconv"
+	"strings"
 
 	"github.com/joho/godotenv"
 
@@ -129,6 +130,15 @@ func getRedisUrl() string {
 	return url
 }
 
+func getAllowedOrigins() []string {
+	origins, hasOrigins := os.LookupEnv("ALLOWED_ORIGINS")
+	if !hasOrigins {
+		return []string{"*"}
+	}
+
+	return strings.Split(origins, ",")
+}
+
 type config struct {
 	DatabaseUrl      string
 	LogLevel         logger.LogLevel
@@ -136,4 +146,5 @@ type config struct {
 	Host             string
 	Port             int
 	RedisUrl         string
+	AllowedOrigins   []string
 }

+ 1 - 0
gmus-backend/pkg/config/main.go

@@ -14,5 +14,6 @@ func GetConfig() config {
 		Host:             getListenHost(),
 		Port:             getPort(),
 		RedisUrl:         getRedisUrl(),
+		AllowedOrigins:   getAllowedOrigins(),
 	}
 }

+ 4 - 4
gmus-backend/pkg/repository/songs_test.go

@@ -172,14 +172,14 @@ var _ = Describe("songs repository", func() {
 			modifiedBatch[0].Title = "Title A modified"
 
 			BeforeEach(func() {
-				setup.PrepareDatabaseForTesting()
-
 				repository.BatchUpsertSongs(db, &songs, 2)
 				repository.BatchUpsertSongs(db, &modifiedBatch, 2)
 
+				result = []*read.Song{}
 				db.Select(&result, `
-	select track_number, title, artist, album, duration, base_path, relative_path, modified_date
-	from songs
+  select track_number, title, artist, album, duration, base_path, relative_path, modified_date
+  from songs
+  where relative_path in ('song1.ogg', 'song2.ogg')
 	`)
 			})
 

+ 4 - 1
gmus-backend/pkg/server/server.go

@@ -39,7 +39,10 @@ func StartServer() {
 
 	port := conf.Port
 
-	handler := cors.AllowAll().Handler(router)
+	handler := cors.New(cors.Options{
+		AllowedOrigins:   conf.AllowedOrigins,
+		AllowCredentials: true,
+	}).Handler(router)
 
 	l.Info("Starting server on %s:%d\n", conf.Host, port)
 	log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", conf.Host, port), handler))

+ 3 - 1
gmus-web/src/hooks/fetch/artists.ts

@@ -9,6 +9,8 @@ type ArtistsResponse = {
   artists: string[];
 };
 
+const emptyArtists: string[] = [];
+
 export function useArtists(): ArtistsResponse & {
   fetching: boolean;
 } {
@@ -24,7 +26,7 @@ export function useArtists(): ArtistsResponse & {
 
   useEffect(onFetch, [onFetch]);
 
-  return { artists: response?.artists ?? [], fetching };
+  return { artists: response?.artists ?? emptyArtists, fetching };
 }
 
 type ArtistDependencyResponse<K extends string, T> = { artist: string } & { [key in K]: T[] };

+ 1 - 2
gmus-web/src/hooks/request.spec.tsx

@@ -67,9 +67,8 @@ describe(useRequestCallback.name, () => {
       unmount();
     });
 
+    // eslint-disable-next-line jest/prefer-expect-assertions
     it('should set the response and loading state back to false', async () => {
-      expect.assertions(3);
-
       const { getByTestId, unmount } = setupRequest();
 
       await waitFor(() => {

+ 5 - 1
gmus-web/src/hooks/vim.ts

@@ -49,7 +49,11 @@ export function useVimBindings(dispatch: Dispatch<ActionKeyPressed>, skip = fals
     [dispatch],
   );
 
-  const listenerThrottled = useThrottleCallback(listener, 60, true);
+  const listenerThrottled = useThrottleCallback(
+    listener,
+    process.env.NODE_ENV === 'development' ? 15 : 60,
+    true,
+  );
 
   useEffect(() => {
     if (skip) {

+ 1 - 0
gmus-web/src/utils/time.spec.ts

@@ -12,6 +12,7 @@ describe(formatTime.name, () => {
     ${'more than one hour'}    | ${3615}   | ${'1:00:15'}
     ${'more than one day'}     | ${86465}  | ${'1 day, 01:05'}
     ${'negative values'}       | ${-86465} | ${'-1 day, 01:05'}
+    ${'floating point values'} | ${119.99} | ${'02:00'}
   `('should handle case: $case', ({ input, output }) => {
     expect.assertions(1);
     expect(formatTime(input)).toBe(output);

+ 1 - 1
gmus-web/src/utils/time.ts

@@ -5,7 +5,7 @@ export function formatTime(seconds: number | null): string {
     return '';
   }
 
-  const totalSecondsAbsolute = Math.abs(seconds);
+  const totalSecondsAbsolute = Math.abs(Math.round(seconds));
   const sign = seconds < 0 ? '-' : '';
 
   const hours = Math.floor(totalSecondsAbsolute / 3600);

+ 5 - 3
gmus-web/src/utils/url.spec.ts

@@ -7,13 +7,15 @@ describe(getPubsubUrl.name, () => {
   });
 
   describe.each`
-    case             | apiUrl                     | testCase          | expectedPubsubUrl
-    ${'is https'}    | ${'https://some.api:1876'} | ${'a secure URL'} | ${'wss://some.api:1876/pubsub'}
-    ${'has no port'} | ${'http://some.api'}       | ${'no port'}      | ${'ws://some.api/pubsub'}
+    case                 | apiUrl                     | testCase          | expectedPubsubUrl
+    ${'is https'}        | ${'https://some.api:1876'} | ${'a secure URL'} | ${'wss://some.api:1876/pubsub'}
+    ${'has no port'}     | ${'http://some.api'}       | ${'no port'}      | ${'ws://some.api/pubsub'}
+    ${'has no protocol'} | ${'//some.api'}            | ${'no protocol'}  | ${'ws://some.api/pubsub'}
   `('when the URL $case', ({ testCase, apiUrl, expectedPubsubUrl }) => {
     const envBefore = process.env.REACT_APP_API_URL;
     beforeAll(() => {
       process.env.REACT_APP_API_URL = apiUrl;
+      window.location.protocol = 'http:';
     });
     afterAll(() => {
       process.env.REACT_APP_API_URL = envBefore;

+ 5 - 1
gmus-web/src/utils/url.ts

@@ -1,5 +1,9 @@
 export function getApiUrl(): string {
-  return process.env.REACT_APP_API_URL ?? 'http://localhost:3000';
+  const baseUrl = process.env.REACT_APP_API_URL ?? 'http://localhost:3000';
+  if (baseUrl.startsWith('//')) {
+    return `${window.location.protocol}${baseUrl}`;
+  }
+  return baseUrl;
 }
 
 export function getPubsubUrl(): string {

+ 1 - 1
k8s/manifest.yml

@@ -257,7 +257,7 @@ spec:
             - name: gmus-scan
               image: docker.fela.space/gmus-backend:0
               args:
-                - scan
+                - gmus.scan
               envFrom:
                 - configMapRef:
                     name: gmus-backend