From b86851444a8e6bd4c47229b25ac896b1672bd73d Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Mon, 23 Sep 2024 06:02:25 -0500
Subject: [PATCH 01/20] OV-377: + add preview page with video player
---
.../bundles/common/enums/app-route.enum.ts | 1 +
.../src/bundles/preview/pages/preview.tsx | 21 +++++++++++++++++++
.../bundles/preview/pages/styles.module.css | 6 ++++++
frontend/src/routes/routes.tsx | 7 +++++++
4 files changed, 35 insertions(+)
create mode 100644 frontend/src/bundles/preview/pages/preview.tsx
create mode 100644 frontend/src/bundles/preview/pages/styles.module.css
diff --git a/frontend/src/bundles/common/enums/app-route.enum.ts b/frontend/src/bundles/common/enums/app-route.enum.ts
index d6526128a..158df0e85 100644
--- a/frontend/src/bundles/common/enums/app-route.enum.ts
+++ b/frontend/src/bundles/common/enums/app-route.enum.ts
@@ -6,6 +6,7 @@ const AppRoute = {
MY_AVATAR: '/my-avatar',
ANY: '*',
CREATE_AVATAR: '/create-avatar',
+ PREVIEW: '/preview',
} as const;
export { AppRoute };
diff --git a/frontend/src/bundles/preview/pages/preview.tsx b/frontend/src/bundles/preview/pages/preview.tsx
new file mode 100644
index 000000000..2384865a6
--- /dev/null
+++ b/frontend/src/bundles/preview/pages/preview.tsx
@@ -0,0 +1,21 @@
+import { Box, Header , VideoPlayer } from '~/bundles/common/components/components.js';
+
+import styles from './styles.module.css';
+
+const Preview: React.FC = () => {
+
+ return (
+
+
+
+
+ );
+};
+
+export { Preview };
diff --git a/frontend/src/bundles/preview/pages/styles.module.css b/frontend/src/bundles/preview/pages/styles.module.css
new file mode 100644
index 000000000..7317d0311
--- /dev/null
+++ b/frontend/src/bundles/preview/pages/styles.module.css
@@ -0,0 +1,6 @@
+.video-player {
+ height: 1000px;
+ width: 1000px;
+ position: relative;
+ background-color: var(--chakra-colors-gray-200);
+}
diff --git a/frontend/src/routes/routes.tsx b/frontend/src/routes/routes.tsx
index 1a6e2e18d..32e823ea9 100644
--- a/frontend/src/routes/routes.tsx
+++ b/frontend/src/routes/routes.tsx
@@ -6,6 +6,7 @@ import { NotFound } from '~/bundles/common/pages/not-found/not-found.js';
import { CreateAvatar } from '~/bundles/create-avatar/pages/create-avatar.js';
import { Home } from '~/bundles/home/pages/home.js';
import { MyAvatar } from '~/bundles/my-avatar/pages/my-avatar.js';
+import { Preview } from '~/bundles/preview/pages/preview.js';
import { Studio } from '~/bundles/studio/pages/studio.js';
const routes = [
@@ -57,6 +58,12 @@ const routes = [
path: AppRoute.ANY,
element: ,
},
+ {
+ path: AppRoute.PREVIEW,
+ element: (
+
+ ),
+ }
],
},
];
From 49af338d7e8206c4f3d4948e7b8fecde40e51c17 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Mon, 23 Sep 2024 08:30:02 -0500
Subject: [PATCH 02/20] OV-377: + add copy url button to homepage
---
.../src/bundles/common/api/video-api/videos-api.ts | 14 ++++++++++++++
.../common/icons/helper/icon-conversion.helper.ts | 3 +++
frontend/src/bundles/common/icons/icon-name.ts | 2 ++
.../home/components/video-card/video-card.tsx | 11 +++++++++++
frontend/src/bundles/home/store/actions.ts | 11 ++++++++++-
frontend/src/bundles/home/store/home.ts | 3 ++-
6 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/frontend/src/bundles/common/api/video-api/videos-api.ts b/frontend/src/bundles/common/api/video-api/videos-api.ts
index 3c8448a44..94d485e1c 100644
--- a/frontend/src/bundles/common/api/video-api/videos-api.ts
+++ b/frontend/src/bundles/common/api/video-api/videos-api.ts
@@ -81,6 +81,20 @@ class VideosApi extends BaseHttpApi {
await response.json();
}
+
+ public async createVideoUrl(id: string): Promise {
+ const response = await this.load(
+ this.getFullEndpoint(`${VideosApiPath.ROOT}${id}`, {}),
+ {
+ method: HTTPMethod.GET,
+ contentType: ContentType.JSON,
+ payload: JSON.stringify({}),
+ hasAuth: true,
+ },
+ );
+ //TODO: Response type should be changed
+ await response.json();
+ }
}
export { VideosApi };
diff --git a/frontend/src/bundles/common/icons/helper/icon-conversion.helper.ts b/frontend/src/bundles/common/icons/helper/icon-conversion.helper.ts
index 8b24d8759..a7442f954 100644
--- a/frontend/src/bundles/common/icons/helper/icon-conversion.helper.ts
+++ b/frontend/src/bundles/common/icons/helper/icon-conversion.helper.ts
@@ -3,6 +3,7 @@ import {
faCircleUser,
faCloudArrowDown,
faCloudArrowUp,
+ faCopy,
faEllipsisVertical,
faFileLines,
faFont,
@@ -41,12 +42,14 @@ const CloudArrowDown = convertIcon(faCloudArrowDown);
const VolumeHigh = convertIcon(faVolumeHigh);
const VolumeOff = convertIcon(faVolumeOff);
const Stop = convertIcon(faStop);
+const Copy = convertIcon(faCopy);
export {
BackwardStep,
CircleUser,
CloudArrowDown,
CloudArrowUp,
+ Copy,
EllipsisVertical,
FileLines,
Font,
diff --git a/frontend/src/bundles/common/icons/icon-name.ts b/frontend/src/bundles/common/icons/icon-name.ts
index 953788739..3a047ee89 100644
--- a/frontend/src/bundles/common/icons/icon-name.ts
+++ b/frontend/src/bundles/common/icons/icon-name.ts
@@ -18,6 +18,7 @@ import {
CircleUser,
CloudArrowDown,
CloudArrowUp,
+ Copy,
EllipsisVertical,
FileLines,
Font,
@@ -69,6 +70,7 @@ const IconName = {
LOGO_TEXT: LogoText,
DELETE: DeleteIcon,
WARNING: WarningIcon,
+ COPY: Copy,
} as const;
export { IconName };
diff --git a/frontend/src/bundles/home/components/video-card/video-card.tsx b/frontend/src/bundles/home/components/video-card/video-card.tsx
index 5e23438de..2d3de7d3c 100644
--- a/frontend/src/bundles/home/components/video-card/video-card.tsx
+++ b/frontend/src/bundles/home/components/video-card/video-card.tsx
@@ -94,6 +94,9 @@ const VideoCard: React.FC = ({
handleWarningModalClose();
}, [dispatch, handleWarningModalClose, id]);
+ const handleCopyButtonClick = useCallback(() => {
+ void dispatch(homeActions.createVideoUrl(id));
+ }, []);
return (
= ({
Delete
+ }
+ onClick={handleCopyButtonClick}
+ >
+
+ Copy video URL
+
+
diff --git a/frontend/src/bundles/home/store/actions.ts b/frontend/src/bundles/home/store/actions.ts
index 56bd864c7..430921232 100644
--- a/frontend/src/bundles/home/store/actions.ts
+++ b/frontend/src/bundles/home/store/actions.ts
@@ -24,4 +24,13 @@ const deleteVideo = createAsyncThunk, string, AsyncThunkConfig>(
},
);
-export { deleteVideo, loadUserVideos };
+const createVideoUrl = createAsyncThunk, string, AsyncThunkConfig>(
+ `${sliceName}/create-video-url`,
+ (payload, { extra }) => {
+ const { videosApi } = extra;
+
+ return videosApi.deleteVideo(payload);
+ },
+);
+
+export { createVideoUrl, deleteVideo, loadUserVideos };
diff --git a/frontend/src/bundles/home/store/home.ts b/frontend/src/bundles/home/store/home.ts
index 9b26c21f9..c4b6247ee 100644
--- a/frontend/src/bundles/home/store/home.ts
+++ b/frontend/src/bundles/home/store/home.ts
@@ -1,10 +1,11 @@
-import { deleteVideo, loadUserVideos } from './actions.js';
+import { createVideoUrl, deleteVideo, loadUserVideos, } from './actions.js';
import { actions } from './slice.js';
const allActions = {
...actions,
deleteVideo,
loadUserVideos,
+ createVideoUrl,
};
export { reducer } from './slice.js';
From 06e0c10274289185100908b386c6f15898e1e61c Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Mon, 23 Sep 2024 21:29:03 -0500
Subject: [PATCH 03/20] OV-377: + create JWT with video id and return it to
frontend
---
.../src/bundles/videos/video.controller.ts | 22 +++++++++++++++
backend/src/bundles/videos/video.service.ts | 6 ++++-
.../common/services/token/token.services.ts | 12 +++++++++
.../common/api/video-api/videos-api.ts | 27 ++++++++++---------
.../home/components/video-card/video-card.tsx | 14 ++++++++--
.../bundles/home/helpers/create-url-token.ts | 7 +++++
frontend/src/bundles/home/helpers/helpers.ts | 1 +
frontend/src/bundles/home/store/actions.ts | 5 ++--
.../videos/enums/videos-api-path.enum.ts | 1 +
9 files changed, 77 insertions(+), 18 deletions(-)
create mode 100644 frontend/src/bundles/home/helpers/create-url-token.ts
create mode 100644 frontend/src/bundles/home/helpers/helpers.ts
diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts
index 2ec2314d8..93cb6f5d8 100644
--- a/backend/src/bundles/videos/video.controller.ts
+++ b/backend/src/bundles/videos/video.controller.ts
@@ -109,6 +109,17 @@ class VideoController extends BaseController {
}>,
),
});
+ this.addRoute({
+ path: `${VideosApiPath.ID}/share`,
+ method: HTTPMethod.GET,
+ handler: (options) => {
+ return this.createVideoIdJWT(
+ options as ApiHandlerOptions<{
+ params: VideoGetOneRequestDto;
+ }>,
+ );
+ },
+ });
}
/**
@@ -186,6 +197,17 @@ class VideoController extends BaseController {
};
}
+ private async createVideoIdJWT(
+ options: ApiHandlerOptions<{
+ params: VideoGetOneRequestDto;
+ }>,
+ ): Promise {
+ return {
+ status: HTTPCode.OK,
+ payload: await this.videoService.getVideoIdToken(options.params.id),
+ };
+ }
+
/**
* @swagger
* /videos/:
diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts
index fad0bacb5..8b17eeab6 100644
--- a/backend/src/bundles/videos/video.service.ts
+++ b/backend/src/bundles/videos/video.service.ts
@@ -2,6 +2,7 @@ import { VideoEntity } from '~/bundles/videos/video.entity.js';
import { type VideoRepository } from '~/bundles/videos/video.repository.js';
import { HTTPCode, HttpError } from '~/common/http/http.js';
import { type FileService } from '~/common/services/file/file.service.js';
+import { tokenService } from '~/common/services/services.js';
import { type Service } from '~/common/types/types.js';
import { VideoValidationMessage } from './enums/enums.js';
@@ -15,7 +16,6 @@ import {
class VideoService implements Service {
private videoRepository: VideoRepository;
private fileService: FileService;
-
public constructor(
videoRepository: VideoRepository,
fileService: FileService,
@@ -100,6 +100,10 @@ class VideoService implements Service {
return isVideoDeleted;
}
+
+ public async getVideoIdToken(id: string): Promise {
+ return await tokenService.createVideoIdToken(id);
+ }
}
export { VideoService };
diff --git a/backend/src/common/services/token/token.services.ts b/backend/src/common/services/token/token.services.ts
index 3bef998a0..b0df2bb4c 100644
--- a/backend/src/common/services/token/token.services.ts
+++ b/backend/src/common/services/token/token.services.ts
@@ -17,6 +17,13 @@ class TokenService {
.sign(this.secretKey);
}
+ public async createVideoIdToken(videoId: string): Promise {
+ const jwt = await new SignJWT({ videoId })
+ .setProtectedHeader({ alg: 'HS256' })
+ .sign(this.secretKey);
+ return jwt.replaceAll('.', '-');
+ }
+
public async verifyToken(token: string): Promise {
try {
const { payload } = await jwtVerify(token, this.secretKey);
@@ -30,6 +37,11 @@ class TokenService {
const payload = await this.verifyToken(token);
return (payload?.['userId'] as string) || null;
}
+
+ public async getVideoIdFromToken(token: string): Promise {
+ const payload = await this.verifyToken(token);
+ return (payload?.['videoId'] as string) || null;
+ }
}
export { TokenService };
diff --git a/frontend/src/bundles/common/api/video-api/videos-api.ts b/frontend/src/bundles/common/api/video-api/videos-api.ts
index 94d485e1c..966eaafc4 100644
--- a/frontend/src/bundles/common/api/video-api/videos-api.ts
+++ b/frontend/src/bundles/common/api/video-api/videos-api.ts
@@ -82,18 +82,21 @@ class VideosApi extends BaseHttpApi {
await response.json();
}
- public async createVideoUrl(id: string): Promise {
- const response = await this.load(
- this.getFullEndpoint(`${VideosApiPath.ROOT}${id}`, {}),
- {
- method: HTTPMethod.GET,
- contentType: ContentType.JSON,
- payload: JSON.stringify({}),
- hasAuth: true,
- },
- );
- //TODO: Response type should be changed
- await response.json();
+ public async getVideoIdJWT(id: string): Promise {
+
+ const response = await this.load(
+ this.getFullEndpoint(`${VideosApiPath.ROOT}${id}/share`, {}),
+ {
+ method: HTTPMethod.GET,
+ contentType: ContentType.JSON,
+ hasAuth: true,
+ },
+ );
+
+ if (!response.ok) {
+ throw new Error(`Failed to get video ID JWT: ${response.statusText}`);
+ }
+ return await response.text();
}
}
diff --git a/frontend/src/bundles/home/components/video-card/video-card.tsx b/frontend/src/bundles/home/components/video-card/video-card.tsx
index 2d3de7d3c..d9a02052b 100644
--- a/frontend/src/bundles/home/components/video-card/video-card.tsx
+++ b/frontend/src/bundles/home/components/video-card/video-card.tsx
@@ -24,6 +24,7 @@ import {
useState,
} from '~/bundles/common/hooks/hooks.js';
import { IconName, IconSize } from '~/bundles/common/icons/icons.js';
+import { createVideoUrl } from '~/bundles/home/helpers/helpers.js';
import { actions as homeActions } from '~/bundles/home/store/home.js';
import { PlayerModal } from '../player-modal/player-modal.js';
@@ -95,8 +96,17 @@ const VideoCard: React.FC = ({
}, [dispatch, handleWarningModalClose, id]);
const handleCopyButtonClick = useCallback(() => {
- void dispatch(homeActions.createVideoUrl(id));
- }, []);
+ dispatch(homeActions.createVideoUrl(id))
+ .unwrap()
+ .then(async (jwt) => {
+ const token = await jwt;
+ createVideoUrl(token);
+ })
+ .catch((error) => {
+ alert(error.message);
+ });
+ }, [dispatch, id]);
+
return (
{
+ const baseUrl = 'http://localhost:3000';
+ return `${baseUrl}/preview/${jwtToken}`;
+};
+
+export { createVideoUrl };
\ No newline at end of file
diff --git a/frontend/src/bundles/home/helpers/helpers.ts b/frontend/src/bundles/home/helpers/helpers.ts
new file mode 100644
index 000000000..51239f491
--- /dev/null
+++ b/frontend/src/bundles/home/helpers/helpers.ts
@@ -0,0 +1 @@
+export { createVideoUrl } from './create-url-token.js';
\ No newline at end of file
diff --git a/frontend/src/bundles/home/store/actions.ts b/frontend/src/bundles/home/store/actions.ts
index 430921232..05797904d 100644
--- a/frontend/src/bundles/home/store/actions.ts
+++ b/frontend/src/bundles/home/store/actions.ts
@@ -24,12 +24,11 @@ const deleteVideo = createAsyncThunk, string, AsyncThunkConfig>(
},
);
-const createVideoUrl = createAsyncThunk, string, AsyncThunkConfig>(
+const createVideoUrl = createAsyncThunk, string, AsyncThunkConfig>(
`${sliceName}/create-video-url`,
(payload, { extra }) => {
const { videosApi } = extra;
-
- return videosApi.deleteVideo(payload);
+ return videosApi.getVideoIdJWT(payload);
},
);
diff --git a/shared/src/bundles/videos/enums/videos-api-path.enum.ts b/shared/src/bundles/videos/enums/videos-api-path.enum.ts
index 82abbdcfa..0832c0367 100644
--- a/shared/src/bundles/videos/enums/videos-api-path.enum.ts
+++ b/shared/src/bundles/videos/enums/videos-api-path.enum.ts
@@ -1,6 +1,7 @@
const VideosApiPath = {
ROOT: '/',
ID: '/:id',
+ SHARE: '/share',
} as const;
export { VideosApiPath };
From 945fac9d0e6c14de9a07becbb91443a8b54faaf9 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Tue, 24 Sep 2024 03:39:47 -0500
Subject: [PATCH 04/20] OV-377: + copy url to clipboard
---
.../src/bundles/home/components/video-card/video-card.tsx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/frontend/src/bundles/home/components/video-card/video-card.tsx b/frontend/src/bundles/home/components/video-card/video-card.tsx
index d9a02052b..6c5860d6f 100644
--- a/frontend/src/bundles/home/components/video-card/video-card.tsx
+++ b/frontend/src/bundles/home/components/video-card/video-card.tsx
@@ -30,6 +30,7 @@ import { actions as homeActions } from '~/bundles/home/store/home.js';
import { PlayerModal } from '../player-modal/player-modal.js';
import { DeleteWarning } from './components/delete-warning.js';
import styles from './styles.module.css';
+import { notificationService } from '~/bundles/common/services/services.js';
type Properties = {
id: string;
@@ -100,11 +101,14 @@ const VideoCard: React.FC = ({
.unwrap()
.then(async (jwt) => {
const token = await jwt;
- createVideoUrl(token);
+ const url = createVideoUrl(token);
+ await navigator.clipboard.writeText(createVideoUrl(url));
+
})
.catch((error) => {
- alert(error.message);
+ throw new Error(`Failed to get video ID JWT: ${error}`);
});
+
}, [dispatch, id]);
return (
From c19a3fafcd860899205b06f68d16a1682cd1fe8c Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Tue, 24 Sep 2024 04:55:42 -0500
Subject: [PATCH 05/20] OV-377: + create dynamic preview url
---
.../src/bundles/videos/video.controller.ts | 26 +++++++++++++++++++
.../common/api/video-api/videos-api.ts | 16 ++++++++++++
.../home/components/video-card/video-card.tsx | 8 +++---
frontend/src/bundles/home/store/actions.ts | 4 +--
frontend/src/bundles/home/store/home.ts | 4 +--
.../preview/components/preview-wrapper.tsx | 10 +++++++
.../src/bundles/preview/pages/preview.tsx | 7 ++++-
frontend/src/routes/routes.tsx | 6 ++---
8 files changed, 69 insertions(+), 12 deletions(-)
create mode 100644 frontend/src/bundles/preview/components/preview-wrapper.tsx
diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts
index 93cb6f5d8..0aaa10dd5 100644
--- a/backend/src/bundles/videos/video.controller.ts
+++ b/backend/src/bundles/videos/video.controller.ts
@@ -197,6 +197,32 @@ class VideoController extends BaseController {
};
}
+ /**
+ * @swagger
+ * /videos/{id}/share:
+ * get:
+ * parameters:
+ * - in: path
+ * name: id
+ * required: true
+ * schema:
+ * type: string
+ * format: uuid
+ * description: The video id
+ * description: Create a JWT for the video id
+ * security:
+ * - bearerAuth: []
+ * responses:
+ * 200:
+ * description: Successful operation
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * token:
+ * type: string
+ */
private async createVideoIdJWT(
options: ApiHandlerOptions<{
params: VideoGetOneRequestDto;
diff --git a/frontend/src/bundles/common/api/video-api/videos-api.ts b/frontend/src/bundles/common/api/video-api/videos-api.ts
index 966eaafc4..74d7f8892 100644
--- a/frontend/src/bundles/common/api/video-api/videos-api.ts
+++ b/frontend/src/bundles/common/api/video-api/videos-api.ts
@@ -68,6 +68,22 @@ class VideosApi extends BaseHttpApi {
return await response.json();
}
+ public async getVideo(
+ payload: UpdateVideoRequestDto,
+ id: string,
+ ): Promise {
+ const response = await this.load(
+ this.getFullEndpoint(VideosApiPath.ID, { id }),
+ {
+ method: HTTPMethod.GET,
+ contentType: ContentType.JSON,
+ hasAuth: true,
+ },
+ );
+
+ return await response.json();
+ }
+
public async deleteVideo(id: string): Promise {
const response = await this.load(
this.getFullEndpoint(`${VideosApiPath.ROOT}${id}`, {}),
diff --git a/frontend/src/bundles/home/components/video-card/video-card.tsx b/frontend/src/bundles/home/components/video-card/video-card.tsx
index 6c5860d6f..41a094e88 100644
--- a/frontend/src/bundles/home/components/video-card/video-card.tsx
+++ b/frontend/src/bundles/home/components/video-card/video-card.tsx
@@ -24,13 +24,13 @@ import {
useState,
} from '~/bundles/common/hooks/hooks.js';
import { IconName, IconSize } from '~/bundles/common/icons/icons.js';
+import { notificationService } from '~/bundles/common/services/services.js';
import { createVideoUrl } from '~/bundles/home/helpers/helpers.js';
import { actions as homeActions } from '~/bundles/home/store/home.js';
import { PlayerModal } from '../player-modal/player-modal.js';
import { DeleteWarning } from './components/delete-warning.js';
import styles from './styles.module.css';
-import { notificationService } from '~/bundles/common/services/services.js';
type Properties = {
id: string;
@@ -97,13 +97,13 @@ const VideoCard: React.FC = ({
}, [dispatch, handleWarningModalClose, id]);
const handleCopyButtonClick = useCallback(() => {
- dispatch(homeActions.createVideoUrl(id))
+ dispatch(homeActions.getJwt(id))
.unwrap()
.then(async (jwt) => {
const token = await jwt;
const url = createVideoUrl(token);
- await navigator.clipboard.writeText(createVideoUrl(url));
-
+ await navigator.clipboard.writeText(url);
+ notificationService.success({ message: 'Url copied to clipboard', id : 'url-copied', title : 'Success' });
})
.catch((error) => {
throw new Error(`Failed to get video ID JWT: ${error}`);
diff --git a/frontend/src/bundles/home/store/actions.ts b/frontend/src/bundles/home/store/actions.ts
index 05797904d..3312e2cd5 100644
--- a/frontend/src/bundles/home/store/actions.ts
+++ b/frontend/src/bundles/home/store/actions.ts
@@ -24,7 +24,7 @@ const deleteVideo = createAsyncThunk, string, AsyncThunkConfig>(
},
);
-const createVideoUrl = createAsyncThunk, string, AsyncThunkConfig>(
+const getJwt = createAsyncThunk, string, AsyncThunkConfig>(
`${sliceName}/create-video-url`,
(payload, { extra }) => {
const { videosApi } = extra;
@@ -32,4 +32,4 @@ const createVideoUrl = createAsyncThunk, string, AsyncThunkConfi
},
);
-export { createVideoUrl, deleteVideo, loadUserVideos };
+export { deleteVideo, getJwt, loadUserVideos };
diff --git a/frontend/src/bundles/home/store/home.ts b/frontend/src/bundles/home/store/home.ts
index c4b6247ee..f97fc0dbb 100644
--- a/frontend/src/bundles/home/store/home.ts
+++ b/frontend/src/bundles/home/store/home.ts
@@ -1,11 +1,11 @@
-import { createVideoUrl, deleteVideo, loadUserVideos, } from './actions.js';
+import { deleteVideo, getJwt, loadUserVideos, } from './actions.js';
import { actions } from './slice.js';
const allActions = {
...actions,
deleteVideo,
loadUserVideos,
- createVideoUrl,
+ getJwt,
};
export { reducer } from './slice.js';
diff --git a/frontend/src/bundles/preview/components/preview-wrapper.tsx b/frontend/src/bundles/preview/components/preview-wrapper.tsx
new file mode 100644
index 000000000..631934df9
--- /dev/null
+++ b/frontend/src/bundles/preview/components/preview-wrapper.tsx
@@ -0,0 +1,10 @@
+import { useParams } from 'react-router-dom';
+
+import { Preview } from '~/bundles/preview/pages/preview.js';
+
+const PreviewWrapper: React.FC = () => {
+ const { id } = useParams<{ id: string }>();
+ return ;
+};
+
+export { PreviewWrapper };
\ No newline at end of file
diff --git a/frontend/src/bundles/preview/pages/preview.tsx b/frontend/src/bundles/preview/pages/preview.tsx
index 2384865a6..6a361d3c9 100644
--- a/frontend/src/bundles/preview/pages/preview.tsx
+++ b/frontend/src/bundles/preview/pages/preview.tsx
@@ -2,12 +2,17 @@ import { Box, Header , VideoPlayer } from '~/bundles/common/components/component
import styles from './styles.module.css';
-const Preview: React.FC = () => {
+type Properties = {
+ id: string;
+};
+
+const Preview: React.FC = ({ id }) => {
return (
+ {id}
,
},
{
- path: AppRoute.PREVIEW,
+ path: `${AppRoute.PREVIEW}/:id`,
element: (
-
+
),
}
],
From 01bf93f9c48d0c8ce00eb87e4a625dfd45a4289c Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Wed, 25 Sep 2024 06:50:39 -0500
Subject: [PATCH 06/20] OV-377: + create public-video controller and service
---
.../src/bundles/public-video/enums/enums.ts | 1 +
.../enums/public-videos-api-path.enum.ts | 5 +++
.../public-video/public-video.controller.ts | 40 +++++++++++++++++
.../public-video/public-video.service.ts | 43 +++++++++++++++++++
.../src/bundles/public-video/public-videos.ts | 12 ++++++
.../controller/base-controller.package.ts | 3 +-
.../types/api-handler-options.type.ts | 2 +
.../server-application/server-application.ts | 3 ++
.../common/services/token/token.services.ts | 2 +-
frontend/src/bundles/common/api/api.ts | 9 +++-
.../api/public-video-api/enums/enums.ts | 1 +
.../api/public-video-api/public-videos-api.ts | 43 +++++++++++++++++++
.../preview/components/preview-wrapper.tsx | 4 +-
.../src/bundles/preview/pages/preview.tsx | 40 ++++++++++++-----
frontend/src/bundles/preview/store/actions.ts | 13 ++++++
.../http-api/base-http-api.package.ts | 8 +++-
.../http-api/types/http-api-options.type.ts | 1 +
frontend/src/framework/store/store.package.ts | 4 +-
frontend/src/routes/routes.tsx | 2 +-
shared/src/enums/api-path.enum.ts | 1 +
20 files changed, 219 insertions(+), 18 deletions(-)
create mode 100644 backend/src/bundles/public-video/enums/enums.ts
create mode 100644 backend/src/bundles/public-video/enums/public-videos-api-path.enum.ts
create mode 100644 backend/src/bundles/public-video/public-video.controller.ts
create mode 100644 backend/src/bundles/public-video/public-video.service.ts
create mode 100644 backend/src/bundles/public-video/public-videos.ts
create mode 100644 frontend/src/bundles/common/api/public-video-api/enums/enums.ts
create mode 100644 frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
create mode 100644 frontend/src/bundles/preview/store/actions.ts
diff --git a/backend/src/bundles/public-video/enums/enums.ts b/backend/src/bundles/public-video/enums/enums.ts
new file mode 100644
index 000000000..2f314a44f
--- /dev/null
+++ b/backend/src/bundles/public-video/enums/enums.ts
@@ -0,0 +1 @@
+export { VideosApiPath, VideoValidationMessage } from 'shared';
diff --git a/backend/src/bundles/public-video/enums/public-videos-api-path.enum.ts b/backend/src/bundles/public-video/enums/public-videos-api-path.enum.ts
new file mode 100644
index 000000000..d41af0187
--- /dev/null
+++ b/backend/src/bundles/public-video/enums/public-videos-api-path.enum.ts
@@ -0,0 +1,5 @@
+const PublicVideosApiPath = {
+ ROOT: '/',
+} as const;
+
+export { PublicVideosApiPath };
diff --git a/backend/src/bundles/public-video/public-video.controller.ts b/backend/src/bundles/public-video/public-video.controller.ts
new file mode 100644
index 000000000..bbf999f77
--- /dev/null
+++ b/backend/src/bundles/public-video/public-video.controller.ts
@@ -0,0 +1,40 @@
+import { type PublicVideoService } from '~/bundles/public-video/public-video.service.js';
+import {
+ type ApiHandlerOptions,
+ type ApiHandlerResponse,
+ BaseController,
+} from '~/common/controller/controller.js';
+import { HTTPCode, HTTPMethod } from '~/common/http/http.js';
+import { type Logger } from '~/common/logger/logger.js';
+
+import { PublicVideosApiPath } from './enums/public-videos-api-path.enum.js';
+
+class PublicVideoController extends BaseController {
+ private publicVideoService: PublicVideoService;
+
+ public constructor(logger: Logger, publicVideoService: PublicVideoService) {
+ super(logger, '/public-video');
+
+ this.publicVideoService = publicVideoService;
+
+ this.addRoute({
+ path: PublicVideosApiPath.ROOT,
+ method: HTTPMethod.GET,
+ handler: (options) => this.findUrlByToken(options),
+ });
+ }
+
+ private async findUrlByToken(
+ options: ApiHandlerOptions,
+ ): Promise {
+ const headers = options.headers as Record;
+ const videoTokenHeader = headers['video_token']?.toString() ?? '';
+
+ return {
+ status: HTTPCode.OK,
+ payload: await this.publicVideoService.findUrlByToken(videoTokenHeader ?? ''),
+ };
+ }
+}
+
+export { PublicVideoController };
diff --git a/backend/src/bundles/public-video/public-video.service.ts b/backend/src/bundles/public-video/public-video.service.ts
new file mode 100644
index 000000000..f95cccd1d
--- /dev/null
+++ b/backend/src/bundles/public-video/public-video.service.ts
@@ -0,0 +1,43 @@
+import { type VideoRepository } from '~/bundles/videos/video.repository.js';
+import { HTTPCode, HttpError } from '~/common/http/http.js';
+import { tokenService } from '~/common/services/services.js';
+
+import { VideoValidationMessage } from './enums/enums.js';
+
+class PublicVideoService {
+ private videoRepository: VideoRepository;
+ public constructor(
+ videoRepository: VideoRepository,
+ ) {
+ this.videoRepository = videoRepository;
+ }
+
+ public async findUrlByToken(token: string): Promise {
+ const id = await tokenService.getVideoIdFromToken(token);
+
+ if (!id) {
+ this.throwVideoNotFoundError();
+ }
+
+ const video = await this.videoRepository.findById(id);
+
+ if (!video) {
+ this.throwVideoNotFoundError();
+ }
+
+ const url = video.toObject().url;
+ if (!url) {
+ this.throwVideoNotFoundError();
+ }
+ return url;
+ }
+
+ private throwVideoNotFoundError(): never {
+ throw new HttpError({
+ message: VideoValidationMessage.VIDEO_DOESNT_EXIST,
+ status: HTTPCode.NOT_FOUND,
+ });
+ }
+}
+
+export { PublicVideoService };
diff --git a/backend/src/bundles/public-video/public-videos.ts b/backend/src/bundles/public-video/public-videos.ts
new file mode 100644
index 000000000..0018fc4b1
--- /dev/null
+++ b/backend/src/bundles/public-video/public-videos.ts
@@ -0,0 +1,12 @@
+import { VideoModel } from '~/bundles/videos/video.model.js';
+import { VideoRepository } from '~/bundles/videos/video.repository.js';
+import { logger } from '~/common/logger/logger.js';
+
+import { PublicVideoController } from './public-video.controller.js';
+import { PublicVideoService } from './public-video.service.js';
+
+const videoRepository = new VideoRepository(VideoModel);
+const videoService = new PublicVideoService(videoRepository);
+const publicVideoController = new PublicVideoController(logger, videoService);
+
+export { publicVideoController };
diff --git a/backend/src/common/controller/base-controller.package.ts b/backend/src/common/controller/base-controller.package.ts
index 3ec714afd..eb3bcfd70 100644
--- a/backend/src/common/controller/base-controller.package.ts
+++ b/backend/src/common/controller/base-controller.package.ts
@@ -49,7 +49,7 @@ class BaseController implements Controller {
private mapRequest(
request: Parameters[0],
): ApiHandlerOptions {
- const { body, query, params, session, user } = request;
+ const { body, query, params, session, user, headers } = request;
return {
body,
@@ -57,6 +57,7 @@ class BaseController implements Controller {
params,
session,
user,
+ headers,
};
}
}
diff --git a/backend/src/common/controller/types/api-handler-options.type.ts b/backend/src/common/controller/types/api-handler-options.type.ts
index 0aee24e31..07838befe 100644
--- a/backend/src/common/controller/types/api-handler-options.type.ts
+++ b/backend/src/common/controller/types/api-handler-options.type.ts
@@ -4,6 +4,7 @@ type DefaultApiHandlerOptions = {
params?: unknown;
session?: unknown;
user?: unknown;
+ headers?: unknown;
};
type ApiHandlerOptions<
@@ -14,6 +15,7 @@ type ApiHandlerOptions<
params: T['params'];
session: T['session'];
user: T['user'];
+ headers: T['headers'];
};
export { type ApiHandlerOptions };
diff --git a/backend/src/common/server-application/server-application.ts b/backend/src/common/server-application/server-application.ts
index f940b4b54..67e8701fd 100644
--- a/backend/src/common/server-application/server-application.ts
+++ b/backend/src/common/server-application/server-application.ts
@@ -3,6 +3,7 @@ import { avatarVideoController } from '~/bundles/avatar-videos/avatar-videos.js'
import { avatarController } from '~/bundles/avatars/avatars.js';
import { chatController } from '~/bundles/chat/chat.js';
import { notificationController } from '~/bundles/notifications/notifications.js';
+import { publicVideoController } from '~/bundles/public-video/public-videos.js';
import { speechController } from '~/bundles/speech/speech.js';
import { userController } from '~/bundles/users/users.js';
import { videoController } from '~/bundles/videos/videos.js';
@@ -24,6 +25,8 @@ const apiV1 = new BaseServerAppApi(
...chatController.routes,
...speechController.routes,
...avatarVideoController.routes,
+ ...publicVideoController.routes,
+
);
const serverApp = new BaseServerApp({
diff --git a/backend/src/common/services/token/token.services.ts b/backend/src/common/services/token/token.services.ts
index b0df2bb4c..cd06b720a 100644
--- a/backend/src/common/services/token/token.services.ts
+++ b/backend/src/common/services/token/token.services.ts
@@ -21,7 +21,7 @@ class TokenService {
const jwt = await new SignJWT({ videoId })
.setProtectedHeader({ alg: 'HS256' })
.sign(this.secretKey);
- return jwt.replaceAll('.', '-');
+ return jwt.replaceAll('.', '~');
}
public async verifyToken(token: string): Promise {
diff --git a/frontend/src/bundles/common/api/api.ts b/frontend/src/bundles/common/api/api.ts
index b492f9ff0..2a2663498 100644
--- a/frontend/src/bundles/common/api/api.ts
+++ b/frontend/src/bundles/common/api/api.ts
@@ -2,6 +2,7 @@ import { config } from '~/framework/config/config.js';
import { http } from '~/framework/http/http.js';
import { storage } from '~/framework/storage/storage.js';
+import { PublicVideosApi } from './public-video-api/public-videos-api.js';
import { VideosApi } from './video-api/videos-api.js';
const videosApi = new VideosApi({
@@ -10,4 +11,10 @@ const videosApi = new VideosApi({
http,
});
-export { videosApi };
+const publicVideosApi = new PublicVideosApi({
+ baseUrl: config.ENV.API.ORIGIN_URL,
+ storage,
+ http,
+});
+
+export { publicVideosApi,videosApi };
diff --git a/frontend/src/bundles/common/api/public-video-api/enums/enums.ts b/frontend/src/bundles/common/api/public-video-api/enums/enums.ts
new file mode 100644
index 000000000..7e0da47c3
--- /dev/null
+++ b/frontend/src/bundles/common/api/public-video-api/enums/enums.ts
@@ -0,0 +1 @@
+export { VideosApiPath } from 'shared';
diff --git a/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts b/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
new file mode 100644
index 000000000..c6851b3a7
--- /dev/null
+++ b/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
@@ -0,0 +1,43 @@
+import { ApiPath, ContentType } from '~/bundles/common/enums/enums.js';
+import { type Http, HTTPMethod } from '~/framework/http/http.js';
+import { BaseHttpApi } from '~/framework/http-api/http-api.js';
+import { type Storage } from '~/framework/storage/storage.js';
+
+import { VideosApiPath } from './enums/enums.js';
+
+type Constructor = {
+ baseUrl: string;
+ http: Http;
+ storage: Storage;
+};
+
+class PublicVideosApi extends BaseHttpApi {
+ public constructor({ baseUrl, http, storage }: Constructor) {
+ super({ path: ApiPath.PUBLIC_VIDEO, baseUrl, http, storage });
+ }
+
+ public async getVideoUrlFromJWT(jwt: string): Promise {
+
+ const headers = new Headers();
+ headers.append('video_token', jwt.replaceAll('~', '.'));
+
+ const options = {
+ method: HTTPMethod.GET,
+ contentType: ContentType.JSON,
+ hasAuth: true,
+ customHeaders: headers,
+ };
+
+ const response = await this.load(
+ this.getFullEndpoint(`/public-video${VideosApiPath.ROOT}`, {}),
+ options,
+ );
+
+ if (!response.ok) {
+ throw new Error(`Failed to get video ID JWT: ${response.statusText}`);
+ }
+ return await response.text();
+}
+}
+
+export { PublicVideosApi };
diff --git a/frontend/src/bundles/preview/components/preview-wrapper.tsx b/frontend/src/bundles/preview/components/preview-wrapper.tsx
index 631934df9..4d70848f8 100644
--- a/frontend/src/bundles/preview/components/preview-wrapper.tsx
+++ b/frontend/src/bundles/preview/components/preview-wrapper.tsx
@@ -3,8 +3,8 @@ import { useParams } from 'react-router-dom';
import { Preview } from '~/bundles/preview/pages/preview.js';
const PreviewWrapper: React.FC = () => {
- const { id } = useParams<{ id: string }>();
- return ;
+ const { jwt } = useParams<{ jwt: string }>();
+ return ;
};
export { PreviewWrapper };
\ No newline at end of file
diff --git a/frontend/src/bundles/preview/pages/preview.tsx b/frontend/src/bundles/preview/pages/preview.tsx
index 6a361d3c9..8407d32e1 100644
--- a/frontend/src/bundles/preview/pages/preview.tsx
+++ b/frontend/src/bundles/preview/pages/preview.tsx
@@ -1,20 +1,40 @@
-import { Box, Header , VideoPlayer } from '~/bundles/common/components/components.js';
+import { Box, Header, Loader, VideoPlayer } from '~/bundles/common/components/components.js';
+import { useAppDispatch, useEffect, useState } from '~/bundles/common/hooks/hooks.js';
+import { getUrl } from '../store/actions.js';
import styles from './styles.module.css';
type Properties = {
- id: string;
+ jwt: string;
};
-const Preview: React.FC = ({ id }) => {
-
+const Preview: React.FC = ({ jwt }) => {
+ const dispatch = useAppDispatch();
+ const [url, setUrl] = useState('');
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ const fetchUrl = async (): Promise => {
+ try {
+ const result = await dispatch(getUrl(jwt)).unwrap();
+ setUrl(result);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchUrl().catch(error => {throw new Error(error); });
+ }, [dispatch, jwt]);
+
+ if (loading) {
+ return ;
+ }
+
return (
-
-
- {id}
+
+
= ({ id }) => {
);
};
-export { Preview };
+export { Preview };
\ No newline at end of file
diff --git a/frontend/src/bundles/preview/store/actions.ts b/frontend/src/bundles/preview/store/actions.ts
new file mode 100644
index 000000000..57baeb9e0
--- /dev/null
+++ b/frontend/src/bundles/preview/store/actions.ts
@@ -0,0 +1,13 @@
+import { createAsyncThunk } from '@reduxjs/toolkit';
+
+import { type AsyncThunkConfig } from '~/bundles/common/types/types.js';
+
+const getUrl = createAsyncThunk, string, AsyncThunkConfig>(
+ 'preview/create-video-url',
+ (payload, { extra }) => {
+ const { publicVideosApi } = extra;
+ return publicVideosApi.getVideoUrlFromJWT(payload);
+ },
+);
+
+export { getUrl };
diff --git a/frontend/src/framework/http-api/base-http-api.package.ts b/frontend/src/framework/http-api/base-http-api.package.ts
index 48fadbd2d..90d86c912 100644
--- a/frontend/src/framework/http-api/base-http-api.package.ts
+++ b/frontend/src/framework/http-api/base-http-api.package.ts
@@ -51,9 +51,15 @@ class BaseHttpApi implements HttpApi {
hasAuth,
credentials = 'same-origin',
keepAlive = false,
+ customHeaders,
} = options;
-
+
const headers = await this.getHeaders(contentType, hasAuth);
+ if (customHeaders) {
+ for (const [key, value] of customHeaders) {
+ headers.append(key, value);
+ }
+ }
const response = await this.http.load(path, {
method,
diff --git a/frontend/src/framework/http-api/types/http-api-options.type.ts b/frontend/src/framework/http-api/types/http-api-options.type.ts
index 2a635c599..4c44b70b7 100644
--- a/frontend/src/framework/http-api/types/http-api-options.type.ts
+++ b/frontend/src/framework/http-api/types/http-api-options.type.ts
@@ -11,6 +11,7 @@ type HTTPApiOptions = Omit<
payload?: HttpOptions['payload'];
credentials?: HttpOptions['credentials'];
keepAlive?: HttpOptions['keepAlive'];
+ customHeaders?: HttpOptions['headers'];
};
export { type HTTPApiOptions };
diff --git a/frontend/src/framework/store/store.package.ts b/frontend/src/framework/store/store.package.ts
index 33e2f8f29..15ec62bec 100644
--- a/frontend/src/framework/store/store.package.ts
+++ b/frontend/src/framework/store/store.package.ts
@@ -9,7 +9,7 @@ import { authApi } from '~/bundles/auth/auth.js';
import { reducer as authReducer } from '~/bundles/auth/store/auth.js';
import { chatApi } from '~/bundles/chat/chat.js';
import { reducer as chatReducer } from '~/bundles/chat/store/chat.js';
-import { videosApi } from '~/bundles/common/api/api.js';
+import { publicVideosApi, videosApi } from '~/bundles/common/api/api.js';
import { AppEnvironment } from '~/bundles/common/enums/enums.js';
import {
draftMiddleware,
@@ -42,6 +42,7 @@ type ExtraArguments = {
avatarVideosApi: typeof avatarVideosApi;
chatApi: typeof chatApi;
storage: typeof storage;
+ publicVideosApi: typeof publicVideosApi;
};
class Store {
@@ -87,6 +88,7 @@ class Store {
avatarVideosApi,
chatApi,
storage,
+ publicVideosApi,
};
}
}
diff --git a/frontend/src/routes/routes.tsx b/frontend/src/routes/routes.tsx
index b5a58fc6d..08e6cdf6c 100644
--- a/frontend/src/routes/routes.tsx
+++ b/frontend/src/routes/routes.tsx
@@ -59,7 +59,7 @@ const routes = [
element: ,
},
{
- path: `${AppRoute.PREVIEW}/:id`,
+ path: `${AppRoute.PREVIEW}/:jwt`,
element: (
),
diff --git a/shared/src/enums/api-path.enum.ts b/shared/src/enums/api-path.enum.ts
index a3429e663..b2d8fe95a 100644
--- a/shared/src/enums/api-path.enum.ts
+++ b/shared/src/enums/api-path.enum.ts
@@ -8,6 +8,7 @@ const ApiPath = {
CHAT: '/chat',
SPEECH: '/speech',
AVATAR_VIDEO: '/avatar-video',
+ PUBLIC_VIDEO: '/public-video',
} as const;
export { ApiPath };
From 5e9044d7b2af4a3c24ddff6e0862f1f05550b274 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Wed, 25 Sep 2024 08:14:49 -0500
Subject: [PATCH 07/20] OV-377: + white route public-video
---
backend/src/bundles/public-video/public-video.controller.ts | 5 +++--
backend/src/common/constants/white-routes.constants.ts | 4 ++++
.../common/api/public-video-api/public-videos-api.ts | 6 +++---
frontend/src/bundles/preview/pages/preview.tsx | 1 +
frontend/src/bundles/preview/store/actions.ts | 1 +
5 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/backend/src/bundles/public-video/public-video.controller.ts b/backend/src/bundles/public-video/public-video.controller.ts
index bbf999f77..7c813113f 100644
--- a/backend/src/bundles/public-video/public-video.controller.ts
+++ b/backend/src/bundles/public-video/public-video.controller.ts
@@ -4,6 +4,7 @@ import {
type ApiHandlerResponse,
BaseController,
} from '~/common/controller/controller.js';
+import { ApiPath } from '~/common/enums/enums.js';
import { HTTPCode, HTTPMethod } from '~/common/http/http.js';
import { type Logger } from '~/common/logger/logger.js';
@@ -13,7 +14,7 @@ class PublicVideoController extends BaseController {
private publicVideoService: PublicVideoService;
public constructor(logger: Logger, publicVideoService: PublicVideoService) {
- super(logger, '/public-video');
+ super(logger, ApiPath.PUBLIC_VIDEO);
this.publicVideoService = publicVideoService;
@@ -29,7 +30,7 @@ class PublicVideoController extends BaseController {
): Promise {
const headers = options.headers as Record;
const videoTokenHeader = headers['video_token']?.toString() ?? '';
-
+
return {
status: HTTPCode.OK,
payload: await this.publicVideoService.findUrlByToken(videoTokenHeader ?? ''),
diff --git a/backend/src/common/constants/white-routes.constants.ts b/backend/src/common/constants/white-routes.constants.ts
index 4af3ddb56..5a592caa2 100644
--- a/backend/src/common/constants/white-routes.constants.ts
+++ b/backend/src/common/constants/white-routes.constants.ts
@@ -11,6 +11,10 @@ const WHITE_ROUTES = [
path: `/api/v1${ApiPath.AUTH}${AuthApiPath.SIGN_UP}`,
method: HTTPMethod.POST,
},
+ {
+ path: `/api/v1${ApiPath.PUBLIC_VIDEO}/`,
+ method: HTTPMethod.GET,
+ },
{
path: /\/v1\/documentation\/.*/,
method: HTTPMethod.GET,
diff --git a/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts b/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
index c6851b3a7..6793bdffb 100644
--- a/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
+++ b/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
@@ -20,7 +20,7 @@ class PublicVideosApi extends BaseHttpApi {
const headers = new Headers();
headers.append('video_token', jwt.replaceAll('~', '.'));
-
+
const options = {
method: HTTPMethod.GET,
contentType: ContentType.JSON,
@@ -29,10 +29,10 @@ class PublicVideosApi extends BaseHttpApi {
};
const response = await this.load(
- this.getFullEndpoint(`/public-video${VideosApiPath.ROOT}`, {}),
+ this.getFullEndpoint(`${VideosApiPath.ROOT}`, {}),
options,
);
-
+
if (!response.ok) {
throw new Error(`Failed to get video ID JWT: ${response.statusText}`);
}
diff --git a/frontend/src/bundles/preview/pages/preview.tsx b/frontend/src/bundles/preview/pages/preview.tsx
index 8407d32e1..8e0ca76e5 100644
--- a/frontend/src/bundles/preview/pages/preview.tsx
+++ b/frontend/src/bundles/preview/pages/preview.tsx
@@ -17,6 +17,7 @@ const Preview: React.FC = ({ jwt }) => {
const fetchUrl = async (): Promise => {
try {
const result = await dispatch(getUrl(jwt)).unwrap();
+
setUrl(result);
} finally {
setLoading(false);
diff --git a/frontend/src/bundles/preview/store/actions.ts b/frontend/src/bundles/preview/store/actions.ts
index 57baeb9e0..7a72985bf 100644
--- a/frontend/src/bundles/preview/store/actions.ts
+++ b/frontend/src/bundles/preview/store/actions.ts
@@ -6,6 +6,7 @@ const getUrl = createAsyncThunk, string, AsyncThunkConfig>(
'preview/create-video-url',
(payload, { extra }) => {
const { publicVideosApi } = extra;
+
return publicVideosApi.getVideoUrlFromJWT(payload);
},
);
From ba2031e5e4a33b601e46b6a608ef59359f8d7448 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Wed, 25 Sep 2024 09:01:37 -0500
Subject: [PATCH 08/20] OV-377: + style preview page
---
.../src/bundles/preview/pages/preview.tsx | 19 ++++++++++++----
.../bundles/preview/pages/styles.module.css | 22 ++++++++++++++++---
2 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/frontend/src/bundles/preview/pages/preview.tsx b/frontend/src/bundles/preview/pages/preview.tsx
index 8e0ca76e5..33181410c 100644
--- a/frontend/src/bundles/preview/pages/preview.tsx
+++ b/frontend/src/bundles/preview/pages/preview.tsx
@@ -1,5 +1,8 @@
-import { Box, Header, Loader, VideoPlayer } from '~/bundles/common/components/components.js';
-import { useAppDispatch, useEffect, useState } from '~/bundles/common/hooks/hooks.js';
+import { useNavigate } from 'react-router-dom';
+
+import { Box, Button,Header, Loader, VideoPlayer, } from '~/bundles/common/components/components.js';
+import { AppRoute } from '~/bundles/common/enums/enums.js';
+import { useAppDispatch, useCallback,useEffect, useState } from '~/bundles/common/hooks/hooks.js';
import { getUrl } from '../store/actions.js';
import styles from './styles.module.css';
@@ -27,19 +30,27 @@ const Preview: React.FC = ({ jwt }) => {
fetchUrl().catch(error => {throw new Error(error); });
}, [dispatch, jwt]);
+ const navigate = useNavigate();
+
+ const handleClick = useCallback(() => {
+ navigate(AppRoute.ROOT);
+ }, [navigate]);
+
if (loading) {
- return ;
+ return ;
}
return (
-
+ }/>
+
+
);
};
diff --git a/frontend/src/bundles/preview/pages/styles.module.css b/frontend/src/bundles/preview/pages/styles.module.css
index 7317d0311..420dc5bd5 100644
--- a/frontend/src/bundles/preview/pages/styles.module.css
+++ b/frontend/src/bundles/preview/pages/styles.module.css
@@ -1,6 +1,22 @@
.video-player {
- height: 1000px;
- width: 1000px;
+ height:50vh;
+ width: 90vh;
position: relative;
- background-color: var(--chakra-colors-gray-200);
+ background-color: var(--chakra-colors-background-600);
}
+.loader-box {
+ background-color: var(--chakra-colors-background-900);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+}
+.back-box {
+ background-color: var(--chakra-colors-background-600);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ position: relative;
+ z-index: 0;
+}
\ No newline at end of file
From 423cabcb1da86e101255284afd7f79265a45c4c8 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Wed, 25 Sep 2024 09:24:22 -0500
Subject: [PATCH 09/20] OV-377: * prettier
---
.../public-video/public-video.controller.ts | 8 +--
.../public-video/public-video.service.ts | 4 +-
.../src/bundles/videos/video.controller.ts | 2 +-
backend/src/bundles/videos/video.service.ts | 2 +-
.../server-application/server-application.ts | 1 -
.../common/services/token/token.services.ts | 2 +-
frontend/src/bundles/common/api/api.ts | 2 +-
.../api/public-video-api/public-videos-api.ts | 9 ++--
.../common/api/video-api/videos-api.ts | 25 +++++-----
.../home/components/video-card/video-card.tsx | 9 ++--
.../bundles/home/helpers/create-url-token.ts | 3 +-
frontend/src/bundles/home/helpers/helpers.ts | 2 +-
frontend/src/bundles/home/store/home.ts | 2 +-
.../preview/components/preview-wrapper.tsx | 2 +-
.../src/bundles/preview/pages/preview.tsx | 49 ++++++++++++++-----
.../bundles/preview/pages/styles.module.css | 4 +-
.../http-api/base-http-api.package.ts | 2 +-
frontend/src/routes/routes.tsx | 6 +--
18 files changed, 80 insertions(+), 54 deletions(-)
diff --git a/backend/src/bundles/public-video/public-video.controller.ts b/backend/src/bundles/public-video/public-video.controller.ts
index 7c813113f..8c60f4271 100644
--- a/backend/src/bundles/public-video/public-video.controller.ts
+++ b/backend/src/bundles/public-video/public-video.controller.ts
@@ -24,7 +24,7 @@ class PublicVideoController extends BaseController {
handler: (options) => this.findUrlByToken(options),
});
}
-
+
private async findUrlByToken(
options: ApiHandlerOptions,
): Promise {
@@ -33,9 +33,11 @@ class PublicVideoController extends BaseController {
return {
status: HTTPCode.OK,
- payload: await this.publicVideoService.findUrlByToken(videoTokenHeader ?? ''),
+ payload: await this.publicVideoService.findUrlByToken(
+ videoTokenHeader ?? '',
+ ),
};
}
-}
+}
export { PublicVideoController };
diff --git a/backend/src/bundles/public-video/public-video.service.ts b/backend/src/bundles/public-video/public-video.service.ts
index f95cccd1d..8b57a7740 100644
--- a/backend/src/bundles/public-video/public-video.service.ts
+++ b/backend/src/bundles/public-video/public-video.service.ts
@@ -6,9 +6,7 @@ import { VideoValidationMessage } from './enums/enums.js';
class PublicVideoService {
private videoRepository: VideoRepository;
- public constructor(
- videoRepository: VideoRepository,
- ) {
+ public constructor(videoRepository: VideoRepository) {
this.videoRepository = videoRepository;
}
diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts
index 0aaa10dd5..5e89f2374 100644
--- a/backend/src/bundles/videos/video.controller.ts
+++ b/backend/src/bundles/videos/video.controller.ts
@@ -197,7 +197,7 @@ class VideoController extends BaseController {
};
}
- /**
+ /**
* @swagger
* /videos/{id}/share:
* get:
diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts
index 8b17eeab6..6fec6a96a 100644
--- a/backend/src/bundles/videos/video.service.ts
+++ b/backend/src/bundles/videos/video.service.ts
@@ -102,7 +102,7 @@ class VideoService implements Service {
}
public async getVideoIdToken(id: string): Promise {
- return await tokenService.createVideoIdToken(id);
+ return await tokenService.createVideoIdToken(id);
}
}
diff --git a/backend/src/common/server-application/server-application.ts b/backend/src/common/server-application/server-application.ts
index 67e8701fd..ea5f73ecf 100644
--- a/backend/src/common/server-application/server-application.ts
+++ b/backend/src/common/server-application/server-application.ts
@@ -26,7 +26,6 @@ const apiV1 = new BaseServerAppApi(
...speechController.routes,
...avatarVideoController.routes,
...publicVideoController.routes,
-
);
const serverApp = new BaseServerApp({
diff --git a/backend/src/common/services/token/token.services.ts b/backend/src/common/services/token/token.services.ts
index cd06b720a..f1f6c85ba 100644
--- a/backend/src/common/services/token/token.services.ts
+++ b/backend/src/common/services/token/token.services.ts
@@ -18,7 +18,7 @@ class TokenService {
}
public async createVideoIdToken(videoId: string): Promise {
- const jwt = await new SignJWT({ videoId })
+ const jwt = await new SignJWT({ videoId })
.setProtectedHeader({ alg: 'HS256' })
.sign(this.secretKey);
return jwt.replaceAll('.', '~');
diff --git a/frontend/src/bundles/common/api/api.ts b/frontend/src/bundles/common/api/api.ts
index 2a2663498..70fd2a12c 100644
--- a/frontend/src/bundles/common/api/api.ts
+++ b/frontend/src/bundles/common/api/api.ts
@@ -17,4 +17,4 @@ const publicVideosApi = new PublicVideosApi({
http,
});
-export { publicVideosApi,videosApi };
+export { publicVideosApi, videosApi };
diff --git a/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts b/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
index 6793bdffb..096bfb43d 100644
--- a/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
+++ b/frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
@@ -17,7 +17,6 @@ class PublicVideosApi extends BaseHttpApi {
}
public async getVideoUrlFromJWT(jwt: string): Promise {
-
const headers = new Headers();
headers.append('video_token', jwt.replaceAll('~', '.'));
@@ -34,10 +33,12 @@ class PublicVideosApi extends BaseHttpApi {
);
if (!response.ok) {
- throw new Error(`Failed to get video ID JWT: ${response.statusText}`);
- }
+ throw new Error(
+ `Failed to get video ID JWT: ${response.statusText}`,
+ );
+ }
return await response.text();
-}
+ }
}
export { PublicVideosApi };
diff --git a/frontend/src/bundles/common/api/video-api/videos-api.ts b/frontend/src/bundles/common/api/video-api/videos-api.ts
index 74d7f8892..491ae298c 100644
--- a/frontend/src/bundles/common/api/video-api/videos-api.ts
+++ b/frontend/src/bundles/common/api/video-api/videos-api.ts
@@ -99,20 +99,21 @@ class VideosApi extends BaseHttpApi {
}
public async getVideoIdJWT(id: string): Promise {
+ const response = await this.load(
+ this.getFullEndpoint(`${VideosApiPath.ROOT}${id}/share`, {}),
+ {
+ method: HTTPMethod.GET,
+ contentType: ContentType.JSON,
+ hasAuth: true,
+ },
+ );
- const response = await this.load(
- this.getFullEndpoint(`${VideosApiPath.ROOT}${id}/share`, {}),
- {
- method: HTTPMethod.GET,
- contentType: ContentType.JSON,
- hasAuth: true,
- },
+ if (!response.ok) {
+ throw new Error(
+ `Failed to get video ID JWT: ${response.statusText}`,
);
-
- if (!response.ok) {
- throw new Error(`Failed to get video ID JWT: ${response.statusText}`);
- }
- return await response.text();
+ }
+ return await response.text();
}
}
diff --git a/frontend/src/bundles/home/components/video-card/video-card.tsx b/frontend/src/bundles/home/components/video-card/video-card.tsx
index 41a094e88..5558dfb63 100644
--- a/frontend/src/bundles/home/components/video-card/video-card.tsx
+++ b/frontend/src/bundles/home/components/video-card/video-card.tsx
@@ -103,14 +103,17 @@ const VideoCard: React.FC = ({
const token = await jwt;
const url = createVideoUrl(token);
await navigator.clipboard.writeText(url);
- notificationService.success({ message: 'Url copied to clipboard', id : 'url-copied', title : 'Success' });
+ notificationService.success({
+ message: 'Url copied to clipboard',
+ id: 'url-copied',
+ title: 'Success',
+ });
})
.catch((error) => {
throw new Error(`Failed to get video ID JWT: ${error}`);
});
-
}, [dispatch, id]);
-
+
return (
{
const baseUrl = 'http://localhost:3000';
return `${baseUrl}/preview/${jwtToken}`;
};
-export { createVideoUrl };
\ No newline at end of file
+export { createVideoUrl };
diff --git a/frontend/src/bundles/home/helpers/helpers.ts b/frontend/src/bundles/home/helpers/helpers.ts
index 51239f491..2a9c6a4b1 100644
--- a/frontend/src/bundles/home/helpers/helpers.ts
+++ b/frontend/src/bundles/home/helpers/helpers.ts
@@ -1 +1 @@
-export { createVideoUrl } from './create-url-token.js';
\ No newline at end of file
+export { createVideoUrl } from './create-url-token.js';
diff --git a/frontend/src/bundles/home/store/home.ts b/frontend/src/bundles/home/store/home.ts
index f97fc0dbb..f682b3b1d 100644
--- a/frontend/src/bundles/home/store/home.ts
+++ b/frontend/src/bundles/home/store/home.ts
@@ -1,4 +1,4 @@
-import { deleteVideo, getJwt, loadUserVideos, } from './actions.js';
+import { deleteVideo, getJwt, loadUserVideos } from './actions.js';
import { actions } from './slice.js';
const allActions = {
diff --git a/frontend/src/bundles/preview/components/preview-wrapper.tsx b/frontend/src/bundles/preview/components/preview-wrapper.tsx
index 4d70848f8..bfa744f70 100644
--- a/frontend/src/bundles/preview/components/preview-wrapper.tsx
+++ b/frontend/src/bundles/preview/components/preview-wrapper.tsx
@@ -7,4 +7,4 @@ const PreviewWrapper: React.FC = () => {
return ;
};
-export { PreviewWrapper };
\ No newline at end of file
+export { PreviewWrapper };
diff --git a/frontend/src/bundles/preview/pages/preview.tsx b/frontend/src/bundles/preview/pages/preview.tsx
index 33181410c..83f39d489 100644
--- a/frontend/src/bundles/preview/pages/preview.tsx
+++ b/frontend/src/bundles/preview/pages/preview.tsx
@@ -1,8 +1,19 @@
import { useNavigate } from 'react-router-dom';
-import { Box, Button,Header, Loader, VideoPlayer, } from '~/bundles/common/components/components.js';
+import {
+ Box,
+ Button,
+ Header,
+ Loader,
+ VideoPlayer,
+} from '~/bundles/common/components/components.js';
import { AppRoute } from '~/bundles/common/enums/enums.js';
-import { useAppDispatch, useCallback,useEffect, useState } from '~/bundles/common/hooks/hooks.js';
+import {
+ useAppDispatch,
+ useCallback,
+ useEffect,
+ useState,
+} from '~/bundles/common/hooks/hooks.js';
import { getUrl } from '../store/actions.js';
import styles from './styles.module.css';
@@ -27,7 +38,9 @@ const Preview: React.FC = ({ jwt }) => {
}
};
- fetchUrl().catch(error => {throw new Error(error); });
+ fetchUrl().catch((error) => {
+ throw new Error(error);
+ });
}, [dispatch, jwt]);
const navigate = useNavigate();
@@ -37,22 +50,34 @@ const Preview: React.FC = ({ jwt }) => {
}, [navigate]);
if (loading) {
- return ;
+ return (
+
+
+
+ );
}
return (
- }/>
-
-
+ }
/>
+
+
);
};
-export { Preview };
\ No newline at end of file
+export { Preview };
diff --git a/frontend/src/bundles/preview/pages/styles.module.css b/frontend/src/bundles/preview/pages/styles.module.css
index 420dc5bd5..21d73a329 100644
--- a/frontend/src/bundles/preview/pages/styles.module.css
+++ b/frontend/src/bundles/preview/pages/styles.module.css
@@ -1,5 +1,5 @@
.video-player {
- height:50vh;
+ height: 50vh;
width: 90vh;
position: relative;
background-color: var(--chakra-colors-background-600);
@@ -19,4 +19,4 @@
height: 100vh;
position: relative;
z-index: 0;
-}
\ No newline at end of file
+}
diff --git a/frontend/src/framework/http-api/base-http-api.package.ts b/frontend/src/framework/http-api/base-http-api.package.ts
index 90d86c912..f64d71e5d 100644
--- a/frontend/src/framework/http-api/base-http-api.package.ts
+++ b/frontend/src/framework/http-api/base-http-api.package.ts
@@ -53,7 +53,7 @@ class BaseHttpApi implements HttpApi {
keepAlive = false,
customHeaders,
} = options;
-
+
const headers = await this.getHeaders(contentType, hasAuth);
if (customHeaders) {
for (const [key, value] of customHeaders) {
diff --git a/frontend/src/routes/routes.tsx b/frontend/src/routes/routes.tsx
index 08e6cdf6c..1a527e48d 100644
--- a/frontend/src/routes/routes.tsx
+++ b/frontend/src/routes/routes.tsx
@@ -60,10 +60,8 @@ const routes = [
},
{
path: `${AppRoute.PREVIEW}/:jwt`,
- element: (
-
- ),
- }
+ element: ,
+ },
],
},
];
From 5c7e932f7a20c678948a9886582db054f2de8eb8 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 08:19:57 -0500
Subject: [PATCH 10/20] OV-377: * Refactor token service to use a unified
method for creating and decoding tokens
---
.../public-video/public-video.service.ts | 2 +-
backend/src/bundles/videos/video.service.ts | 3 +-
.../common/plugins/auth/auth-jwt.plugin.ts | 2 +-
.../common/services/token/token.services.ts | 30 ++++++++-----------
.../src/bundles/preview/pages/preview.tsx | 6 ++--
5 files changed, 19 insertions(+), 24 deletions(-)
diff --git a/backend/src/bundles/public-video/public-video.service.ts b/backend/src/bundles/public-video/public-video.service.ts
index 8b57a7740..91b73c42c 100644
--- a/backend/src/bundles/public-video/public-video.service.ts
+++ b/backend/src/bundles/public-video/public-video.service.ts
@@ -11,7 +11,7 @@ class PublicVideoService {
}
public async findUrlByToken(token: string): Promise {
- const id = await tokenService.getVideoIdFromToken(token);
+ const id = await tokenService.getIdFromToken(token);
if (!id) {
this.throwVideoNotFoundError();
diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts
index 6fec6a96a..e4e457508 100644
--- a/backend/src/bundles/videos/video.service.ts
+++ b/backend/src/bundles/videos/video.service.ts
@@ -102,7 +102,8 @@ class VideoService implements Service {
}
public async getVideoIdToken(id: string): Promise {
- return await tokenService.createVideoIdToken(id);
+ const token = await tokenService.createToken(id, false);
+ return token.replaceAll('.', '~');
}
}
diff --git a/backend/src/common/plugins/auth/auth-jwt.plugin.ts b/backend/src/common/plugins/auth/auth-jwt.plugin.ts
index f5d41bc6d..01e7cc3bc 100644
--- a/backend/src/common/plugins/auth/auth-jwt.plugin.ts
+++ b/backend/src/common/plugins/auth/auth-jwt.plugin.ts
@@ -31,7 +31,7 @@ const authenticateJWT = fp((fastify, { routesWhiteList }, done) => {
const [, token] = authHeader.split(' ');
- const userId = await tokenService.getUserIdFromToken(token as string);
+ const userId = await tokenService.getIdFromToken(token as string);
if (!userId) {
throw new HttpError({
diff --git a/backend/src/common/services/token/token.services.ts b/backend/src/common/services/token/token.services.ts
index f1f6c85ba..fe69dc4ce 100644
--- a/backend/src/common/services/token/token.services.ts
+++ b/backend/src/common/services/token/token.services.ts
@@ -10,18 +10,17 @@ class TokenService {
this.expirationTime = expirationTime;
}
- public async createToken(userId: string): Promise {
- return await new SignJWT({ userId })
- .setProtectedHeader({ alg: 'HS256' })
- .setExpirationTime(this.expirationTime)
- .sign(this.secretKey);
- }
+ public async createToken(
+ id: string,
+ expires: boolean = true,
+ ): Promise {
+ const jwt = new SignJWT({ id }).setProtectedHeader({ alg: 'HS256' });
+
+ if (expires) {
+ jwt.setExpirationTime(this.expirationTime);
+ }
- public async createVideoIdToken(videoId: string): Promise {
- const jwt = await new SignJWT({ videoId })
- .setProtectedHeader({ alg: 'HS256' })
- .sign(this.secretKey);
- return jwt.replaceAll('.', '~');
+ return await jwt.sign(this.secretKey);
}
public async verifyToken(token: string): Promise {
@@ -33,14 +32,9 @@ class TokenService {
}
}
- public async getUserIdFromToken(token: string): Promise {
- const payload = await this.verifyToken(token);
- return (payload?.['userId'] as string) || null;
- }
-
- public async getVideoIdFromToken(token: string): Promise {
+ public async getIdFromToken(token: string): Promise {
const payload = await this.verifyToken(token);
- return (payload?.['videoId'] as string) || null;
+ return (payload?.['id'] as string) ?? null;
}
}
diff --git a/frontend/src/bundles/preview/pages/preview.tsx b/frontend/src/bundles/preview/pages/preview.tsx
index 83f39d489..afad3b54a 100644
--- a/frontend/src/bundles/preview/pages/preview.tsx
+++ b/frontend/src/bundles/preview/pages/preview.tsx
@@ -25,7 +25,7 @@ type Properties = {
const Preview: React.FC = ({ jwt }) => {
const dispatch = useAppDispatch();
const [url, setUrl] = useState('');
- const [loading, setLoading] = useState(true);
+ const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchUrl = async (): Promise => {
@@ -34,7 +34,7 @@ const Preview: React.FC = ({ jwt }) => {
setUrl(result);
} finally {
- setLoading(false);
+ setIsLoading(false);
}
};
@@ -49,7 +49,7 @@ const Preview: React.FC = ({ jwt }) => {
navigate(AppRoute.ROOT);
}, [navigate]);
- if (loading) {
+ if (isLoading) {
return (
From 480e38f75dd1450008aa0754be904c08f5733ab3 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 08:40:45 -0500
Subject: [PATCH 11/20] OV-377: + added dynamically created sharing URL
---
frontend/src/bundles/home/helpers/create-url-token.ts | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/frontend/src/bundles/home/helpers/create-url-token.ts b/frontend/src/bundles/home/helpers/create-url-token.ts
index 9f617e0a6..b9b5bd0bb 100644
--- a/frontend/src/bundles/home/helpers/create-url-token.ts
+++ b/frontend/src/bundles/home/helpers/create-url-token.ts
@@ -1,5 +1,9 @@
const createVideoUrl = (jwtToken: string): string => {
- const baseUrl = 'http://localhost:3000';
+ const baseUrl =
+ import.meta.env['VITE_APP_NODE_ENV'] === 'production'
+ ? 'http://bsa-2024-outreachvids-dev.eu-north-1.elasticbeanstalk.com/'
+ : 'http://localhost:3000';
+
return `${baseUrl}/preview/${jwtToken}`;
};
From 556ed1d693149729abb2f8511bbc251a20bff0ac Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 09:01:15 -0500
Subject: [PATCH 12/20] OV-377: - use config to create video url
---
frontend/src/bundles/home/helpers/create-url-token.ts | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/frontend/src/bundles/home/helpers/create-url-token.ts b/frontend/src/bundles/home/helpers/create-url-token.ts
index b9b5bd0bb..a39c76c60 100644
--- a/frontend/src/bundles/home/helpers/create-url-token.ts
+++ b/frontend/src/bundles/home/helpers/create-url-token.ts
@@ -1,7 +1,10 @@
+import { AppEnvironment } from '~/bundles/common/enums/enums.js';
+import { config } from '~/framework/config/config.js';
+
const createVideoUrl = (jwtToken: string): string => {
const baseUrl =
- import.meta.env['VITE_APP_NODE_ENV'] === 'production'
- ? 'http://bsa-2024-outreachvids-dev.eu-north-1.elasticbeanstalk.com/'
+ config.ENV.APP.ENVIRONMENT === AppEnvironment.PRODUCTION
+ ? 'http://bsa-2024-outreachvids-dev.eu-north-1.elasticbeanstalk.com'
: 'http://localhost:3000';
return `${baseUrl}/preview/${jwtToken}`;
From c2ebd64ed00905a4e8a9dc26422bbd4cae2bc2e8 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 09:16:06 -0500
Subject: [PATCH 13/20] Merge branch 'next' into
task/OV-377-create-preview-page
From 32b55b7c413640c36b6442193516259f6d42d92d Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 10:09:43 -0500
Subject: [PATCH 14/20] OV-377: + create env variable for deployment URL andfix
magic numbers
---
backend/src/bundles/public-video/public-video.controller.ts | 2 +-
backend/src/bundles/public-video/public-video.service.ts | 2 +-
backend/src/bundles/videos/video.controller.ts | 2 +-
frontend/.env.example | 6 ++++++
frontend/src/bundles/common/api/video-api/videos-api.ts | 2 +-
frontend/src/bundles/home/helpers/create-url-token.ts | 2 +-
frontend/src/framework/config/base-config.package.ts | 3 +++
.../src/framework/config/types/environment-schema.type.ts | 3 +++
8 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/backend/src/bundles/public-video/public-video.controller.ts b/backend/src/bundles/public-video/public-video.controller.ts
index 8c60f4271..b9ae03978 100644
--- a/backend/src/bundles/public-video/public-video.controller.ts
+++ b/backend/src/bundles/public-video/public-video.controller.ts
@@ -34,7 +34,7 @@ class PublicVideoController extends BaseController {
return {
status: HTTPCode.OK,
payload: await this.publicVideoService.findUrlByToken(
- videoTokenHeader ?? '',
+ videoTokenHeader,
),
};
}
diff --git a/backend/src/bundles/public-video/public-video.service.ts b/backend/src/bundles/public-video/public-video.service.ts
index 91b73c42c..018cd2006 100644
--- a/backend/src/bundles/public-video/public-video.service.ts
+++ b/backend/src/bundles/public-video/public-video.service.ts
@@ -23,7 +23,7 @@ class PublicVideoService {
this.throwVideoNotFoundError();
}
- const url = video.toObject().url;
+ const { url } = video.toObject();
if (!url) {
this.throwVideoNotFoundError();
}
diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts
index 5e89f2374..45ce5db2f 100644
--- a/backend/src/bundles/videos/video.controller.ts
+++ b/backend/src/bundles/videos/video.controller.ts
@@ -110,7 +110,7 @@ class VideoController extends BaseController {
),
});
this.addRoute({
- path: `${VideosApiPath.ID}/share`,
+ path: `${VideosApiPath.ID}${VideosApiPath.SHARE}`,
method: HTTPMethod.GET,
handler: (options) => {
return this.createVideoIdJWT(
diff --git a/frontend/.env.example b/frontend/.env.example
index 9d1ec0623..6092178be 100644
--- a/frontend/.env.example
+++ b/frontend/.env.example
@@ -10,3 +10,9 @@ VITE_APP_API_ORIGIN_URL=/api/v1
#
VITE_APP_PROXY_SERVER_URL=http://localhost:3001
VITE_APP_SOCKET_ORIGIN_URL=/socket.io
+
+#
+# DEPLOYMENT
+#
+DEPLOYMENT_URL=http://bsa-2024-outreachvids-dev.eu-north-1.elasticbeanstalk.com
+
diff --git a/frontend/src/bundles/common/api/video-api/videos-api.ts b/frontend/src/bundles/common/api/video-api/videos-api.ts
index 491ae298c..f40e8ed34 100644
--- a/frontend/src/bundles/common/api/video-api/videos-api.ts
+++ b/frontend/src/bundles/common/api/video-api/videos-api.ts
@@ -100,7 +100,7 @@ class VideosApi extends BaseHttpApi {
public async getVideoIdJWT(id: string): Promise {
const response = await this.load(
- this.getFullEndpoint(`${VideosApiPath.ROOT}${id}/share`, {}),
+ this.getFullEndpoint(`${VideosApiPath.ROOT}${id}${VideosApiPath.SHARE}`, {}),
{
method: HTTPMethod.GET,
contentType: ContentType.JSON,
diff --git a/frontend/src/bundles/home/helpers/create-url-token.ts b/frontend/src/bundles/home/helpers/create-url-token.ts
index a39c76c60..0a7eb46c1 100644
--- a/frontend/src/bundles/home/helpers/create-url-token.ts
+++ b/frontend/src/bundles/home/helpers/create-url-token.ts
@@ -4,7 +4,7 @@ import { config } from '~/framework/config/config.js';
const createVideoUrl = (jwtToken: string): string => {
const baseUrl =
config.ENV.APP.ENVIRONMENT === AppEnvironment.PRODUCTION
- ? 'http://bsa-2024-outreachvids-dev.eu-north-1.elasticbeanstalk.com'
+ ? config.ENV.DEPLOYMENT.URL
: 'http://localhost:3000';
return `${baseUrl}/preview/${jwtToken}`;
diff --git a/frontend/src/framework/config/base-config.package.ts b/frontend/src/framework/config/base-config.package.ts
index f58044b4b..8c16f79f0 100644
--- a/frontend/src/framework/config/base-config.package.ts
+++ b/frontend/src/framework/config/base-config.package.ts
@@ -20,6 +20,9 @@ class BaseConfig implements Config {
'VITE_APP_SOCKET_ORIGIN_URL'
] as string,
},
+ DEPLOYMENT: {
+ URL: import.meta.env['DEPLOYMENT_URL'] as string,
+ },
};
}
}
diff --git a/frontend/src/framework/config/types/environment-schema.type.ts b/frontend/src/framework/config/types/environment-schema.type.ts
index 92adb2fd0..ac7921fe5 100644
--- a/frontend/src/framework/config/types/environment-schema.type.ts
+++ b/frontend/src/framework/config/types/environment-schema.type.ts
@@ -9,6 +9,9 @@ type EnvironmentSchema = {
ORIGIN_URL: string;
SOCKET_ORIGIN_URL: string;
};
+ DEPLOYMENT: {
+ URL: string;
+ };
};
export { type EnvironmentSchema };
From 7d1c53602e8a22d7b514a99a36634fc5b3a19a6e Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 10:12:24 -0500
Subject: [PATCH 15/20] OV-377: * prettier
---
backend/src/bundles/public-video/public-video.controller.ts | 5 ++---
frontend/src/bundles/common/api/video-api/videos-api.ts | 5 ++++-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/backend/src/bundles/public-video/public-video.controller.ts b/backend/src/bundles/public-video/public-video.controller.ts
index b9ae03978..f864f9128 100644
--- a/backend/src/bundles/public-video/public-video.controller.ts
+++ b/backend/src/bundles/public-video/public-video.controller.ts
@@ -33,9 +33,8 @@ class PublicVideoController extends BaseController {
return {
status: HTTPCode.OK,
- payload: await this.publicVideoService.findUrlByToken(
- videoTokenHeader,
- ),
+ payload:
+ await this.publicVideoService.findUrlByToken(videoTokenHeader),
};
}
}
diff --git a/frontend/src/bundles/common/api/video-api/videos-api.ts b/frontend/src/bundles/common/api/video-api/videos-api.ts
index f40e8ed34..22238dec9 100644
--- a/frontend/src/bundles/common/api/video-api/videos-api.ts
+++ b/frontend/src/bundles/common/api/video-api/videos-api.ts
@@ -100,7 +100,10 @@ class VideosApi extends BaseHttpApi {
public async getVideoIdJWT(id: string): Promise {
const response = await this.load(
- this.getFullEndpoint(`${VideosApiPath.ROOT}${id}${VideosApiPath.SHARE}`, {}),
+ this.getFullEndpoint(
+ `${VideosApiPath.ROOT}${id}${VideosApiPath.SHARE}`,
+ {},
+ ),
{
method: HTTPMethod.GET,
contentType: ContentType.JSON,
From 3ae5db17874f62ce361e00d87ddf601e8641824d Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 14:01:20 -0500
Subject: [PATCH 16/20] OV-377: * changed baseurl to access env PUBLIC_URL
---
frontend/src/bundles/home/helpers/create-url-token.ts | 6 +-----
frontend/src/framework/config/base-config.package.ts | 2 +-
.../src/framework/config/types/environment-schema.type.ts | 2 +-
frontend/vite.config.ts | 1 +
4 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/frontend/src/bundles/home/helpers/create-url-token.ts b/frontend/src/bundles/home/helpers/create-url-token.ts
index 0a7eb46c1..fc31d5e07 100644
--- a/frontend/src/bundles/home/helpers/create-url-token.ts
+++ b/frontend/src/bundles/home/helpers/create-url-token.ts
@@ -1,11 +1,7 @@
-import { AppEnvironment } from '~/bundles/common/enums/enums.js';
import { config } from '~/framework/config/config.js';
const createVideoUrl = (jwtToken: string): string => {
- const baseUrl =
- config.ENV.APP.ENVIRONMENT === AppEnvironment.PRODUCTION
- ? config.ENV.DEPLOYMENT.URL
- : 'http://localhost:3000';
+ const baseUrl = config.ENV.DEPLOYMENT.PUBLIC_URL;
return `${baseUrl}/preview/${jwtToken}`;
};
diff --git a/frontend/src/framework/config/base-config.package.ts b/frontend/src/framework/config/base-config.package.ts
index 8c16f79f0..56ba31483 100644
--- a/frontend/src/framework/config/base-config.package.ts
+++ b/frontend/src/framework/config/base-config.package.ts
@@ -21,7 +21,7 @@ class BaseConfig implements Config {
] as string,
},
DEPLOYMENT: {
- URL: import.meta.env['DEPLOYMENT_URL'] as string,
+ PUBLIC_URL: import.meta.env['PUBLIC_URL'] as string,
},
};
}
diff --git a/frontend/src/framework/config/types/environment-schema.type.ts b/frontend/src/framework/config/types/environment-schema.type.ts
index ac7921fe5..cdbe7675a 100644
--- a/frontend/src/framework/config/types/environment-schema.type.ts
+++ b/frontend/src/framework/config/types/environment-schema.type.ts
@@ -10,7 +10,7 @@ type EnvironmentSchema = {
SOCKET_ORIGIN_URL: string;
};
DEPLOYMENT: {
- URL: string;
+ PUBLIC_URL: string;
};
};
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index bfd716c3f..1c1f488b7 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -10,6 +10,7 @@ const config = ({ mode }: ConfigEnv): ReturnType => {
VITE_APP_API_ORIGIN_URL,
VITE_APP_PROXY_SERVER_URL,
VITE_APP_SOCKET_ORIGIN_URL,
+
} = loadEnv(mode, process.cwd());
return defineConfig({
From d932a5a36789ee4d3e4fdb4e2d0b891fa0276ecd Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 14:02:40 -0500
Subject: [PATCH 17/20] OV-377: * changed baseurl to access env PUBLIC_URL
---
frontend/.env.example | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/.env.example b/frontend/.env.example
index 6092178be..d79b56559 100644
--- a/frontend/.env.example
+++ b/frontend/.env.example
@@ -14,5 +14,5 @@ VITE_APP_SOCKET_ORIGIN_URL=/socket.io
#
# DEPLOYMENT
#
-DEPLOYMENT_URL=http://bsa-2024-outreachvids-dev.eu-north-1.elasticbeanstalk.com
+PUBLIC_URL=http://bsa-2024-outreachvids-dev.eu-north-1.elasticbeanstalk.com
From 89fd45db291b2b2f213302b8f60ac1511da2b154 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Thu, 26 Sep 2024 14:04:45 -0500
Subject: [PATCH 18/20] OV-377: * prettier
---
frontend/vite.config.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 1c1f488b7..bfd716c3f 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -10,7 +10,6 @@ const config = ({ mode }: ConfigEnv): ReturnType => {
VITE_APP_API_ORIGIN_URL,
VITE_APP_PROXY_SERVER_URL,
VITE_APP_SOCKET_ORIGIN_URL,
-
} = loadEnv(mode, process.cwd());
return defineConfig({
From b8e9f782ff5b8d5570d50e9f3b95c5d3416990b7 Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Fri, 27 Sep 2024 04:29:24 -0500
Subject: [PATCH 19/20] OV-377: - prettier
---
frontend/src/bundles/home/store/actions.ts | 8 +++++++-
frontend/src/bundles/home/store/home.ts | 5 +++--
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/frontend/src/bundles/home/store/actions.ts b/frontend/src/bundles/home/store/actions.ts
index 19a7e5e29..be65b7615 100644
--- a/frontend/src/bundles/home/store/actions.ts
+++ b/frontend/src/bundles/home/store/actions.ts
@@ -57,4 +57,10 @@ const generateScriptSpeechPreview = createAsyncThunk<
return speechApi.generateScriptSpeech(payload);
});
-export { deleteVideo, generateScriptSpeechPreview, getJwt, loadUserVideos, loadVoices };
+export {
+ deleteVideo,
+ generateScriptSpeechPreview,
+ getJwt,
+ loadUserVideos,
+ loadVoices,
+};
diff --git a/frontend/src/bundles/home/store/home.ts b/frontend/src/bundles/home/store/home.ts
index acf10b4cd..d6e5c96e2 100644
--- a/frontend/src/bundles/home/store/home.ts
+++ b/frontend/src/bundles/home/store/home.ts
@@ -1,6 +1,7 @@
import {
- deleteVideo, generateScriptSpeechPreview,
-getJwt,
+ deleteVideo,
+ generateScriptSpeechPreview,
+ getJwt,
loadUserVideos,
} from './actions.js';
import { actions } from './slice.js';
From 34e108446e16819e0bcc15e43729fa7175d4ba7b Mon Sep 17 00:00:00 2001
From: stefano-lacorazza <112132737+stefano-lacorazza@users.noreply.github.com>
Date: Fri, 27 Sep 2024 04:57:51 -0500
Subject: [PATCH 20/20] OV-377: * change .env variable
---
frontend/.env.example | 2 +-
frontend/src/bundles/home/helpers/create-url-token.ts | 1 -
frontend/src/framework/config/base-config.package.ts | 2 +-
3 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/frontend/.env.example b/frontend/.env.example
index d79b56559..2303ec6c4 100644
--- a/frontend/.env.example
+++ b/frontend/.env.example
@@ -14,5 +14,5 @@ VITE_APP_SOCKET_ORIGIN_URL=/socket.io
#
# DEPLOYMENT
#
-PUBLIC_URL=http://bsa-2024-outreachvids-dev.eu-north-1.elasticbeanstalk.com
+VITE_APP_PUBLIC_URL=http://localhost:3000
diff --git a/frontend/src/bundles/home/helpers/create-url-token.ts b/frontend/src/bundles/home/helpers/create-url-token.ts
index fc31d5e07..a4d778936 100644
--- a/frontend/src/bundles/home/helpers/create-url-token.ts
+++ b/frontend/src/bundles/home/helpers/create-url-token.ts
@@ -2,7 +2,6 @@ import { config } from '~/framework/config/config.js';
const createVideoUrl = (jwtToken: string): string => {
const baseUrl = config.ENV.DEPLOYMENT.PUBLIC_URL;
-
return `${baseUrl}/preview/${jwtToken}`;
};
diff --git a/frontend/src/framework/config/base-config.package.ts b/frontend/src/framework/config/base-config.package.ts
index 56ba31483..a4a408ea2 100644
--- a/frontend/src/framework/config/base-config.package.ts
+++ b/frontend/src/framework/config/base-config.package.ts
@@ -21,7 +21,7 @@ class BaseConfig implements Config {
] as string,
},
DEPLOYMENT: {
- PUBLIC_URL: import.meta.env['PUBLIC_URL'] as string,
+ PUBLIC_URL: import.meta.env['VITE_APP_PUBLIC_URL'] as string,
},
};
}