-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OV-377: Create preview page and flow #429
Merged
Merged
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
b868514
OV-377: + add preview page with video player
stefano-lacorazza 49af338
OV-377: + add copy url button to homepage
stefano-lacorazza 06e0c10
OV-377: + create JWT with video id and return it to frontend
stefano-lacorazza 945fac9
OV-377: + copy url to clipboard
stefano-lacorazza c19a3fa
OV-377: + create dynamic preview url
stefano-lacorazza 01bf93f
OV-377: + create public-video controller and service
stefano-lacorazza e7cc793
Merge branch 'next' into task/OV-377-create-preview-page
stefano-lacorazza 5e9044d
OV-377: + white route public-video
stefano-lacorazza ba2031e
OV-377: + style preview page
stefano-lacorazza 423cabc
OV-377: * prettier
stefano-lacorazza 5c7e932
OV-377: * Refactor token service to use a unified method for creating…
stefano-lacorazza 480e38f
OV-377: + added dynamically created sharing URL
stefano-lacorazza 556ed1d
OV-377: - use config to create video url
stefano-lacorazza 907bdaf
Merge branch 'next' into task/OV-377-create-preview-page
stefano-lacorazza c2ebd64
Merge branch 'next' into task/OV-377-create-preview-page
stefano-lacorazza 32b55b7
OV-377: + create env variable for deployment URL andfix magic numbers
stefano-lacorazza 7d1c536
OV-377: * prettier
stefano-lacorazza 3ae5db1
OV-377: * changed baseurl to access env PUBLIC_URL
stefano-lacorazza d932a5a
OV-377: * changed baseurl to access env PUBLIC_URL
stefano-lacorazza 89fd45d
OV-377: * prettier
stefano-lacorazza b012825
Merge branch 'next' into task/OV-377-create-preview-page
stefano-lacorazza b8e9f78
OV-377: - prettier
stefano-lacorazza 34e1084
OV-377: * change .env variable
stefano-lacorazza File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { VideosApiPath, VideoValidationMessage } from 'shared'; |
5 changes: 5 additions & 0 deletions
5
backend/src/bundles/public-video/enums/public-videos-api-path.enum.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const PublicVideosApiPath = { | ||
ROOT: '/', | ||
} as const; | ||
|
||
export { PublicVideosApiPath }; |
41 changes: 41 additions & 0 deletions
41
backend/src/bundles/public-video/public-video.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { type PublicVideoService } from '~/bundles/public-video/public-video.service.js'; | ||
import { | ||
type ApiHandlerOptions, | ||
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'; | ||
|
||
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, ApiPath.PUBLIC_VIDEO); | ||
|
||
this.publicVideoService = publicVideoService; | ||
|
||
this.addRoute({ | ||
path: PublicVideosApiPath.ROOT, | ||
method: HTTPMethod.GET, | ||
handler: (options) => this.findUrlByToken(options), | ||
}); | ||
} | ||
|
||
private async findUrlByToken( | ||
options: ApiHandlerOptions, | ||
): Promise<ApiHandlerResponse> { | ||
const headers = options.headers as Record<string, { value: string }>; | ||
const videoTokenHeader = headers['video_token']?.toString() ?? ''; | ||
|
||
return { | ||
status: HTTPCode.OK, | ||
payload: await this.publicVideoService.findUrlByToken(videoTokenHeader ?? ''), | ||
}; | ||
} | ||
} | ||
|
||
export { PublicVideoController }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string> { | ||
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,6 +109,17 @@ class VideoController extends BaseController { | |
}>, | ||
), | ||
}); | ||
this.addRoute({ | ||
path: `${VideosApiPath.ID}/share`, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add this path to the enum |
||
method: HTTPMethod.GET, | ||
handler: (options) => { | ||
return this.createVideoIdJWT( | ||
options as ApiHandlerOptions<{ | ||
params: VideoGetOneRequestDto; | ||
}>, | ||
); | ||
}, | ||
}); | ||
} | ||
|
||
/** | ||
|
@@ -186,6 +197,43 @@ 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; | ||
}>, | ||
): Promise<ApiHandlerResponse> { | ||
return { | ||
status: HTTPCode.OK, | ||
payload: await this.videoService.getVideoIdToken(options.params.id), | ||
}; | ||
} | ||
|
||
/** | ||
* @swagger | ||
* /videos/: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -17,6 +17,13 @@ class TokenService { | |||||
.sign(this.secretKey); | ||||||
} | ||||||
|
||||||
public async createVideoIdToken(videoId: string): Promise<string> { | ||||||
const jwt = await new SignJWT({ videoId }) | ||||||
.setProtectedHeader({ alg: 'HS256' }) | ||||||
.sign(this.secretKey); | ||||||
return jwt.replaceAll('.', '~'); | ||||||
} | ||||||
|
||||||
public async verifyToken(token: string): Promise<TokenPayload | null> { | ||||||
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<string | null> { | ||||||
const payload = await this.verifyToken(token); | ||||||
return (payload?.['videoId'] as string) || null; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
} | ||||||
|
||||||
export { TokenService }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
frontend/src/bundles/common/api/public-video-api/enums/enums.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { VideosApiPath } from 'shared'; |
43 changes: 43 additions & 0 deletions
43
frontend/src/bundles/common/api/public-video-api/public-videos-api.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string> { | ||
|
||
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(`${VideosApiPath.ROOT}`, {}), | ||
options, | ||
); | ||
|
||
if (!response.ok) { | ||
throw new Error(`Failed to get video ID JWT: ${response.statusText}`); | ||
} | ||
return await response.text(); | ||
} | ||
} | ||
|
||
export { PublicVideosApi }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.