aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-10-19 10:43:53 +0200
committerChocobozzz <chocobozzz@cpy.re>2022-10-24 14:48:24 +0200
commit9ab330b90decf4edf152ff8e1d2948c065766b2c (patch)
tree29d924f50f7307e8e828a57ecb9ea78623487ce0
parent3545e72c686ff1725bbdfd8d16d693e2f4aa75a3 (diff)
downloadPeerTube-9ab330b90decf4edf152ff8e1d2948c065766b2c.tar.gz
PeerTube-9ab330b90decf4edf152ff8e1d2948c065766b2c.tar.zst
PeerTube-9ab330b90decf4edf152ff8e1d2948c065766b2c.zip
Use private ACL for private videos in s3
-rw-r--r--.github/workflows/test.yml2
-rw-r--r--config/default.yaml7
-rw-r--r--config/production.yaml.example7
-rw-r--r--package.json6
-rw-r--r--server.ts2
-rw-r--r--server/controllers/download.ts22
-rw-r--r--server/controllers/index.ts11
-rw-r--r--server/controllers/object-storage-proxy.ts78
-rw-r--r--server/helpers/webtorrent.ts4
-rw-r--r--server/initializers/checker-after-init.ts8
-rw-r--r--server/initializers/config.ts5
-rw-r--r--server/initializers/constants.ts8
-rw-r--r--server/lib/live/live-segment-sha-store.ts27
-rw-r--r--server/lib/object-storage/shared/object-storage-helpers.ts192
-rw-r--r--server/lib/object-storage/urls.ts29
-rw-r--r--server/lib/object-storage/videos.ts80
-rw-r--r--server/lib/video-privacy.ts89
-rw-r--r--server/middlewares/validators/shared/videos.ts6
-rw-r--r--server/middlewares/validators/static.ts72
-rw-r--r--server/models/video/video-file.ts62
-rw-r--r--server/models/video/video-streaming-playlist.ts28
-rw-r--r--server/models/video/video.ts34
-rw-r--r--server/tests/api/object-storage/index.ts1
-rw-r--r--server/tests/api/object-storage/live.ts10
-rw-r--r--server/tests/api/object-storage/video-imports.ts14
-rw-r--r--server/tests/api/object-storage/video-static-file-privacy.ts336
-rw-r--r--server/tests/api/object-storage/videos.ts36
-rw-r--r--server/tests/api/server/proxy.ts14
-rw-r--r--server/tests/api/transcoding/create-transcoding.ts16
-rw-r--r--server/tests/api/transcoding/hls.ts10
-rw-r--r--server/tests/api/transcoding/update-while-transcoding.ts10
-rw-r--r--server/tests/api/transcoding/video-studio.ts12
-rw-r--r--server/tests/api/videos/video-static-file-privacy.ts14
-rw-r--r--server/tests/cli/create-import-video-file-job.ts10
-rw-r--r--server/tests/cli/create-move-video-storage-job.ts16
-rw-r--r--server/tests/cli/create-transcoding-job.ts12
-rw-r--r--server/tests/shared/live.ts6
-rw-r--r--server/tests/shared/mock-servers/mock-object-storage.ts2
-rw-r--r--server/types/express.d.ts2
-rw-r--r--shared/core-utils/common/env.ts20
-rw-r--r--shared/core-utils/videos/common.ts (renamed from shared/core-utils/videos/privacy.ts)15
-rw-r--r--shared/core-utils/videos/index.ts2
-rw-r--r--shared/server-commands/miscs/sql-command.ts5
-rw-r--r--shared/server-commands/server/object-storage-command.ts91
-rw-r--r--shared/server-commands/videos/live-command.ts6
-rw-r--r--yarn.lock1157
46 files changed, 1752 insertions, 844 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 59840d076..65e1acec6 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -46,6 +46,8 @@ jobs:
46 PGHOST: localhost 46 PGHOST: localhost
47 NODE_PENDING_JOB_WAIT: 250 47 NODE_PENDING_JOB_WAIT: 250
48 ENABLE_OBJECT_STORAGE_TESTS: true 48 ENABLE_OBJECT_STORAGE_TESTS: true
49 OBJECT_STORAGE_SCALEWAY_KEY_ID: ${{ secrets.OBJECT_STORAGE_SCALEWAY_KEY_ID }}
50 OBJECT_STORAGE_SCALEWAY_ACCESS_KEY: ${{ secrets.OBJECT_STORAGE_SCALEWAY_ACCESS_KEY }}
49 51
50 steps: 52 steps:
51 - uses: actions/checkout@v3 53 - uses: actions/checkout@v3
diff --git a/config/default.yaml b/config/default.yaml
index f94ec6209..7753821da 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -148,8 +148,11 @@ object_storage:
148 148
149 region: 'us-east-1' 149 region: 'us-east-1'
150 150
151 # Set this ACL on each uploaded object 151 upload_acl:
152 upload_acl: 'public-read' 152 # Set this ACL on each uploaded object of public/unlisted videos
153 public: 'public-read'
154 # Set this ACL on each uploaded object of private/internal videos
155 private: 'private'
153 156
154 credentials: 157 credentials:
155 # You can also use AWS_ACCESS_KEY_ID env variable 158 # You can also use AWS_ACCESS_KEY_ID env variable
diff --git a/config/production.yaml.example b/config/production.yaml.example
index 48613e1c3..167d23af8 100644
--- a/config/production.yaml.example
+++ b/config/production.yaml.example
@@ -146,8 +146,11 @@ object_storage:
146 146
147 region: 'us-east-1' 147 region: 'us-east-1'
148 148
149 # Set this ACL on each uploaded object 149 upload_acl:
150 upload_acl: 'public-read' 150 # Set this ACL on each uploaded object of public/unlisted videos
151 public: 'public-read'
152 # Set this ACL on each uploaded object of private/internal videos
153 private: 'private'
151 154
152 credentials: 155 credentials:
153 # You can also use AWS_ACCESS_KEY_ID env variable 156 # You can also use AWS_ACCESS_KEY_ID env variable
diff --git a/package.json b/package.json
index 23cd9e112..249455068 100644
--- a/package.json
+++ b/package.json
@@ -78,9 +78,9 @@
78 "jpeg-js": "0.4.4" 78 "jpeg-js": "0.4.4"
79 }, 79 },
80 "dependencies": { 80 "dependencies": {
81 "@aws-sdk/client-s3": "^3.23.0", 81 "@aws-sdk/client-s3": "^3.190.0",
82 "@aws-sdk/lib-storage": "^3.72.0", 82 "@aws-sdk/lib-storage": "^3.190.0",
83 "@aws-sdk/node-http-handler": "^3.82.0", 83 "@aws-sdk/node-http-handler": "^3.190.0",
84 "@babel/parser": "^7.17.8", 84 "@babel/parser": "^7.17.8",
85 "@node-oauth/oauth2-server": "^4.2.0", 85 "@node-oauth/oauth2-server": "^4.2.0",
86 "@opentelemetry/api": "^1.1.0", 86 "@opentelemetry/api": "^1.1.0",
diff --git a/server.ts b/server.ts
index a29b5e408..dd595e951 100644
--- a/server.ts
+++ b/server.ts
@@ -107,6 +107,7 @@ import {
107 wellKnownRouter, 107 wellKnownRouter,
108 lazyStaticRouter, 108 lazyStaticRouter,
109 servicesRouter, 109 servicesRouter,
110 objectStorageProxyRouter,
110 pluginsRouter, 111 pluginsRouter,
111 webfingerRouter, 112 webfingerRouter,
112 trackerRouter, 113 trackerRouter,
@@ -240,6 +241,7 @@ app.use('/', wellKnownRouter)
240app.use('/', miscRouter) 241app.use('/', miscRouter)
241app.use('/', downloadRouter) 242app.use('/', downloadRouter)
242app.use('/', lazyStaticRouter) 243app.use('/', lazyStaticRouter)
244app.use('/', objectStorageProxyRouter)
243 245
244// Client files, last valid routes! 246// Client files, last valid routes!
245const cliOptions = cli.opts<{ client: boolean, plugins: boolean }>() 247const cliOptions = cli.opts<{ client: boolean, plugins: boolean }>()
diff --git a/server/controllers/download.ts b/server/controllers/download.ts
index abd1df26f..d9f34109f 100644
--- a/server/controllers/download.ts
+++ b/server/controllers/download.ts
@@ -5,6 +5,7 @@ import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache
5import { Hooks } from '@server/lib/plugins/hooks' 5import { Hooks } from '@server/lib/plugins/hooks'
6import { VideoPathManager } from '@server/lib/video-path-manager' 6import { VideoPathManager } from '@server/lib/video-path-manager'
7import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' 7import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
8import { addQueryParams } from '@shared/core-utils'
8import { HttpStatusCode, VideoStorage, VideoStreamingPlaylistType } from '@shared/models' 9import { HttpStatusCode, VideoStorage, VideoStreamingPlaylistType } from '@shared/models'
9import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants' 10import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants'
10import { asyncMiddleware, optionalAuthenticate, videosDownloadValidator } from '../middlewares' 11import { asyncMiddleware, optionalAuthenticate, videosDownloadValidator } from '../middlewares'
@@ -84,7 +85,7 @@ async function downloadVideoFile (req: express.Request, res: express.Response) {
84 if (!checkAllowResult(res, allowParameters, allowedResult)) return 85 if (!checkAllowResult(res, allowParameters, allowedResult)) return
85 86
86 if (videoFile.storage === VideoStorage.OBJECT_STORAGE) { 87 if (videoFile.storage === VideoStorage.OBJECT_STORAGE) {
87 return res.redirect(videoFile.getObjectStorageUrl()) 88 return redirectToObjectStorage({ req, res, video, file: videoFile })
88 } 89 }
89 90
90 await VideoPathManager.Instance.makeAvailableVideoFile(videoFile.withVideoOrPlaylist(video), path => { 91 await VideoPathManager.Instance.makeAvailableVideoFile(videoFile.withVideoOrPlaylist(video), path => {
@@ -120,7 +121,7 @@ async function downloadHLSVideoFile (req: express.Request, res: express.Response
120 if (!checkAllowResult(res, allowParameters, allowedResult)) return 121 if (!checkAllowResult(res, allowParameters, allowedResult)) return
121 122
122 if (videoFile.storage === VideoStorage.OBJECT_STORAGE) { 123 if (videoFile.storage === VideoStorage.OBJECT_STORAGE) {
123 return res.redirect(videoFile.getObjectStorageUrl()) 124 return redirectToObjectStorage({ req, res, video, file: videoFile })
124 } 125 }
125 126
126 await VideoPathManager.Instance.makeAvailableVideoFile(videoFile.withVideoOrPlaylist(streamingPlaylist), path => { 127 await VideoPathManager.Instance.makeAvailableVideoFile(videoFile.withVideoOrPlaylist(streamingPlaylist), path => {
@@ -174,3 +175,20 @@ function checkAllowResult (res: express.Response, allowParameters: any, result?:
174 175
175 return true 176 return true
176} 177}
178
179function redirectToObjectStorage (options: {
180 req: express.Request
181 res: express.Response
182 video: MVideo
183 file: MVideoFile
184}) {
185 const { req, res, video, file } = options
186
187 const baseUrl = file.getObjectStorageUrl(video)
188
189 const url = video.hasPrivateStaticPath() && req.query.videoFileToken
190 ? addQueryParams(baseUrl, { videoFileToken: req.query.videoFileToken })
191 : baseUrl
192
193 return res.redirect(url)
194}
diff --git a/server/controllers/index.ts b/server/controllers/index.ts
index 8574a9e7b..eaa2dd7c8 100644
--- a/server/controllers/index.ts
+++ b/server/controllers/index.ts
@@ -1,14 +1,15 @@
1export * from './activitypub' 1export * from './activitypub'
2export * from './api' 2export * from './api'
3export * from './bots'
3export * from './client' 4export * from './client'
4export * from './download' 5export * from './download'
5export * from './feeds' 6export * from './feeds'
6export * from './services'
7export * from './static'
8export * from './lazy-static' 7export * from './lazy-static'
9export * from './misc' 8export * from './misc'
10export * from './webfinger' 9export * from './object-storage-proxy'
11export * from './tracker'
12export * from './bots'
13export * from './plugins' 10export * from './plugins'
11export * from './services'
12export * from './static'
13export * from './tracker'
14export * from './webfinger'
14export * from './well-known' 15export * from './well-known'
diff --git a/server/controllers/object-storage-proxy.ts b/server/controllers/object-storage-proxy.ts
new file mode 100644
index 000000000..6fedcfd8f
--- /dev/null
+++ b/server/controllers/object-storage-proxy.ts
@@ -0,0 +1,78 @@
1import cors from 'cors'
2import express from 'express'
3import { OBJECT_STORAGE_PROXY_PATHS } from '@server/initializers/constants'
4import { getHLSFileReadStream, getWebTorrentFileReadStream } from '@server/lib/object-storage'
5import {
6 asyncMiddleware,
7 ensureCanAccessPrivateVideoHLSFiles,
8 ensureCanAccessVideoPrivateWebTorrentFiles,
9 optionalAuthenticate
10} from '@server/middlewares'
11import { HttpStatusCode } from '@shared/models'
12
13const objectStorageProxyRouter = express.Router()
14
15objectStorageProxyRouter.use(cors())
16
17objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + ':filename',
18 optionalAuthenticate,
19 asyncMiddleware(ensureCanAccessVideoPrivateWebTorrentFiles),
20 asyncMiddleware(proxifyWebTorrent)
21)
22
23objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:filename',
24 optionalAuthenticate,
25 asyncMiddleware(ensureCanAccessPrivateVideoHLSFiles),
26 asyncMiddleware(proxifyHLS)
27)
28
29// ---------------------------------------------------------------------------
30
31export {
32 objectStorageProxyRouter
33}
34
35async function proxifyWebTorrent (req: express.Request, res: express.Response) {
36 const filename = req.params.filename
37
38 try {
39 const stream = await getWebTorrentFileReadStream({
40 filename,
41 rangeHeader: req.header('range')
42 })
43
44 return stream.pipe(res)
45 } catch (err) {
46 return handleObjectStorageFailure(res, err)
47 }
48}
49
50async function proxifyHLS (req: express.Request, res: express.Response) {
51 const playlist = res.locals.videoStreamingPlaylist
52 const video = res.locals.onlyVideo
53 const filename = req.params.filename
54
55 try {
56 const stream = await getHLSFileReadStream({
57 playlist: playlist.withVideo(video),
58 filename,
59 rangeHeader: req.header('range')
60 })
61
62 return stream.pipe(res)
63 } catch (err) {
64 return handleObjectStorageFailure(res, err)
65 }
66}
67
68function handleObjectStorageFailure (res: express.Response, err: Error) {
69 if (err.name === 'NoSuchKey') {
70 return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
71 }
72
73 return res.fail({
74 status: HttpStatusCode.INTERNAL_SERVER_ERROR_500,
75 message: err.message,
76 type: err.name
77 })
78}
diff --git a/server/helpers/webtorrent.ts b/server/helpers/webtorrent.ts
index 6d87c74f7..b458e86d2 100644
--- a/server/helpers/webtorrent.ts
+++ b/server/helpers/webtorrent.ts
@@ -165,7 +165,7 @@ function generateMagnetUri (
165 const xs = videoFile.getTorrentUrl() 165 const xs = videoFile.getTorrentUrl()
166 const announce = trackerUrls 166 const announce = trackerUrls
167 167
168 let urlList = video.requiresAuth(video.uuid) 168 let urlList = video.hasPrivateStaticPath()
169 ? [] 169 ? []
170 : [ videoFile.getFileUrl(video) ] 170 : [ videoFile.getFileUrl(video) ]
171 171
@@ -243,7 +243,7 @@ function buildAnnounceList () {
243} 243}
244 244
245function buildUrlList (video: MVideo, videoFile: MVideoFile) { 245function buildUrlList (video: MVideo, videoFile: MVideoFile) {
246 if (video.requiresAuth(video.uuid)) return [] 246 if (video.hasPrivateStaticPath()) return []
247 247
248 return [ videoFile.getFileUrl(video) ] 248 return [ videoFile.getFileUrl(video) ]
249} 249}
diff --git a/server/initializers/checker-after-init.ts b/server/initializers/checker-after-init.ts
index c83fef425..09e878eee 100644
--- a/server/initializers/checker-after-init.ts
+++ b/server/initializers/checker-after-init.ts
@@ -278,6 +278,14 @@ function checkObjectStorageConfig () {
278 'Object storage bucket prefixes should be set to different values when the same bucket is used for both types of video.' 278 'Object storage bucket prefixes should be set to different values when the same bucket is used for both types of video.'
279 ) 279 )
280 } 280 }
281
282 if (!CONFIG.OBJECT_STORAGE.UPLOAD_ACL.PUBLIC) {
283 throw new Error('object_storage.upload_acl.public must be set')
284 }
285
286 if (!CONFIG.OBJECT_STORAGE.UPLOAD_ACL.PRIVATE) {
287 throw new Error('object_storage.upload_acl.private must be set')
288 }
281 } 289 }
282} 290}
283 291
diff --git a/server/initializers/config.ts b/server/initializers/config.ts
index a5a0d4e46..ab5e645ad 100644
--- a/server/initializers/config.ts
+++ b/server/initializers/config.ts
@@ -118,7 +118,10 @@ const CONFIG = {
118 MAX_UPLOAD_PART: bytes.parse(config.get<string>('object_storage.max_upload_part')), 118 MAX_UPLOAD_PART: bytes.parse(config.get<string>('object_storage.max_upload_part')),
119 ENDPOINT: config.get<string>('object_storage.endpoint'), 119 ENDPOINT: config.get<string>('object_storage.endpoint'),
120 REGION: config.get<string>('object_storage.region'), 120 REGION: config.get<string>('object_storage.region'),
121 UPLOAD_ACL: config.get<string>('object_storage.upload_acl'), 121 UPLOAD_ACL: {
122 PUBLIC: config.get<string>('object_storage.upload_acl.public'),
123 PRIVATE: config.get<string>('object_storage.upload_acl.private')
124 },
122 CREDENTIALS: { 125 CREDENTIALS: {
123 ACCESS_KEY_ID: config.get<string>('object_storage.credentials.access_key_id'), 126 ACCESS_KEY_ID: config.get<string>('object_storage.credentials.access_key_id'),
124 SECRET_ACCESS_KEY: config.get<string>('object_storage.credentials.secret_access_key') 127 SECRET_ACCESS_KEY: config.get<string>('object_storage.credentials.secret_access_key')
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 88bdd07fe..66eb31230 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -685,6 +685,13 @@ const LAZY_STATIC_PATHS = {
685 VIDEO_CAPTIONS: '/lazy-static/video-captions/', 685 VIDEO_CAPTIONS: '/lazy-static/video-captions/',
686 TORRENTS: '/lazy-static/torrents/' 686 TORRENTS: '/lazy-static/torrents/'
687} 687}
688const OBJECT_STORAGE_PROXY_PATHS = {
689 PRIVATE_WEBSEED: '/object-storage-proxy/webseed/private/',
690
691 STREAMING_PLAYLISTS: {
692 PRIVATE_HLS: '/object-storage-proxy/streaming-playlists/hls/private/'
693 }
694}
688 695
689// Cache control 696// Cache control
690const STATIC_MAX_AGE = { 697const STATIC_MAX_AGE = {
@@ -995,6 +1002,7 @@ export {
995 VIDEO_LIVE, 1002 VIDEO_LIVE,
996 PEERTUBE_VERSION, 1003 PEERTUBE_VERSION,
997 LAZY_STATIC_PATHS, 1004 LAZY_STATIC_PATHS,
1005 OBJECT_STORAGE_PROXY_PATHS,
998 SEARCH_INDEX, 1006 SEARCH_INDEX,
999 DIRECTORIES, 1007 DIRECTORIES,
1000 RESUMABLE_UPLOAD_SESSION_LIFETIME, 1008 RESUMABLE_UPLOAD_SESSION_LIFETIME,
diff --git a/server/lib/live/live-segment-sha-store.ts b/server/lib/live/live-segment-sha-store.ts
index faf03dccf..4d03754a9 100644
--- a/server/lib/live/live-segment-sha-store.ts
+++ b/server/lib/live/live-segment-sha-store.ts
@@ -5,6 +5,7 @@ import { logger, loggerTagsFactory } from '@server/helpers/logger'
5import { MStreamingPlaylistVideo } from '@server/types/models' 5import { MStreamingPlaylistVideo } from '@server/types/models'
6import { buildSha256Segment } from '../hls' 6import { buildSha256Segment } from '../hls'
7import { storeHLSFileFromPath } from '../object-storage' 7import { storeHLSFileFromPath } from '../object-storage'
8import PQueue from 'p-queue'
8 9
9const lTags = loggerTagsFactory('live') 10const lTags = loggerTagsFactory('live')
10 11
@@ -16,6 +17,7 @@ class LiveSegmentShaStore {
16 private readonly sha256Path: string 17 private readonly sha256Path: string
17 private readonly streamingPlaylist: MStreamingPlaylistVideo 18 private readonly streamingPlaylist: MStreamingPlaylistVideo
18 private readonly sendToObjectStorage: boolean 19 private readonly sendToObjectStorage: boolean
20 private readonly writeQueue = new PQueue({ concurrency: 1 })
19 21
20 constructor (options: { 22 constructor (options: {
21 videoUUID: string 23 videoUUID: string
@@ -37,7 +39,11 @@ class LiveSegmentShaStore {
37 const segmentName = basename(segmentPath) 39 const segmentName = basename(segmentPath)
38 this.segmentsSha256.set(segmentName, shaResult) 40 this.segmentsSha256.set(segmentName, shaResult)
39 41
40 await this.writeToDisk() 42 try {
43 await this.writeToDisk()
44 } catch (err) {
45 logger.error('Cannot write sha segments to disk.', { err })
46 }
41 } 47 }
42 48
43 async removeSegmentSha (segmentPath: string) { 49 async removeSegmentSha (segmentPath: string) {
@@ -55,19 +61,20 @@ class LiveSegmentShaStore {
55 await this.writeToDisk() 61 await this.writeToDisk()
56 } 62 }
57 63
58 private async writeToDisk () { 64 private writeToDisk () {
59 await writeJson(this.sha256Path, mapToJSON(this.segmentsSha256)) 65 return this.writeQueue.add(async () => {
66 await writeJson(this.sha256Path, mapToJSON(this.segmentsSha256))
60 67
61 if (this.sendToObjectStorage) { 68 if (this.sendToObjectStorage) {
62 const url = await storeHLSFileFromPath(this.streamingPlaylist, this.sha256Path) 69 const url = await storeHLSFileFromPath(this.streamingPlaylist, this.sha256Path)
63 70
64 if (this.streamingPlaylist.segmentsSha256Url !== url) { 71 if (this.streamingPlaylist.segmentsSha256Url !== url) {
65 this.streamingPlaylist.segmentsSha256Url = url 72 this.streamingPlaylist.segmentsSha256Url = url
66 await this.streamingPlaylist.save() 73 await this.streamingPlaylist.save()
74 }
67 } 75 }
68 } 76 })
69 } 77 }
70
71} 78}
72 79
73export { 80export {
diff --git a/server/lib/object-storage/shared/object-storage-helpers.ts b/server/lib/object-storage/shared/object-storage-helpers.ts
index c131977e8..05b52f412 100644
--- a/server/lib/object-storage/shared/object-storage-helpers.ts
+++ b/server/lib/object-storage/shared/object-storage-helpers.ts
@@ -2,18 +2,21 @@ import { createReadStream, createWriteStream, ensureDir, ReadStream } from 'fs-e
2import { dirname } from 'path' 2import { dirname } from 'path'
3import { Readable } from 'stream' 3import { Readable } from 'stream'
4import { 4import {
5 _Object,
5 CompleteMultipartUploadCommandOutput, 6 CompleteMultipartUploadCommandOutput,
6 DeleteObjectCommand, 7 DeleteObjectCommand,
7 GetObjectCommand, 8 GetObjectCommand,
8 ListObjectsV2Command, 9 ListObjectsV2Command,
9 PutObjectCommandInput 10 PutObjectAclCommand,
11 PutObjectCommandInput,
12 S3Client
10} from '@aws-sdk/client-s3' 13} from '@aws-sdk/client-s3'
11import { Upload } from '@aws-sdk/lib-storage' 14import { Upload } from '@aws-sdk/lib-storage'
12import { pipelinePromise } from '@server/helpers/core-utils' 15import { pipelinePromise } from '@server/helpers/core-utils'
13import { isArray } from '@server/helpers/custom-validators/misc' 16import { isArray } from '@server/helpers/custom-validators/misc'
14import { logger } from '@server/helpers/logger' 17import { logger } from '@server/helpers/logger'
15import { CONFIG } from '@server/initializers/config' 18import { CONFIG } from '@server/initializers/config'
16import { getPrivateUrl } from '../urls' 19import { getInternalUrl } from '../urls'
17import { getClient } from './client' 20import { getClient } from './client'
18import { lTags } from './logger' 21import { lTags } from './logger'
19 22
@@ -44,69 +47,91 @@ async function storeObject (options: {
44 inputPath: string 47 inputPath: string
45 objectStorageKey: string 48 objectStorageKey: string
46 bucketInfo: BucketInfo 49 bucketInfo: BucketInfo
50 isPrivate: boolean
47}): Promise<string> { 51}): Promise<string> {
48 const { inputPath, objectStorageKey, bucketInfo } = options 52 const { inputPath, objectStorageKey, bucketInfo, isPrivate } = options
49 53
50 logger.debug('Uploading file %s to %s%s in bucket %s', inputPath, bucketInfo.PREFIX, objectStorageKey, bucketInfo.BUCKET_NAME, lTags()) 54 logger.debug('Uploading file %s to %s%s in bucket %s', inputPath, bucketInfo.PREFIX, objectStorageKey, bucketInfo.BUCKET_NAME, lTags())
51 55
52 const fileStream = createReadStream(inputPath) 56 const fileStream = createReadStream(inputPath)
53 57
54 return uploadToStorage({ objectStorageKey, content: fileStream, bucketInfo }) 58 return uploadToStorage({ objectStorageKey, content: fileStream, bucketInfo, isPrivate })
55} 59}
56 60
57// --------------------------------------------------------------------------- 61// ---------------------------------------------------------------------------
58 62
59async function removeObject (filename: string, bucketInfo: BucketInfo) { 63function updateObjectACL (options: {
60 const command = new DeleteObjectCommand({ 64 objectStorageKey: string
65 bucketInfo: BucketInfo
66 isPrivate: boolean
67}) {
68 const { objectStorageKey, bucketInfo, isPrivate } = options
69
70 const key = buildKey(objectStorageKey, bucketInfo)
71
72 logger.debug('Updating ACL file %s in bucket %s', key, bucketInfo.BUCKET_NAME, lTags())
73
74 const command = new PutObjectAclCommand({
61 Bucket: bucketInfo.BUCKET_NAME, 75 Bucket: bucketInfo.BUCKET_NAME,
62 Key: buildKey(filename, bucketInfo) 76 Key: key,
77 ACL: getACL(isPrivate)
63 }) 78 })
64 79
65 return getClient().send(command) 80 return getClient().send(command)
66} 81}
67 82
68async function removePrefix (prefix: string, bucketInfo: BucketInfo) { 83function updatePrefixACL (options: {
69 const s3Client = getClient() 84 prefix: string
70 85 bucketInfo: BucketInfo
71 const commandPrefix = bucketInfo.PREFIX + prefix 86 isPrivate: boolean
72 const listCommand = new ListObjectsV2Command({ 87}) {
73 Bucket: bucketInfo.BUCKET_NAME, 88 const { prefix, bucketInfo, isPrivate } = options
74 Prefix: commandPrefix 89
90 logger.debug('Updating ACL of files in prefix %s in bucket %s', prefix, bucketInfo.BUCKET_NAME, lTags())
91
92 return applyOnPrefix({
93 prefix,
94 bucketInfo,
95 commandBuilder: obj => {
96 return new PutObjectAclCommand({
97 Bucket: bucketInfo.BUCKET_NAME,
98 Key: obj.Key,
99 ACL: getACL(isPrivate)
100 })
101 }
75 }) 102 })
103}
76 104
77 const listedObjects = await s3Client.send(listCommand) 105// ---------------------------------------------------------------------------
78 106
79 // FIXME: use bulk delete when s3ninja will support this operation 107function removeObject (objectStorageKey: string, bucketInfo: BucketInfo) {
80 // const deleteParams = { 108 const key = buildKey(objectStorageKey, bucketInfo)
81 // Bucket: bucketInfo.BUCKET_NAME,
82 // Delete: { Objects: [] }
83 // }
84 109
85 if (isArray(listedObjects.Contents) !== true) { 110 logger.debug('Removing file %s in bucket %s', key, bucketInfo.BUCKET_NAME, lTags())
86 const message = `Cannot remove ${commandPrefix} prefix in bucket ${bucketInfo.BUCKET_NAME}: no files listed.`
87 111
88 logger.error(message, { response: listedObjects, ...lTags() }) 112 const command = new DeleteObjectCommand({
89 throw new Error(message) 113 Bucket: bucketInfo.BUCKET_NAME,
90 } 114 Key: key
91 115 })
92 for (const object of listedObjects.Contents) {
93 const command = new DeleteObjectCommand({
94 Bucket: bucketInfo.BUCKET_NAME,
95 Key: object.Key
96 })
97
98 await s3Client.send(command)
99 116
100 // FIXME: use bulk delete when s3ninja will support this operation 117 return getClient().send(command)
101 // deleteParams.Delete.Objects.push({ Key: object.Key }) 118}
102 }
103 119
120function removePrefix (prefix: string, bucketInfo: BucketInfo) {
104 // FIXME: use bulk delete when s3ninja will support this operation 121 // FIXME: use bulk delete when s3ninja will support this operation
105 // const deleteCommand = new DeleteObjectsCommand(deleteParams)
106 // await s3Client.send(deleteCommand)
107 122
108 // Repeat if not all objects could be listed at once (limit of 1000?) 123 logger.debug('Removing prefix %s in bucket %s', prefix, bucketInfo.BUCKET_NAME, lTags())
109 if (listedObjects.IsTruncated) await removePrefix(prefix, bucketInfo) 124
125 return applyOnPrefix({
126 prefix,
127 bucketInfo,
128 commandBuilder: obj => {
129 return new DeleteObjectCommand({
130 Bucket: bucketInfo.BUCKET_NAME,
131 Key: obj.Key
132 })
133 }
134 })
110} 135}
111 136
112// --------------------------------------------------------------------------- 137// ---------------------------------------------------------------------------
@@ -138,14 +163,42 @@ function buildKey (key: string, bucketInfo: BucketInfo) {
138 163
139// --------------------------------------------------------------------------- 164// ---------------------------------------------------------------------------
140 165
166async function createObjectReadStream (options: {
167 key: string
168 bucketInfo: BucketInfo
169 rangeHeader: string
170}) {
171 const { key, bucketInfo, rangeHeader } = options
172
173 const command = new GetObjectCommand({
174 Bucket: bucketInfo.BUCKET_NAME,
175 Key: buildKey(key, bucketInfo),
176 Range: rangeHeader
177 })
178
179 const response = await getClient().send(command)
180
181 return response.Body as Readable
182}
183
184// ---------------------------------------------------------------------------
185
141export { 186export {
142 BucketInfo, 187 BucketInfo,
143 buildKey, 188 buildKey,
189
144 storeObject, 190 storeObject,
191
145 removeObject, 192 removeObject,
146 removePrefix, 193 removePrefix,
194
147 makeAvailable, 195 makeAvailable,
148 listKeysOfPrefix 196
197 updateObjectACL,
198 updatePrefixACL,
199
200 listKeysOfPrefix,
201 createObjectReadStream
149} 202}
150 203
151// --------------------------------------------------------------------------- 204// ---------------------------------------------------------------------------
@@ -154,17 +207,15 @@ async function uploadToStorage (options: {
154 content: ReadStream 207 content: ReadStream
155 objectStorageKey: string 208 objectStorageKey: string
156 bucketInfo: BucketInfo 209 bucketInfo: BucketInfo
210 isPrivate: boolean
157}) { 211}) {
158 const { content, objectStorageKey, bucketInfo } = options 212 const { content, objectStorageKey, bucketInfo, isPrivate } = options
159 213
160 const input: PutObjectCommandInput = { 214 const input: PutObjectCommandInput = {
161 Body: content, 215 Body: content,
162 Bucket: bucketInfo.BUCKET_NAME, 216 Bucket: bucketInfo.BUCKET_NAME,
163 Key: buildKey(objectStorageKey, bucketInfo) 217 Key: buildKey(objectStorageKey, bucketInfo),
164 } 218 ACL: getACL(isPrivate)
165
166 if (CONFIG.OBJECT_STORAGE.UPLOAD_ACL) {
167 input.ACL = CONFIG.OBJECT_STORAGE.UPLOAD_ACL
168 } 219 }
169 220
170 const parallelUploads3 = new Upload({ 221 const parallelUploads3 = new Upload({
@@ -194,5 +245,50 @@ async function uploadToStorage (options: {
194 bucketInfo.PREFIX, objectStorageKey, bucketInfo.BUCKET_NAME, lTags() 245 bucketInfo.PREFIX, objectStorageKey, bucketInfo.BUCKET_NAME, lTags()
195 ) 246 )
196 247
197 return getPrivateUrl(bucketInfo, objectStorageKey) 248 return getInternalUrl(bucketInfo, objectStorageKey)
249}
250
251async function applyOnPrefix (options: {
252 prefix: string
253 bucketInfo: BucketInfo
254 commandBuilder: (obj: _Object) => Parameters<S3Client['send']>[0]
255
256 continuationToken?: string
257}) {
258 const { prefix, bucketInfo, commandBuilder, continuationToken } = options
259
260 const s3Client = getClient()
261
262 const commandPrefix = bucketInfo.PREFIX + prefix
263 const listCommand = new ListObjectsV2Command({
264 Bucket: bucketInfo.BUCKET_NAME,
265 Prefix: commandPrefix,
266 ContinuationToken: continuationToken
267 })
268
269 const listedObjects = await s3Client.send(listCommand)
270
271 if (isArray(listedObjects.Contents) !== true) {
272 const message = `Cannot apply function on ${commandPrefix} prefix in bucket ${bucketInfo.BUCKET_NAME}: no files listed.`
273
274 logger.error(message, { response: listedObjects, ...lTags() })
275 throw new Error(message)
276 }
277
278 for (const object of listedObjects.Contents) {
279 const command = commandBuilder(object)
280
281 await s3Client.send(command)
282 }
283
284 // Repeat if not all objects could be listed at once (limit of 1000?)
285 if (listedObjects.IsTruncated) {
286 await applyOnPrefix({ ...options, continuationToken: listedObjects.ContinuationToken })
287 }
288}
289
290function getACL (isPrivate: boolean) {
291 return isPrivate
292 ? CONFIG.OBJECT_STORAGE.UPLOAD_ACL.PRIVATE
293 : CONFIG.OBJECT_STORAGE.UPLOAD_ACL.PUBLIC
198} 294}
diff --git a/server/lib/object-storage/urls.ts b/server/lib/object-storage/urls.ts
index 2a889190b..a47a98b98 100644
--- a/server/lib/object-storage/urls.ts
+++ b/server/lib/object-storage/urls.ts
@@ -1,10 +1,14 @@
1import { CONFIG } from '@server/initializers/config' 1import { CONFIG } from '@server/initializers/config'
2import { OBJECT_STORAGE_PROXY_PATHS, WEBSERVER } from '@server/initializers/constants'
3import { MVideoUUID } from '@server/types/models'
2import { BucketInfo, buildKey, getEndpointParsed } from './shared' 4import { BucketInfo, buildKey, getEndpointParsed } from './shared'
3 5
4function getPrivateUrl (config: BucketInfo, keyWithoutPrefix: string) { 6function getInternalUrl (config: BucketInfo, keyWithoutPrefix: string) {
5 return getBaseUrl(config) + buildKey(keyWithoutPrefix, config) 7 return getBaseUrl(config) + buildKey(keyWithoutPrefix, config)
6} 8}
7 9
10// ---------------------------------------------------------------------------
11
8function getWebTorrentPublicFileUrl (fileUrl: string) { 12function getWebTorrentPublicFileUrl (fileUrl: string) {
9 const baseUrl = CONFIG.OBJECT_STORAGE.VIDEOS.BASE_URL 13 const baseUrl = CONFIG.OBJECT_STORAGE.VIDEOS.BASE_URL
10 if (!baseUrl) return fileUrl 14 if (!baseUrl) return fileUrl
@@ -19,11 +23,28 @@ function getHLSPublicFileUrl (fileUrl: string) {
19 return replaceByBaseUrl(fileUrl, baseUrl) 23 return replaceByBaseUrl(fileUrl, baseUrl)
20} 24}
21 25
26// ---------------------------------------------------------------------------
27
28function getHLSPrivateFileUrl (video: MVideoUUID, filename: string) {
29 return WEBSERVER.URL + OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + video.uuid + `/${filename}`
30}
31
32function getWebTorrentPrivateFileUrl (filename: string) {
33 return WEBSERVER.URL + OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + filename
34}
35
36// ---------------------------------------------------------------------------
37
22export { 38export {
23 getPrivateUrl, 39 getInternalUrl,
40
24 getWebTorrentPublicFileUrl, 41 getWebTorrentPublicFileUrl,
25 replaceByBaseUrl, 42 getHLSPublicFileUrl,
26 getHLSPublicFileUrl 43
44 getHLSPrivateFileUrl,
45 getWebTorrentPrivateFileUrl,
46
47 replaceByBaseUrl
27} 48}
28 49
29// --------------------------------------------------------------------------- 50// ---------------------------------------------------------------------------
diff --git a/server/lib/object-storage/videos.ts b/server/lib/object-storage/videos.ts
index e323baaa2..003807826 100644
--- a/server/lib/object-storage/videos.ts
+++ b/server/lib/object-storage/videos.ts
@@ -5,7 +5,17 @@ import { MStreamingPlaylistVideo, MVideo, MVideoFile } from '@server/types/model
5import { getHLSDirectory } from '../paths' 5import { getHLSDirectory } from '../paths'
6import { VideoPathManager } from '../video-path-manager' 6import { VideoPathManager } from '../video-path-manager'
7import { generateHLSObjectBaseStorageKey, generateHLSObjectStorageKey, generateWebTorrentObjectStorageKey } from './keys' 7import { generateHLSObjectBaseStorageKey, generateHLSObjectStorageKey, generateWebTorrentObjectStorageKey } from './keys'
8import { listKeysOfPrefix, lTags, makeAvailable, removeObject, removePrefix, storeObject } from './shared' 8import {
9 createObjectReadStream,
10 listKeysOfPrefix,
11 lTags,
12 makeAvailable,
13 removeObject,
14 removePrefix,
15 storeObject,
16 updateObjectACL,
17 updatePrefixACL
18} from './shared'
9 19
10function listHLSFileKeysOf (playlist: MStreamingPlaylistVideo) { 20function listHLSFileKeysOf (playlist: MStreamingPlaylistVideo) {
11 return listKeysOfPrefix(generateHLSObjectBaseStorageKey(playlist), CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS) 21 return listKeysOfPrefix(generateHLSObjectBaseStorageKey(playlist), CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS)
@@ -17,7 +27,8 @@ function storeHLSFileFromFilename (playlist: MStreamingPlaylistVideo, filename:
17 return storeObject({ 27 return storeObject({
18 inputPath: join(getHLSDirectory(playlist.Video), filename), 28 inputPath: join(getHLSDirectory(playlist.Video), filename),
19 objectStorageKey: generateHLSObjectStorageKey(playlist, filename), 29 objectStorageKey: generateHLSObjectStorageKey(playlist, filename),
20 bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS 30 bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS,
31 isPrivate: playlist.Video.hasPrivateStaticPath()
21 }) 32 })
22} 33}
23 34
@@ -25,7 +36,8 @@ function storeHLSFileFromPath (playlist: MStreamingPlaylistVideo, path: string)
25 return storeObject({ 36 return storeObject({
26 inputPath: path, 37 inputPath: path,
27 objectStorageKey: generateHLSObjectStorageKey(playlist, basename(path)), 38 objectStorageKey: generateHLSObjectStorageKey(playlist, basename(path)),
28 bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS 39 bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS,
40 isPrivate: playlist.Video.hasPrivateStaticPath()
29 }) 41 })
30} 42}
31 43
@@ -35,7 +47,26 @@ function storeWebTorrentFile (video: MVideo, file: MVideoFile) {
35 return storeObject({ 47 return storeObject({
36 inputPath: VideoPathManager.Instance.getFSVideoFileOutputPath(video, file), 48 inputPath: VideoPathManager.Instance.getFSVideoFileOutputPath(video, file),
37 objectStorageKey: generateWebTorrentObjectStorageKey(file.filename), 49 objectStorageKey: generateWebTorrentObjectStorageKey(file.filename),
38 bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS 50 bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS,
51 isPrivate: video.hasPrivateStaticPath()
52 })
53}
54
55// ---------------------------------------------------------------------------
56
57function updateWebTorrentFileACL (video: MVideo, file: MVideoFile) {
58 return updateObjectACL({
59 objectStorageKey: generateWebTorrentObjectStorageKey(file.filename),
60 bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS,
61 isPrivate: video.hasPrivateStaticPath()
62 })
63}
64
65function updateHLSFilesACL (playlist: MStreamingPlaylistVideo) {
66 return updatePrefixACL({
67 prefix: generateHLSObjectBaseStorageKey(playlist),
68 bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS,
69 isPrivate: playlist.Video.hasPrivateStaticPath()
39 }) 70 })
40} 71}
41 72
@@ -87,6 +118,39 @@ async function makeWebTorrentFileAvailable (filename: string, destination: strin
87 118
88// --------------------------------------------------------------------------- 119// ---------------------------------------------------------------------------
89 120
121function getWebTorrentFileReadStream (options: {
122 filename: string
123 rangeHeader: string
124}) {
125 const { filename, rangeHeader } = options
126
127 const key = generateWebTorrentObjectStorageKey(filename)
128
129 return createObjectReadStream({
130 key,
131 bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS,
132 rangeHeader
133 })
134}
135
136function getHLSFileReadStream (options: {
137 playlist: MStreamingPlaylistVideo
138 filename: string
139 rangeHeader: string
140}) {
141 const { playlist, filename, rangeHeader } = options
142
143 const key = generateHLSObjectStorageKey(playlist, filename)
144
145 return createObjectReadStream({
146 key,
147 bucketInfo: CONFIG.OBJECT_STORAGE.STREAMING_PLAYLISTS,
148 rangeHeader
149 })
150}
151
152// ---------------------------------------------------------------------------
153
90export { 154export {
91 listHLSFileKeysOf, 155 listHLSFileKeysOf,
92 156
@@ -94,10 +158,16 @@ export {
94 storeHLSFileFromFilename, 158 storeHLSFileFromFilename,
95 storeHLSFileFromPath, 159 storeHLSFileFromPath,
96 160
161 updateWebTorrentFileACL,
162 updateHLSFilesACL,
163
97 removeHLSObjectStorage, 164 removeHLSObjectStorage,
98 removeHLSFileObjectStorage, 165 removeHLSFileObjectStorage,
99 removeWebTorrentObjectStorage, 166 removeWebTorrentObjectStorage,
100 167
101 makeWebTorrentFileAvailable, 168 makeWebTorrentFileAvailable,
102 makeHLSFileAvailable 169 makeHLSFileAvailable,
170
171 getWebTorrentFileReadStream,
172 getHLSFileReadStream
103} 173}
diff --git a/server/lib/video-privacy.ts b/server/lib/video-privacy.ts
index 1a4a5a22d..41f9d62b3 100644
--- a/server/lib/video-privacy.ts
+++ b/server/lib/video-privacy.ts
@@ -2,8 +2,9 @@ import { move } from 'fs-extra'
2import { join } from 'path' 2import { join } from 'path'
3import { logger } from '@server/helpers/logger' 3import { logger } from '@server/helpers/logger'
4import { DIRECTORIES } from '@server/initializers/constants' 4import { DIRECTORIES } from '@server/initializers/constants'
5import { MVideo, MVideoFullLight } from '@server/types/models' 5import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
6import { VideoPrivacy } from '@shared/models' 6import { VideoPrivacy, VideoStorage } from '@shared/models'
7import { updateHLSFilesACL, updateWebTorrentFileACL } from './object-storage'
7 8
8function setVideoPrivacy (video: MVideo, newPrivacy: VideoPrivacy) { 9function setVideoPrivacy (video: MVideo, newPrivacy: VideoPrivacy) {
9 if (video.privacy === VideoPrivacy.PRIVATE && newPrivacy !== VideoPrivacy.PRIVATE) { 10 if (video.privacy === VideoPrivacy.PRIVATE && newPrivacy !== VideoPrivacy.PRIVATE) {
@@ -50,47 +51,77 @@ export {
50 51
51// --------------------------------------------------------------------------- 52// ---------------------------------------------------------------------------
52 53
54type MoveType = 'private-to-public' | 'public-to-private'
55
53async function moveFiles (options: { 56async function moveFiles (options: {
54 type: 'private-to-public' | 'public-to-private' 57 type: MoveType
55 video: MVideoFullLight 58 video: MVideoFullLight
56}) { 59}) {
57 const { type, video } = options 60 const { type, video } = options
58 61
59 const directories = type === 'private-to-public' 62 for (const file of video.VideoFiles) {
60 ? { 63 if (file.storage === VideoStorage.FILE_SYSTEM) {
61 webtorrent: { old: DIRECTORIES.VIDEOS.PRIVATE, new: DIRECTORIES.VIDEOS.PUBLIC }, 64 await moveWebTorrentFileOnFS(type, video, file)
62 hls: { old: DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE, new: DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC } 65 } else {
66 await updateWebTorrentFileACL(video, file)
63 } 67 }
64 : { 68 }
65 webtorrent: { old: DIRECTORIES.VIDEOS.PUBLIC, new: DIRECTORIES.VIDEOS.PRIVATE }, 69
66 hls: { old: DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC, new: DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE } 70 const hls = video.getHLSPlaylist()
71
72 if (hls) {
73 if (hls.storage === VideoStorage.FILE_SYSTEM) {
74 await moveHLSFilesOnFS(type, video)
75 } else {
76 await updateHLSFilesACL(hls)
67 } 77 }
78 }
79}
68 80
69 for (const file of video.VideoFiles) { 81async function moveWebTorrentFileOnFS (type: MoveType, video: MVideo, file: MVideoFile) {
70 const source = join(directories.webtorrent.old, file.filename) 82 const directories = getWebTorrentDirectories(type)
71 const destination = join(directories.webtorrent.new, file.filename)
72 83
73 try { 84 const source = join(directories.old, file.filename)
74 logger.info('Moving WebTorrent files of %s after privacy change (%s -> %s).', video.uuid, source, destination) 85 const destination = join(directories.new, file.filename)
75 86
76 await move(source, destination) 87 try {
77 } catch (err) { 88 logger.info('Moving WebTorrent files of %s after privacy change (%s -> %s).', video.uuid, source, destination)
78 logger.error('Cannot move webtorrent file %s to %s after privacy change', source, destination, { err }) 89
79 } 90 await move(source, destination)
91 } catch (err) {
92 logger.error('Cannot move webtorrent file %s to %s after privacy change', source, destination, { err })
93 }
94}
95
96function getWebTorrentDirectories (moveType: MoveType) {
97 if (moveType === 'private-to-public') {
98 return { old: DIRECTORIES.VIDEOS.PRIVATE, new: DIRECTORIES.VIDEOS.PUBLIC }
80 } 99 }
81 100
82 const hls = video.getHLSPlaylist() 101 return { old: DIRECTORIES.VIDEOS.PUBLIC, new: DIRECTORIES.VIDEOS.PRIVATE }
102}
83 103
84 if (hls) { 104// ---------------------------------------------------------------------------
85 const source = join(directories.hls.old, video.uuid)
86 const destination = join(directories.hls.new, video.uuid)
87 105
88 try { 106async function moveHLSFilesOnFS (type: MoveType, video: MVideo) {
89 logger.info('Moving HLS files of %s after privacy change (%s -> %s).', video.uuid, source, destination) 107 const directories = getHLSDirectories(type)
90 108
91 await move(source, destination) 109 const source = join(directories.old, video.uuid)
92 } catch (err) { 110 const destination = join(directories.new, video.uuid)
93 logger.error('Cannot move HLS file %s to %s after privacy change', source, destination, { err }) 111
94 } 112 try {
113 logger.info('Moving HLS files of %s after privacy change (%s -> %s).', video.uuid, source, destination)
114
115 await move(source, destination)
116 } catch (err) {
117 logger.error('Cannot move HLS file %s to %s after privacy change', source, destination, { err })
118 }
119}
120
121function getHLSDirectories (moveType: MoveType) {
122 if (moveType === 'private-to-public') {
123 return { old: DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE, new: DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC }
95 } 124 }
125
126 return { old: DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC, new: DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE }
96} 127}
diff --git a/server/middlewares/validators/shared/videos.ts b/server/middlewares/validators/shared/videos.ts
index c29751eca..ebbfc0a0a 100644
--- a/server/middlewares/validators/shared/videos.ts
+++ b/server/middlewares/validators/shared/videos.ts
@@ -111,7 +111,7 @@ async function checkCanSeeVideo (options: {
111}) { 111}) {
112 const { req, res, video, paramId } = options 112 const { req, res, video, paramId } = options
113 113
114 if (video.requiresAuth(paramId)) { 114 if (video.requiresAuth({ urlParamId: paramId, checkBlacklist: true })) {
115 return checkCanSeeAuthVideo(req, res, video) 115 return checkCanSeeAuthVideo(req, res, video)
116 } 116 }
117 117
@@ -174,13 +174,13 @@ async function checkCanAccessVideoStaticFiles (options: {
174 res: Response 174 res: Response
175 paramId: string 175 paramId: string
176}) { 176}) {
177 const { video, req, res, paramId } = options 177 const { video, req, res } = options
178 178
179 if (res.locals.oauth?.token.User) { 179 if (res.locals.oauth?.token.User) {
180 return checkCanSeeVideo(options) 180 return checkCanSeeVideo(options)
181 } 181 }
182 182
183 if (!video.requiresAuth(paramId)) return true 183 if (!video.hasPrivateStaticPath()) return true
184 184
185 const videoFileToken = req.query.videoFileToken 185 const videoFileToken = req.query.videoFileToken
186 if (!videoFileToken) { 186 if (!videoFileToken) {
diff --git a/server/middlewares/validators/static.ts b/server/middlewares/validators/static.ts
index ff9e6ae6e..13fde6dd1 100644
--- a/server/middlewares/validators/static.ts
+++ b/server/middlewares/validators/static.ts
@@ -7,10 +7,17 @@ import { logger } from '@server/helpers/logger'
7import { LRU_CACHE } from '@server/initializers/constants' 7import { LRU_CACHE } from '@server/initializers/constants'
8import { VideoModel } from '@server/models/video/video' 8import { VideoModel } from '@server/models/video/video'
9import { VideoFileModel } from '@server/models/video/video-file' 9import { VideoFileModel } from '@server/models/video/video-file'
10import { MStreamingPlaylist, MVideoFile, MVideoThumbnail } from '@server/types/models'
10import { HttpStatusCode } from '@shared/models' 11import { HttpStatusCode } from '@shared/models'
11import { areValidationErrors, checkCanAccessVideoStaticFiles } from './shared' 12import { areValidationErrors, checkCanAccessVideoStaticFiles } from './shared'
12 13
13const staticFileTokenBypass = new LRUCache<string, boolean>({ 14type LRUValue = {
15 allowed: boolean
16 video?: MVideoThumbnail
17 file?: MVideoFile
18 playlist?: MStreamingPlaylist }
19
20const staticFileTokenBypass = new LRUCache<string, LRUValue>({
14 max: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.MAX_SIZE, 21 max: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.MAX_SIZE,
15 ttl: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL 22 ttl: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL
16}) 23})
@@ -27,18 +34,26 @@ const ensureCanAccessVideoPrivateWebTorrentFiles = [
27 const cacheKey = token + '-' + req.originalUrl 34 const cacheKey = token + '-' + req.originalUrl
28 35
29 if (staticFileTokenBypass.has(cacheKey)) { 36 if (staticFileTokenBypass.has(cacheKey)) {
30 const allowedFromCache = staticFileTokenBypass.get(cacheKey) 37 const { allowed, file, video } = staticFileTokenBypass.get(cacheKey)
38
39 if (allowed === true) {
40 res.locals.onlyVideo = video
41 res.locals.videoFile = file
31 42
32 if (allowedFromCache === true) return next() 43 return next()
44 }
33 45
34 return res.sendStatus(HttpStatusCode.FORBIDDEN_403) 46 return res.sendStatus(HttpStatusCode.FORBIDDEN_403)
35 } 47 }
36 48
37 const allowed = await isWebTorrentAllowed(req, res) 49 const result = await isWebTorrentAllowed(req, res)
50
51 staticFileTokenBypass.set(cacheKey, result)
38 52
39 staticFileTokenBypass.set(cacheKey, allowed) 53 if (result.allowed !== true) return
40 54
41 if (allowed !== true) return 55 res.locals.onlyVideo = result.video
56 res.locals.videoFile = result.file
42 57
43 return next() 58 return next()
44 } 59 }
@@ -64,18 +79,28 @@ const ensureCanAccessPrivateVideoHLSFiles = [
64 const cacheKey = token + '-' + videoUUID 79 const cacheKey = token + '-' + videoUUID
65 80
66 if (staticFileTokenBypass.has(cacheKey)) { 81 if (staticFileTokenBypass.has(cacheKey)) {
67 const allowedFromCache = staticFileTokenBypass.get(cacheKey) 82 const { allowed, file, playlist, video } = staticFileTokenBypass.get(cacheKey)
68 83
69 if (allowedFromCache === true) return next() 84 if (allowed === true) {
85 res.locals.onlyVideo = video
86 res.locals.videoFile = file
87 res.locals.videoStreamingPlaylist = playlist
88
89 return next()
90 }
70 91
71 return res.sendStatus(HttpStatusCode.FORBIDDEN_403) 92 return res.sendStatus(HttpStatusCode.FORBIDDEN_403)
72 } 93 }
73 94
74 const allowed = await isHLSAllowed(req, res, videoUUID) 95 const result = await isHLSAllowed(req, res, videoUUID)
96
97 staticFileTokenBypass.set(cacheKey, result)
75 98
76 staticFileTokenBypass.set(cacheKey, allowed) 99 if (result.allowed !== true) return
77 100
78 if (allowed !== true) return 101 res.locals.onlyVideo = result.video
102 res.locals.videoFile = result.file
103 res.locals.videoStreamingPlaylist = result.playlist
79 104
80 return next() 105 return next()
81 } 106 }
@@ -96,25 +121,38 @@ async function isWebTorrentAllowed (req: express.Request, res: express.Response)
96 logger.debug('Unknown static file %s to serve', req.originalUrl, { filename }) 121 logger.debug('Unknown static file %s to serve', req.originalUrl, { filename })
97 122
98 res.sendStatus(HttpStatusCode.FORBIDDEN_403) 123 res.sendStatus(HttpStatusCode.FORBIDDEN_403)
99 return false 124 return { allowed: false }
100 } 125 }
101 126
102 const video = file.getVideo() 127 const video = await VideoModel.load(file.getVideo().id)
103 128
104 return checkCanAccessVideoStaticFiles({ req, res, video, paramId: video.uuid }) 129 return {
130 file,
131 video,
132 allowed: await checkCanAccessVideoStaticFiles({ req, res, video, paramId: video.uuid })
133 }
105} 134}
106 135
107async function isHLSAllowed (req: express.Request, res: express.Response, videoUUID: string) { 136async function isHLSAllowed (req: express.Request, res: express.Response, videoUUID: string) {
108 const video = await VideoModel.load(videoUUID) 137 const filename = basename(req.path)
138
139 const video = await VideoModel.loadWithFiles(videoUUID)
109 140
110 if (!video) { 141 if (!video) {
111 logger.debug('Unknown static file %s to serve', req.originalUrl, { videoUUID }) 142 logger.debug('Unknown static file %s to serve', req.originalUrl, { videoUUID })
112 143
113 res.sendStatus(HttpStatusCode.FORBIDDEN_403) 144 res.sendStatus(HttpStatusCode.FORBIDDEN_403)
114 return false 145 return { allowed: false }
115 } 146 }
116 147
117 return checkCanAccessVideoStaticFiles({ req, res, video, paramId: video.uuid }) 148 const file = await VideoFileModel.loadByFilename(filename)
149
150 return {
151 file,
152 video,
153 playlist: video.getHLSPlaylist(),
154 allowed: await checkCanAccessVideoStaticFiles({ req, res, video, paramId: video.uuid })
155 }
118} 156}
119 157
120function extractTokenOrDie (req: express.Request, res: express.Response) { 158function extractTokenOrDie (req: express.Request, res: express.Response) {
diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts
index 1a608932f..c20c90c1b 100644
--- a/server/models/video/video-file.ts
+++ b/server/models/video/video-file.ts
@@ -22,7 +22,12 @@ import validator from 'validator'
22import { logger } from '@server/helpers/logger' 22import { logger } from '@server/helpers/logger'
23import { extractVideo } from '@server/helpers/video' 23import { extractVideo } from '@server/helpers/video'
24import { buildRemoteVideoBaseUrl } from '@server/lib/activitypub/url' 24import { buildRemoteVideoBaseUrl } from '@server/lib/activitypub/url'
25import { getHLSPublicFileUrl, getWebTorrentPublicFileUrl } from '@server/lib/object-storage' 25import {
26 getHLSPrivateFileUrl,
27 getHLSPublicFileUrl,
28 getWebTorrentPrivateFileUrl,
29 getWebTorrentPublicFileUrl
30} from '@server/lib/object-storage'
26import { getFSTorrentFilePath } from '@server/lib/paths' 31import { getFSTorrentFilePath } from '@server/lib/paths'
27import { isVideoInPrivateDirectory } from '@server/lib/video-privacy' 32import { isVideoInPrivateDirectory } from '@server/lib/video-privacy'
28import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models' 33import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models'
@@ -503,7 +508,25 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
503 return !!this.videoStreamingPlaylistId 508 return !!this.videoStreamingPlaylistId
504 } 509 }
505 510
506 getObjectStorageUrl () { 511 // ---------------------------------------------------------------------------
512
513 getObjectStorageUrl (video: MVideo) {
514 if (video.hasPrivateStaticPath()) {
515 return this.getPrivateObjectStorageUrl(video)
516 }
517
518 return this.getPublicObjectStorageUrl()
519 }
520
521 private getPrivateObjectStorageUrl (video: MVideo) {
522 if (this.isHLS()) {
523 return getHLSPrivateFileUrl(video, this.filename)
524 }
525
526 return getWebTorrentPrivateFileUrl(this.filename)
527 }
528
529 private getPublicObjectStorageUrl () {
507 if (this.isHLS()) { 530 if (this.isHLS()) {
508 return getHLSPublicFileUrl(this.fileUrl) 531 return getHLSPublicFileUrl(this.fileUrl)
509 } 532 }
@@ -511,26 +534,29 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
511 return getWebTorrentPublicFileUrl(this.fileUrl) 534 return getWebTorrentPublicFileUrl(this.fileUrl)
512 } 535 }
513 536
537 // ---------------------------------------------------------------------------
538
514 getFileUrl (video: MVideo) { 539 getFileUrl (video: MVideo) {
515 if (this.storage === VideoStorage.OBJECT_STORAGE) { 540 if (video.isOwned()) {
516 return this.getObjectStorageUrl() 541 if (this.storage === VideoStorage.OBJECT_STORAGE) {
517 } 542 return this.getObjectStorageUrl(video)
543 }
518 544
519 if (!this.Video) this.Video = video as VideoModel 545 return WEBSERVER.URL + this.getFileStaticPath(video)
520 if (video.isOwned()) return WEBSERVER.URL + this.getFileStaticPath(video) 546 }
521 547
522 return this.fileUrl 548 return this.fileUrl
523 } 549 }
524 550
551 // ---------------------------------------------------------------------------
552
525 getFileStaticPath (video: MVideo) { 553 getFileStaticPath (video: MVideo) {
526 if (this.isHLS()) { 554 if (this.isHLS()) return this.getHLSFileStaticPath(video)
527 if (isVideoInPrivateDirectory(video.privacy)) {
528 return join(STATIC_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS, video.uuid, this.filename)
529 }
530 555
531 return join(STATIC_PATHS.STREAMING_PLAYLISTS.HLS, video.uuid, this.filename) 556 return this.getWebTorrentFileStaticPath(video)
532 } 557 }
533 558
559 private getWebTorrentFileStaticPath (video: MVideo) {
534 if (isVideoInPrivateDirectory(video.privacy)) { 560 if (isVideoInPrivateDirectory(video.privacy)) {
535 return join(STATIC_PATHS.PRIVATE_WEBSEED, this.filename) 561 return join(STATIC_PATHS.PRIVATE_WEBSEED, this.filename)
536 } 562 }
@@ -538,6 +564,16 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
538 return join(STATIC_PATHS.WEBSEED, this.filename) 564 return join(STATIC_PATHS.WEBSEED, this.filename)
539 } 565 }
540 566
567 private getHLSFileStaticPath (video: MVideo) {
568 if (isVideoInPrivateDirectory(video.privacy)) {
569 return join(STATIC_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS, video.uuid, this.filename)
570 }
571
572 return join(STATIC_PATHS.STREAMING_PLAYLISTS.HLS, video.uuid, this.filename)
573 }
574
575 // ---------------------------------------------------------------------------
576
541 getFileDownloadUrl (video: MVideoWithHost) { 577 getFileDownloadUrl (video: MVideoWithHost) {
542 const path = this.isHLS() 578 const path = this.isHLS()
543 ? join(STATIC_DOWNLOAD_PATHS.HLS_VIDEOS, `${video.uuid}-${this.resolution}-fragmented${this.extname}`) 579 ? join(STATIC_DOWNLOAD_PATHS.HLS_VIDEOS, `${video.uuid}-${this.resolution}-fragmented${this.extname}`)
diff --git a/server/models/video/video-streaming-playlist.ts b/server/models/video/video-streaming-playlist.ts
index b919046ed..1318a4dae 100644
--- a/server/models/video/video-streaming-playlist.ts
+++ b/server/models/video/video-streaming-playlist.ts
@@ -15,7 +15,7 @@ import {
15 Table, 15 Table,
16 UpdatedAt 16 UpdatedAt
17} from 'sequelize-typescript' 17} from 'sequelize-typescript'
18import { getHLSPublicFileUrl } from '@server/lib/object-storage' 18import { getHLSPrivateFileUrl, getHLSPublicFileUrl } from '@server/lib/object-storage'
19import { generateHLSMasterPlaylistFilename, generateHlsSha256SegmentsFilename } from '@server/lib/paths' 19import { generateHLSMasterPlaylistFilename, generateHlsSha256SegmentsFilename } from '@server/lib/paths'
20import { isVideoInPrivateDirectory } from '@server/lib/video-privacy' 20import { isVideoInPrivateDirectory } from '@server/lib/video-privacy'
21import { VideoFileModel } from '@server/models/video/video-file' 21import { VideoFileModel } from '@server/models/video/video-file'
@@ -245,10 +245,12 @@ export class VideoStreamingPlaylistModel extends Model<Partial<AttributesOnly<Vi
245 this.p2pMediaLoaderInfohashes = VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(masterPlaylistUrl, files) 245 this.p2pMediaLoaderInfohashes = VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(masterPlaylistUrl, files)
246 } 246 }
247 247
248 // ---------------------------------------------------------------------------
249
248 getMasterPlaylistUrl (video: MVideo) { 250 getMasterPlaylistUrl (video: MVideo) {
249 if (video.isOwned()) { 251 if (video.isOwned()) {
250 if (this.storage === VideoStorage.OBJECT_STORAGE) { 252 if (this.storage === VideoStorage.OBJECT_STORAGE) {
251 return getHLSPublicFileUrl(this.playlistUrl) 253 return this.getMasterPlaylistObjectStorageUrl(video)
252 } 254 }
253 255
254 return WEBSERVER.URL + this.getMasterPlaylistStaticPath(video) 256 return WEBSERVER.URL + this.getMasterPlaylistStaticPath(video)
@@ -257,10 +259,20 @@ export class VideoStreamingPlaylistModel extends Model<Partial<AttributesOnly<Vi
257 return this.playlistUrl 259 return this.playlistUrl
258 } 260 }
259 261
262 private getMasterPlaylistObjectStorageUrl (video: MVideo) {
263 if (video.hasPrivateStaticPath()) {
264 return getHLSPrivateFileUrl(video, this.playlistFilename)
265 }
266
267 return getHLSPublicFileUrl(this.playlistUrl)
268 }
269
270 // ---------------------------------------------------------------------------
271
260 getSha256SegmentsUrl (video: MVideo) { 272 getSha256SegmentsUrl (video: MVideo) {
261 if (video.isOwned()) { 273 if (video.isOwned()) {
262 if (this.storage === VideoStorage.OBJECT_STORAGE) { 274 if (this.storage === VideoStorage.OBJECT_STORAGE) {
263 return getHLSPublicFileUrl(this.segmentsSha256Url) 275 return this.getSha256SegmentsObjectStorageUrl(video)
264 } 276 }
265 277
266 return WEBSERVER.URL + this.getSha256SegmentsStaticPath(video) 278 return WEBSERVER.URL + this.getSha256SegmentsStaticPath(video)
@@ -269,6 +281,16 @@ export class VideoStreamingPlaylistModel extends Model<Partial<AttributesOnly<Vi
269 return this.segmentsSha256Url 281 return this.segmentsSha256Url
270 } 282 }
271 283
284 private getSha256SegmentsObjectStorageUrl (video: MVideo) {
285 if (video.hasPrivateStaticPath()) {
286 return getHLSPrivateFileUrl(video, this.segmentsSha256Filename)
287 }
288
289 return getHLSPublicFileUrl(this.segmentsSha256Url)
290 }
291
292 // ---------------------------------------------------------------------------
293
272 getStringType () { 294 getStringType () {
273 if (this.type === VideoStreamingPlaylistType.HLS) return 'hls' 295 if (this.type === VideoStreamingPlaylistType.HLS) return 'hls'
274 296
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 82362917e..c568075d8 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -30,6 +30,7 @@ import { removeHLSFileObjectStorage, removeHLSObjectStorage, removeWebTorrentObj
30import { tracer } from '@server/lib/opentelemetry/tracing' 30import { tracer } from '@server/lib/opentelemetry/tracing'
31import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths' 31import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths'
32import { VideoPathManager } from '@server/lib/video-path-manager' 32import { VideoPathManager } from '@server/lib/video-path-manager'
33import { isVideoInPrivateDirectory } from '@server/lib/video-privacy'
33import { getServerActor } from '@server/models/application/application' 34import { getServerActor } from '@server/models/application/application'
34import { ModelCache } from '@server/models/model-cache' 35import { ModelCache } from '@server/models/model-cache'
35import { buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils' 36import { buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils'
@@ -1764,9 +1765,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1764 const playlist = this.VideoStreamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS) 1765 const playlist = this.VideoStreamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
1765 if (!playlist) return undefined 1766 if (!playlist) return undefined
1766 1767
1767 playlist.Video = this 1768 return playlist.withVideo(this)
1768
1769 return playlist
1770 } 1769 }
1771 1770
1772 setHLSPlaylist (playlist: MStreamingPlaylist) { 1771 setHLSPlaylist (playlist: MStreamingPlaylist) {
@@ -1868,16 +1867,39 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1868 return setAsUpdated('video', this.id, transaction) 1867 return setAsUpdated('video', this.id, transaction)
1869 } 1868 }
1870 1869
1871 requiresAuth (paramId: string) { 1870 // ---------------------------------------------------------------------------
1871
1872 requiresAuth (options: {
1873 urlParamId: string
1874 checkBlacklist: boolean
1875 }) {
1876 const { urlParamId, checkBlacklist } = options
1877
1878 if (this.privacy === VideoPrivacy.PRIVATE || this.privacy === VideoPrivacy.INTERNAL) {
1879 return true
1880 }
1881
1872 if (this.privacy === VideoPrivacy.UNLISTED) { 1882 if (this.privacy === VideoPrivacy.UNLISTED) {
1873 if (!isUUIDValid(paramId)) return true 1883 if (urlParamId && !isUUIDValid(urlParamId)) return true
1874 1884
1875 return false 1885 return false
1876 } 1886 }
1877 1887
1878 return this.privacy === VideoPrivacy.PRIVATE || this.privacy === VideoPrivacy.INTERNAL || !!this.VideoBlacklist 1888 if (checkBlacklist && this.VideoBlacklist) return true
1889
1890 if (this.privacy !== VideoPrivacy.PUBLIC) {
1891 throw new Error(`Unknown video privacy ${this.privacy} to know if the video requires auth`)
1892 }
1893
1894 return false
1879 } 1895 }
1880 1896
1897 hasPrivateStaticPath () {
1898 return isVideoInPrivateDirectory(this.privacy)
1899 }
1900
1901 // ---------------------------------------------------------------------------
1902
1881 async setNewState (newState: VideoState, isNewVideo: boolean, transaction: Transaction) { 1903 async setNewState (newState: VideoState, isNewVideo: boolean, transaction: Transaction) {
1882 if (this.state === newState) throw new Error('Cannot use same state ' + newState) 1904 if (this.state === newState) throw new Error('Cannot use same state ' + newState)
1883 1905
diff --git a/server/tests/api/object-storage/index.ts b/server/tests/api/object-storage/index.ts
index f319d6ef5..1f4489fa3 100644
--- a/server/tests/api/object-storage/index.ts
+++ b/server/tests/api/object-storage/index.ts
@@ -1,3 +1,4 @@
1export * from './live' 1export * from './live'
2export * from './video-imports' 2export * from './video-imports'
3export * from './video-static-file-privacy'
3export * from './videos' 4export * from './videos'
diff --git a/server/tests/api/object-storage/live.ts b/server/tests/api/object-storage/live.ts
index 77f3a8066..ad2b554b7 100644
--- a/server/tests/api/object-storage/live.ts
+++ b/server/tests/api/object-storage/live.ts
@@ -2,7 +2,7 @@
2 2
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { expectStartWith, testVideoResolutions } from '@server/tests/shared' 4import { expectStartWith, testVideoResolutions } from '@server/tests/shared'
5import { areObjectStorageTestsDisabled } from '@shared/core-utils' 5import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
6import { HttpStatusCode, LiveVideoCreate, VideoPrivacy } from '@shared/models' 6import { HttpStatusCode, LiveVideoCreate, VideoPrivacy } from '@shared/models'
7import { 7import {
8 createMultipleServers, 8 createMultipleServers,
@@ -46,7 +46,7 @@ async function checkFilesExist (servers: PeerTubeServer[], videoUUID: string, nu
46 expect(files).to.have.lengthOf(numberOfFiles) 46 expect(files).to.have.lengthOf(numberOfFiles)
47 47
48 for (const file of files) { 48 for (const file of files) {
49 expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) 49 expectStartWith(file.fileUrl, ObjectStorageCommand.getMockPlaylistBaseUrl())
50 50
51 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) 51 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
52 } 52 }
@@ -75,16 +75,16 @@ async function checkFilesCleanup (server: PeerTubeServer, videoUUID: string, res
75} 75}
76 76
77describe('Object storage for lives', function () { 77describe('Object storage for lives', function () {
78 if (areObjectStorageTestsDisabled()) return 78 if (areMockObjectStorageTestsDisabled()) return
79 79
80 let servers: PeerTubeServer[] 80 let servers: PeerTubeServer[]
81 81
82 before(async function () { 82 before(async function () {
83 this.timeout(120000) 83 this.timeout(120000)
84 84
85 await ObjectStorageCommand.prepareDefaultBuckets() 85 await ObjectStorageCommand.prepareDefaultMockBuckets()
86 86
87 servers = await createMultipleServers(2, ObjectStorageCommand.getDefaultConfig()) 87 servers = await createMultipleServers(2, ObjectStorageCommand.getDefaultMockConfig())
88 88
89 await setAccessTokensToServers(servers) 89 await setAccessTokensToServers(servers)
90 await setDefaultVideoChannel(servers) 90 await setDefaultVideoChannel(servers)
diff --git a/server/tests/api/object-storage/video-imports.ts b/server/tests/api/object-storage/video-imports.ts
index 90988ea9a..11c866411 100644
--- a/server/tests/api/object-storage/video-imports.ts
+++ b/server/tests/api/object-storage/video-imports.ts
@@ -2,7 +2,7 @@
2 2
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { expectStartWith, FIXTURE_URLS } from '@server/tests/shared' 4import { expectStartWith, FIXTURE_URLS } from '@server/tests/shared'
5import { areObjectStorageTestsDisabled } from '@shared/core-utils' 5import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
6import { HttpStatusCode, VideoPrivacy } from '@shared/models' 6import { HttpStatusCode, VideoPrivacy } from '@shared/models'
7import { 7import {
8 createSingleServer, 8 createSingleServer,
@@ -29,16 +29,16 @@ async function importVideo (server: PeerTubeServer) {
29} 29}
30 30
31describe('Object storage for video import', function () { 31describe('Object storage for video import', function () {
32 if (areObjectStorageTestsDisabled()) return 32 if (areMockObjectStorageTestsDisabled()) return
33 33
34 let server: PeerTubeServer 34 let server: PeerTubeServer
35 35
36 before(async function () { 36 before(async function () {
37 this.timeout(120000) 37 this.timeout(120000)
38 38
39 await ObjectStorageCommand.prepareDefaultBuckets() 39 await ObjectStorageCommand.prepareDefaultMockBuckets()
40 40
41 server = await createSingleServer(1, ObjectStorageCommand.getDefaultConfig()) 41 server = await createSingleServer(1, ObjectStorageCommand.getDefaultMockConfig())
42 42
43 await setAccessTokensToServers([ server ]) 43 await setAccessTokensToServers([ server ])
44 await setDefaultVideoChannel([ server ]) 44 await setDefaultVideoChannel([ server ])
@@ -64,7 +64,7 @@ describe('Object storage for video import', function () {
64 expect(video.streamingPlaylists).to.have.lengthOf(0) 64 expect(video.streamingPlaylists).to.have.lengthOf(0)
65 65
66 const fileUrl = video.files[0].fileUrl 66 const fileUrl = video.files[0].fileUrl
67 expectStartWith(fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) 67 expectStartWith(fileUrl, ObjectStorageCommand.getMockWebTorrentBaseUrl())
68 68
69 await makeRawRequest({ url: fileUrl, expectedStatus: HttpStatusCode.OK_200 }) 69 await makeRawRequest({ url: fileUrl, expectedStatus: HttpStatusCode.OK_200 })
70 }) 70 })
@@ -89,13 +89,13 @@ describe('Object storage for video import', function () {
89 expect(video.streamingPlaylists[0].files).to.have.lengthOf(5) 89 expect(video.streamingPlaylists[0].files).to.have.lengthOf(5)
90 90
91 for (const file of video.files) { 91 for (const file of video.files) {
92 expectStartWith(file.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) 92 expectStartWith(file.fileUrl, ObjectStorageCommand.getMockWebTorrentBaseUrl())
93 93
94 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) 94 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
95 } 95 }
96 96
97 for (const file of video.streamingPlaylists[0].files) { 97 for (const file of video.streamingPlaylists[0].files) {
98 expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) 98 expectStartWith(file.fileUrl, ObjectStorageCommand.getMockPlaylistBaseUrl())
99 99
100 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) 100 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
101 } 101 }
diff --git a/server/tests/api/object-storage/video-static-file-privacy.ts b/server/tests/api/object-storage/video-static-file-privacy.ts
new file mode 100644
index 000000000..981bbaa16
--- /dev/null
+++ b/server/tests/api/object-storage/video-static-file-privacy.ts
@@ -0,0 +1,336 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { basename } from 'path'
5import { expectStartWith } from '@server/tests/shared'
6import { areScalewayObjectStorageTestsDisabled, getAllFiles, getHLS } from '@shared/core-utils'
7import { HttpStatusCode, LiveVideo, VideoDetails, VideoPrivacy } from '@shared/models'
8import {
9 cleanupTests,
10 createSingleServer,
11 findExternalSavedVideo,
12 makeRawRequest,
13 ObjectStorageCommand,
14 PeerTubeServer,
15 sendRTMPStream,
16 setAccessTokensToServers,
17 setDefaultVideoChannel,
18 stopFfmpeg,
19 waitJobs
20} from '@shared/server-commands'
21
22describe('Object storage for video static file privacy', function () {
23 // We need real world object storage to check ACL
24 if (areScalewayObjectStorageTestsDisabled()) return
25
26 let server: PeerTubeServer
27 let userToken: string
28
29 before(async function () {
30 this.timeout(120000)
31
32 server = await createSingleServer(1, ObjectStorageCommand.getDefaultScalewayConfig(1))
33 await setAccessTokensToServers([ server ])
34 await setDefaultVideoChannel([ server ])
35
36 await server.config.enableMinimumTranscoding()
37
38 userToken = await server.users.generateUserAndToken('user1')
39 })
40
41 describe('VOD', function () {
42 let privateVideoUUID: string
43 let publicVideoUUID: string
44 let userPrivateVideoUUID: string
45
46 async function checkPrivateFiles (uuid: string) {
47 const video = await server.videos.getWithToken({ id: uuid })
48
49 for (const file of video.files) {
50 expectStartWith(file.fileUrl, server.url + '/object-storage-proxy/webseed/private/')
51
52 await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
53 }
54
55 for (const file of getAllFiles(video)) {
56 const internalFileUrl = await server.sql.getInternalFileUrl(file.id)
57 expectStartWith(internalFileUrl, ObjectStorageCommand.getScalewayBaseUrl())
58 await makeRawRequest({ url: internalFileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
59 }
60
61 const hls = getHLS(video)
62
63 if (hls) {
64 for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) {
65 expectStartWith(url, server.url + '/object-storage-proxy/streaming-playlists/hls/private/')
66 }
67
68 await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
69 await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
70
71 for (const file of hls.files) {
72 expectStartWith(file.fileUrl, server.url + '/object-storage-proxy/streaming-playlists/hls/private/')
73
74 await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
75 }
76 }
77 }
78
79 async function checkPublicFiles (uuid: string) {
80 const video = await server.videos.getWithToken({ id: uuid })
81
82 for (const file of getAllFiles(video)) {
83 expectStartWith(file.fileUrl, ObjectStorageCommand.getScalewayBaseUrl())
84
85 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
86 }
87
88 const hls = getHLS(video)
89
90 if (hls) {
91 expectStartWith(hls.playlistUrl, ObjectStorageCommand.getScalewayBaseUrl())
92 expectStartWith(hls.segmentsSha256Url, ObjectStorageCommand.getScalewayBaseUrl())
93
94 await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
95 await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
96 }
97 }
98
99 async function getSampleFileUrls (videoId: string) {
100 const video = await server.videos.getWithToken({ id: videoId })
101
102 return {
103 webTorrentFile: video.files[0].fileUrl,
104 hlsFile: getHLS(video).files[0].fileUrl
105 }
106 }
107
108 it('Should upload a private video and have appropriate object storage ACL', async function () {
109 this.timeout(60000)
110
111 {
112 const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
113 privateVideoUUID = uuid
114 }
115
116 {
117 const { uuid } = await server.videos.quickUpload({ name: 'user video', token: userToken, privacy: VideoPrivacy.PRIVATE })
118 userPrivateVideoUUID = uuid
119 }
120
121 await waitJobs([ server ])
122
123 await checkPrivateFiles(privateVideoUUID)
124 })
125
126 it('Should upload a public video and have appropriate object storage ACL', async function () {
127 this.timeout(60000)
128
129 const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.UNLISTED })
130 await waitJobs([ server ])
131
132 publicVideoUUID = uuid
133
134 await checkPublicFiles(publicVideoUUID)
135 })
136
137 it('Should not get files without appropriate OAuth token', async function () {
138 this.timeout(60000)
139
140 const { webTorrentFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
141
142 await makeRawRequest({ url: webTorrentFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
143 await makeRawRequest({ url: webTorrentFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
144
145 await makeRawRequest({ url: hlsFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
146 await makeRawRequest({ url: hlsFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
147 })
148
149 it('Should not get HLS file of another video', async function () {
150 this.timeout(60000)
151
152 const privateVideo = await server.videos.getWithToken({ id: privateVideoUUID })
153 const hlsFilename = basename(getHLS(privateVideo).files[0].fileUrl)
154
155 const badUrl = server.url + '/object-storage-proxy/streaming-playlists/hls/private/' + userPrivateVideoUUID + '/' + hlsFilename
156 const goodUrl = server.url + '/object-storage-proxy/streaming-playlists/hls/private/' + privateVideoUUID + '/' + hlsFilename
157
158 await makeRawRequest({ url: badUrl, token: server.accessToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
159 await makeRawRequest({ url: goodUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
160 })
161
162 it('Should correctly check OAuth or video file token', async function () {
163 this.timeout(60000)
164
165 const badVideoFileToken = await server.videoToken.getVideoFileToken({ token: userToken, videoId: userPrivateVideoUUID })
166 const goodVideoFileToken = await server.videoToken.getVideoFileToken({ videoId: privateVideoUUID })
167
168 const { webTorrentFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
169
170 for (const url of [ webTorrentFile, hlsFile ]) {
171 await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
172 await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
173 await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
174
175 await makeRawRequest({ url, query: { videoFileToken: badVideoFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
176 await makeRawRequest({ url, query: { videoFileToken: goodVideoFileToken }, expectedStatus: HttpStatusCode.OK_200 })
177 }
178 })
179
180 it('Should update public video to private', async function () {
181 this.timeout(60000)
182
183 await server.videos.update({ id: publicVideoUUID, attributes: { privacy: VideoPrivacy.INTERNAL } })
184
185 await checkPrivateFiles(publicVideoUUID)
186 })
187
188 it('Should update private video to public', async function () {
189 this.timeout(60000)
190
191 await server.videos.update({ id: publicVideoUUID, attributes: { privacy: VideoPrivacy.PUBLIC } })
192
193 await checkPublicFiles(publicVideoUUID)
194 })
195
196 after(async function () {
197 this.timeout(30000)
198
199 if (privateVideoUUID) await server.videos.remove({ id: privateVideoUUID })
200 if (publicVideoUUID) await server.videos.remove({ id: publicVideoUUID })
201 if (userPrivateVideoUUID) await server.videos.remove({ id: userPrivateVideoUUID })
202
203 await waitJobs([ server ])
204 })
205 })
206
207 describe('Live', function () {
208 let normalLiveId: string
209 let normalLive: LiveVideo
210
211 let permanentLiveId: string
212 let permanentLive: LiveVideo
213
214 let unrelatedFileToken: string
215
216 async function checkLiveFiles (live: LiveVideo, liveId: string) {
217 const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
218 await server.live.waitUntilPublished({ videoId: liveId })
219
220 const video = await server.videos.getWithToken({ id: liveId })
221 const fileToken = await server.videoToken.getVideoFileToken({ videoId: video.uuid })
222
223 const hls = video.streamingPlaylists[0]
224
225 for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) {
226 expectStartWith(url, server.url + '/object-storage-proxy/streaming-playlists/hls/private/')
227
228 await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
229 await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
230
231 await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
232 await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
233
234 await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
235 await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
236 await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
237 }
238
239 await stopFfmpeg(ffmpegCommand)
240 }
241
242 async function checkReplay (replay: VideoDetails) {
243 const fileToken = await server.videoToken.getVideoFileToken({ videoId: replay.uuid })
244
245 const hls = replay.streamingPlaylists[0]
246 expect(hls.files).to.not.have.lengthOf(0)
247
248 for (const file of hls.files) {
249 await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
250 await makeRawRequest({ url: file.fileUrl, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
251
252 await makeRawRequest({ url: file.fileUrl, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
253 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
254 await makeRawRequest({
255 url: file.fileUrl,
256 query: { videoFileToken: unrelatedFileToken },
257 expectedStatus: HttpStatusCode.FORBIDDEN_403
258 })
259 }
260
261 for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) {
262 expectStartWith(url, server.url + '/object-storage-proxy/streaming-playlists/hls/private/')
263
264 await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
265 await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
266
267 await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
268 await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
269 await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
270 }
271 }
272
273 before(async function () {
274 await server.config.enableMinimumTranscoding()
275
276 const { uuid } = await server.videos.quickUpload({ name: 'another video' })
277 unrelatedFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid })
278
279 await server.config.enableLive({
280 allowReplay: true,
281 transcoding: true,
282 resolutions: 'min'
283 })
284
285 {
286 const { video, live } = await server.live.quickCreate({ saveReplay: true, permanentLive: false, privacy: VideoPrivacy.PRIVATE })
287 normalLiveId = video.uuid
288 normalLive = live
289 }
290
291 {
292 const { video, live } = await server.live.quickCreate({ saveReplay: true, permanentLive: true, privacy: VideoPrivacy.PRIVATE })
293 permanentLiveId = video.uuid
294 permanentLive = live
295 }
296 })
297
298 it('Should create a private normal live and have a private static path', async function () {
299 this.timeout(240000)
300
301 await checkLiveFiles(normalLive, normalLiveId)
302 })
303
304 it('Should create a private permanent live and have a private static path', async function () {
305 this.timeout(240000)
306
307 await checkLiveFiles(permanentLive, permanentLiveId)
308 })
309
310 it('Should have created a replay of the normal live with a private static path', async function () {
311 this.timeout(240000)
312
313 await server.live.waitUntilReplacedByReplay({ videoId: normalLiveId })
314
315 const replay = await server.videos.getWithToken({ id: normalLiveId })
316 await checkReplay(replay)
317 })
318
319 it('Should have created a replay of the permanent live with a private static path', async function () {
320 this.timeout(240000)
321
322 await server.live.waitUntilWaiting({ videoId: permanentLiveId })
323 await waitJobs([ server ])
324
325 const live = await server.videos.getWithToken({ id: permanentLiveId })
326 const replayFromList = await findExternalSavedVideo(server, live)
327 const replay = await server.videos.getWithToken({ id: replayFromList.id })
328
329 await checkReplay(replay)
330 })
331 })
332
333 after(async function () {
334 await cleanupTests([ server ])
335 })
336})
diff --git a/server/tests/api/object-storage/videos.ts b/server/tests/api/object-storage/videos.ts
index 63f5179c7..af3db9334 100644
--- a/server/tests/api/object-storage/videos.ts
+++ b/server/tests/api/object-storage/videos.ts
@@ -11,7 +11,7 @@ import {
11 generateHighBitrateVideo, 11 generateHighBitrateVideo,
12 MockObjectStorage 12 MockObjectStorage
13} from '@server/tests/shared' 13} from '@server/tests/shared'
14import { areObjectStorageTestsDisabled } from '@shared/core-utils' 14import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
15import { HttpStatusCode, VideoDetails } from '@shared/models' 15import { HttpStatusCode, VideoDetails } from '@shared/models'
16import { 16import {
17 cleanupTests, 17 cleanupTests,
@@ -52,7 +52,7 @@ async function checkFiles (options: {
52 for (const file of video.files) { 52 for (const file of video.files) {
53 const baseUrl = baseMockUrl 53 const baseUrl = baseMockUrl
54 ? `${baseMockUrl}/${webtorrentBucket}/` 54 ? `${baseMockUrl}/${webtorrentBucket}/`
55 : `http://${webtorrentBucket}.${ObjectStorageCommand.getEndpointHost()}/` 55 : `http://${webtorrentBucket}.${ObjectStorageCommand.getMockEndpointHost()}/`
56 56
57 const prefix = webtorrentPrefix || '' 57 const prefix = webtorrentPrefix || ''
58 const start = baseUrl + prefix 58 const start = baseUrl + prefix
@@ -73,7 +73,7 @@ async function checkFiles (options: {
73 73
74 const baseUrl = baseMockUrl 74 const baseUrl = baseMockUrl
75 ? `${baseMockUrl}/${playlistBucket}/` 75 ? `${baseMockUrl}/${playlistBucket}/`
76 : `http://${playlistBucket}.${ObjectStorageCommand.getEndpointHost()}/` 76 : `http://${playlistBucket}.${ObjectStorageCommand.getMockEndpointHost()}/`
77 77
78 const prefix = playlistPrefix || '' 78 const prefix = playlistPrefix || ''
79 const start = baseUrl + prefix 79 const start = baseUrl + prefix
@@ -141,16 +141,16 @@ function runTestSuite (options: {
141 const port = await mockObjectStorage.initialize() 141 const port = await mockObjectStorage.initialize()
142 baseMockUrl = options.useMockBaseUrl ? `http://localhost:${port}` : undefined 142 baseMockUrl = options.useMockBaseUrl ? `http://localhost:${port}` : undefined
143 143
144 await ObjectStorageCommand.createBucket(options.playlistBucket) 144 await ObjectStorageCommand.createMockBucket(options.playlistBucket)
145 await ObjectStorageCommand.createBucket(options.webtorrentBucket) 145 await ObjectStorageCommand.createMockBucket(options.webtorrentBucket)
146 146
147 const config = { 147 const config = {
148 object_storage: { 148 object_storage: {
149 enabled: true, 149 enabled: true,
150 endpoint: 'http://' + ObjectStorageCommand.getEndpointHost(), 150 endpoint: 'http://' + ObjectStorageCommand.getMockEndpointHost(),
151 region: ObjectStorageCommand.getRegion(), 151 region: ObjectStorageCommand.getMockRegion(),
152 152
153 credentials: ObjectStorageCommand.getCredentialsConfig(), 153 credentials: ObjectStorageCommand.getMockCredentialsConfig(),
154 154
155 max_upload_part: options.maxUploadPart || '5MB', 155 max_upload_part: options.maxUploadPart || '5MB',
156 156
@@ -261,7 +261,7 @@ function runTestSuite (options: {
261} 261}
262 262
263describe('Object storage for videos', function () { 263describe('Object storage for videos', function () {
264 if (areObjectStorageTestsDisabled()) return 264 if (areMockObjectStorageTestsDisabled()) return
265 265
266 describe('Test config', function () { 266 describe('Test config', function () {
267 let server: PeerTubeServer 267 let server: PeerTubeServer
@@ -269,17 +269,17 @@ describe('Object storage for videos', function () {
269 const baseConfig = { 269 const baseConfig = {
270 object_storage: { 270 object_storage: {
271 enabled: true, 271 enabled: true,
272 endpoint: 'http://' + ObjectStorageCommand.getEndpointHost(), 272 endpoint: 'http://' + ObjectStorageCommand.getMockEndpointHost(),
273 region: ObjectStorageCommand.getRegion(), 273 region: ObjectStorageCommand.getMockRegion(),
274 274
275 credentials: ObjectStorageCommand.getCredentialsConfig(), 275 credentials: ObjectStorageCommand.getMockCredentialsConfig(),
276 276
277 streaming_playlists: { 277 streaming_playlists: {
278 bucket_name: ObjectStorageCommand.DEFAULT_PLAYLIST_BUCKET 278 bucket_name: ObjectStorageCommand.DEFAULT_PLAYLIST_MOCK_BUCKET
279 }, 279 },
280 280
281 videos: { 281 videos: {
282 bucket_name: ObjectStorageCommand.DEFAULT_WEBTORRENT_BUCKET 282 bucket_name: ObjectStorageCommand.DEFAULT_WEBTORRENT_MOCK_BUCKET
283 } 283 }
284 } 284 }
285 } 285 }
@@ -310,7 +310,7 @@ describe('Object storage for videos', function () {
310 it('Should fail with bad credentials', async function () { 310 it('Should fail with bad credentials', async function () {
311 this.timeout(60000) 311 this.timeout(60000)
312 312
313 await ObjectStorageCommand.prepareDefaultBuckets() 313 await ObjectStorageCommand.prepareDefaultMockBuckets()
314 314
315 const config = merge({}, baseConfig, { 315 const config = merge({}, baseConfig, {
316 object_storage: { 316 object_storage: {
@@ -334,7 +334,7 @@ describe('Object storage for videos', function () {
334 it('Should succeed with credentials from env', async function () { 334 it('Should succeed with credentials from env', async function () {
335 this.timeout(60000) 335 this.timeout(60000)
336 336
337 await ObjectStorageCommand.prepareDefaultBuckets() 337 await ObjectStorageCommand.prepareDefaultMockBuckets()
338 338
339 const config = merge({}, baseConfig, { 339 const config = merge({}, baseConfig, {
340 object_storage: { 340 object_storage: {
@@ -345,7 +345,7 @@ describe('Object storage for videos', function () {
345 } 345 }
346 }) 346 })
347 347
348 const goodCredentials = ObjectStorageCommand.getCredentialsConfig() 348 const goodCredentials = ObjectStorageCommand.getMockCredentialsConfig()
349 349
350 server = await createSingleServer(1, config, { 350 server = await createSingleServer(1, config, {
351 env: { 351 env: {
@@ -361,7 +361,7 @@ describe('Object storage for videos', function () {
361 await waitJobs([ server ], true) 361 await waitJobs([ server ], true)
362 const video = await server.videos.get({ id: uuid }) 362 const video = await server.videos.get({ id: uuid })
363 363
364 expectStartWith(video.files[0].fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) 364 expectStartWith(video.files[0].fileUrl, ObjectStorageCommand.getMockWebTorrentBaseUrl())
365 }) 365 })
366 366
367 after(async function () { 367 after(async function () {
diff --git a/server/tests/api/server/proxy.ts b/server/tests/api/server/proxy.ts
index a4151ebdd..3700b0746 100644
--- a/server/tests/api/server/proxy.ts
+++ b/server/tests/api/server/proxy.ts
@@ -2,7 +2,7 @@
2 2
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { expectNotStartWith, expectStartWith, FIXTURE_URLS, MockProxy } from '@server/tests/shared' 4import { expectNotStartWith, expectStartWith, FIXTURE_URLS, MockProxy } from '@server/tests/shared'
5import { areObjectStorageTestsDisabled } from '@shared/core-utils' 5import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
6import { HttpStatusCode, VideoPrivacy } from '@shared/models' 6import { HttpStatusCode, VideoPrivacy } from '@shared/models'
7import { 7import {
8 cleanupTests, 8 cleanupTests,
@@ -120,40 +120,40 @@ describe('Test proxy', function () {
120 }) 120 })
121 121
122 describe('Object storage', function () { 122 describe('Object storage', function () {
123 if (areObjectStorageTestsDisabled()) return 123 if (areMockObjectStorageTestsDisabled()) return
124 124
125 before(async function () { 125 before(async function () {
126 this.timeout(30000) 126 this.timeout(30000)
127 127
128 await ObjectStorageCommand.prepareDefaultBuckets() 128 await ObjectStorageCommand.prepareDefaultMockBuckets()
129 }) 129 })
130 130
131 it('Should succeed to upload to object storage with the appropriate proxy config', async function () { 131 it('Should succeed to upload to object storage with the appropriate proxy config', async function () {
132 this.timeout(120000) 132 this.timeout(120000)
133 133
134 await servers[0].kill() 134 await servers[0].kill()
135 await servers[0].run(ObjectStorageCommand.getDefaultConfig(), { env: goodEnv }) 135 await servers[0].run(ObjectStorageCommand.getDefaultMockConfig(), { env: goodEnv })
136 136
137 const { uuid } = await servers[0].videos.quickUpload({ name: 'video' }) 137 const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
138 await waitJobs(servers) 138 await waitJobs(servers)
139 139
140 const video = await servers[0].videos.get({ id: uuid }) 140 const video = await servers[0].videos.get({ id: uuid })
141 141
142 expectStartWith(video.files[0].fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) 142 expectStartWith(video.files[0].fileUrl, ObjectStorageCommand.getMockWebTorrentBaseUrl())
143 }) 143 })
144 144
145 it('Should fail to upload to object storage with a wrong proxy config', async function () { 145 it('Should fail to upload to object storage with a wrong proxy config', async function () {
146 this.timeout(120000) 146 this.timeout(120000)
147 147
148 await servers[0].kill() 148 await servers[0].kill()
149 await servers[0].run(ObjectStorageCommand.getDefaultConfig(), { env: badEnv }) 149 await servers[0].run(ObjectStorageCommand.getDefaultMockConfig(), { env: badEnv })
150 150
151 const { uuid } = await servers[0].videos.quickUpload({ name: 'video' }) 151 const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
152 await waitJobs(servers) 152 await waitJobs(servers)
153 153
154 const video = await servers[0].videos.get({ id: uuid }) 154 const video = await servers[0].videos.get({ id: uuid })
155 155
156 expectNotStartWith(video.files[0].fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) 156 expectNotStartWith(video.files[0].fileUrl, ObjectStorageCommand.getMockWebTorrentBaseUrl())
157 }) 157 })
158 }) 158 })
159 159
diff --git a/server/tests/api/transcoding/create-transcoding.ts b/server/tests/api/transcoding/create-transcoding.ts
index 372f5332a..85389a949 100644
--- a/server/tests/api/transcoding/create-transcoding.ts
+++ b/server/tests/api/transcoding/create-transcoding.ts
@@ -2,7 +2,7 @@
2 2
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { checkResolutionsInMasterPlaylist, expectStartWith } from '@server/tests/shared' 4import { checkResolutionsInMasterPlaylist, expectStartWith } from '@server/tests/shared'
5import { areObjectStorageTestsDisabled } from '@shared/core-utils' 5import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
6import { HttpStatusCode, VideoDetails } from '@shared/models' 6import { HttpStatusCode, VideoDetails } from '@shared/models'
7import { 7import {
8 cleanupTests, 8 cleanupTests,
@@ -19,7 +19,7 @@ import {
19 19
20async function checkFilesInObjectStorage (video: VideoDetails) { 20async function checkFilesInObjectStorage (video: VideoDetails) {
21 for (const file of video.files) { 21 for (const file of video.files) {
22 expectStartWith(file.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) 22 expectStartWith(file.fileUrl, ObjectStorageCommand.getMockWebTorrentBaseUrl())
23 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) 23 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
24 } 24 }
25 25
@@ -27,14 +27,14 @@ async function checkFilesInObjectStorage (video: VideoDetails) {
27 27
28 const hlsPlaylist = video.streamingPlaylists[0] 28 const hlsPlaylist = video.streamingPlaylists[0]
29 for (const file of hlsPlaylist.files) { 29 for (const file of hlsPlaylist.files) {
30 expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) 30 expectStartWith(file.fileUrl, ObjectStorageCommand.getMockPlaylistBaseUrl())
31 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) 31 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
32 } 32 }
33 33
34 expectStartWith(hlsPlaylist.playlistUrl, ObjectStorageCommand.getPlaylistBaseUrl()) 34 expectStartWith(hlsPlaylist.playlistUrl, ObjectStorageCommand.getMockPlaylistBaseUrl())
35 await makeRawRequest({ url: hlsPlaylist.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) 35 await makeRawRequest({ url: hlsPlaylist.playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
36 36
37 expectStartWith(hlsPlaylist.segmentsSha256Url, ObjectStorageCommand.getPlaylistBaseUrl()) 37 expectStartWith(hlsPlaylist.segmentsSha256Url, ObjectStorageCommand.getMockPlaylistBaseUrl())
38 await makeRawRequest({ url: hlsPlaylist.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) 38 await makeRawRequest({ url: hlsPlaylist.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
39} 39}
40 40
@@ -49,7 +49,7 @@ function runTests (objectStorage: boolean) {
49 this.timeout(120000) 49 this.timeout(120000)
50 50
51 const config = objectStorage 51 const config = objectStorage
52 ? ObjectStorageCommand.getDefaultConfig() 52 ? ObjectStorageCommand.getDefaultMockConfig()
53 : {} 53 : {}
54 54
55 // Run server 2 to have transcoding enabled 55 // Run server 2 to have transcoding enabled
@@ -60,7 +60,7 @@ function runTests (objectStorage: boolean) {
60 60
61 await doubleFollow(servers[0], servers[1]) 61 await doubleFollow(servers[0], servers[1])
62 62
63 if (objectStorage) await ObjectStorageCommand.prepareDefaultBuckets() 63 if (objectStorage) await ObjectStorageCommand.prepareDefaultMockBuckets()
64 64
65 const { shortUUID } = await servers[0].videos.quickUpload({ name: 'video' }) 65 const { shortUUID } = await servers[0].videos.quickUpload({ name: 'video' })
66 videoUUID = shortUUID 66 videoUUID = shortUUID
@@ -256,7 +256,7 @@ describe('Test create transcoding jobs from API', function () {
256 }) 256 })
257 257
258 describe('On object storage', function () { 258 describe('On object storage', function () {
259 if (areObjectStorageTestsDisabled()) return 259 if (areMockObjectStorageTestsDisabled()) return
260 260
261 runTests(true) 261 runTests(true)
262 }) 262 })
diff --git a/server/tests/api/transcoding/hls.ts b/server/tests/api/transcoding/hls.ts
index 7b5492cd4..84a53c0bd 100644
--- a/server/tests/api/transcoding/hls.ts
+++ b/server/tests/api/transcoding/hls.ts
@@ -2,7 +2,7 @@
2 2
3import { join } from 'path' 3import { join } from 'path'
4import { checkDirectoryIsEmpty, checkTmpIsEmpty, completeCheckHlsPlaylist } from '@server/tests/shared' 4import { checkDirectoryIsEmpty, checkTmpIsEmpty, completeCheckHlsPlaylist } from '@server/tests/shared'
5import { areObjectStorageTestsDisabled } from '@shared/core-utils' 5import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
6import { HttpStatusCode } from '@shared/models' 6import { HttpStatusCode } from '@shared/models'
7import { 7import {
8 cleanupTests, 8 cleanupTests,
@@ -150,19 +150,19 @@ describe('Test HLS videos', function () {
150 }) 150 })
151 151
152 describe('With object storage enabled', function () { 152 describe('With object storage enabled', function () {
153 if (areObjectStorageTestsDisabled()) return 153 if (areMockObjectStorageTestsDisabled()) return
154 154
155 before(async function () { 155 before(async function () {
156 this.timeout(120000) 156 this.timeout(120000)
157 157
158 const configOverride = ObjectStorageCommand.getDefaultConfig() 158 const configOverride = ObjectStorageCommand.getDefaultMockConfig()
159 await ObjectStorageCommand.prepareDefaultBuckets() 159 await ObjectStorageCommand.prepareDefaultMockBuckets()
160 160
161 await servers[0].kill() 161 await servers[0].kill()
162 await servers[0].run(configOverride) 162 await servers[0].run(configOverride)
163 }) 163 })
164 164
165 runTestSuite(true, ObjectStorageCommand.getPlaylistBaseUrl()) 165 runTestSuite(true, ObjectStorageCommand.getMockPlaylistBaseUrl())
166 }) 166 })
167 167
168 after(async function () { 168 after(async function () {
diff --git a/server/tests/api/transcoding/update-while-transcoding.ts b/server/tests/api/transcoding/update-while-transcoding.ts
index 5ca923392..8e32ea069 100644
--- a/server/tests/api/transcoding/update-while-transcoding.ts
+++ b/server/tests/api/transcoding/update-while-transcoding.ts
@@ -1,7 +1,7 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import { completeCheckHlsPlaylist } from '@server/tests/shared' 3import { completeCheckHlsPlaylist } from '@server/tests/shared'
4import { areObjectStorageTestsDisabled, wait } from '@shared/core-utils' 4import { areMockObjectStorageTestsDisabled, wait } from '@shared/core-utils'
5import { VideoPrivacy } from '@shared/models' 5import { VideoPrivacy } from '@shared/models'
6import { 6import {
7 cleanupTests, 7 cleanupTests,
@@ -130,19 +130,19 @@ describe('Test update video privacy while transcoding', function () {
130 }) 130 })
131 131
132 describe('With object storage enabled', function () { 132 describe('With object storage enabled', function () {
133 if (areObjectStorageTestsDisabled()) return 133 if (areMockObjectStorageTestsDisabled()) return
134 134
135 before(async function () { 135 before(async function () {
136 this.timeout(120000) 136 this.timeout(120000)
137 137
138 const configOverride = ObjectStorageCommand.getDefaultConfig() 138 const configOverride = ObjectStorageCommand.getDefaultMockConfig()
139 await ObjectStorageCommand.prepareDefaultBuckets() 139 await ObjectStorageCommand.prepareDefaultMockBuckets()
140 140
141 await servers[0].kill() 141 await servers[0].kill()
142 await servers[0].run(configOverride) 142 await servers[0].run(configOverride)
143 }) 143 })
144 144
145 runTestSuite(true, ObjectStorageCommand.getPlaylistBaseUrl()) 145 runTestSuite(true, ObjectStorageCommand.getMockPlaylistBaseUrl())
146 }) 146 })
147 147
148 after(async function () { 148 after(async function () {
diff --git a/server/tests/api/transcoding/video-studio.ts b/server/tests/api/transcoding/video-studio.ts
index 9613111b5..ab08e8fb6 100644
--- a/server/tests/api/transcoding/video-studio.ts
+++ b/server/tests/api/transcoding/video-studio.ts
@@ -1,6 +1,6 @@
1import { expect } from 'chai' 1import { expect } from 'chai'
2import { expectStartWith } from '@server/tests/shared' 2import { expectStartWith } from '@server/tests/shared'
3import { areObjectStorageTestsDisabled, getAllFiles } from '@shared/core-utils' 3import { areMockObjectStorageTestsDisabled, getAllFiles } from '@shared/core-utils'
4import { VideoStudioTask } from '@shared/models' 4import { VideoStudioTask } from '@shared/models'
5import { 5import {
6 cleanupTests, 6 cleanupTests,
@@ -315,13 +315,13 @@ describe('Test video studio', function () {
315 }) 315 })
316 316
317 describe('Object storage video edition', function () { 317 describe('Object storage video edition', function () {
318 if (areObjectStorageTestsDisabled()) return 318 if (areMockObjectStorageTestsDisabled()) return
319 319
320 before(async function () { 320 before(async function () {
321 await ObjectStorageCommand.prepareDefaultBuckets() 321 await ObjectStorageCommand.prepareDefaultMockBuckets()
322 322
323 await servers[0].kill() 323 await servers[0].kill()
324 await servers[0].run(ObjectStorageCommand.getDefaultConfig()) 324 await servers[0].run(ObjectStorageCommand.getDefaultMockConfig())
325 325
326 await servers[0].config.enableMinimumTranscoding() 326 await servers[0].config.enableMinimumTranscoding()
327 }) 327 })
@@ -344,11 +344,11 @@ describe('Test video studio', function () {
344 } 344 }
345 345
346 for (const webtorrentFile of video.files) { 346 for (const webtorrentFile of video.files) {
347 expectStartWith(webtorrentFile.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) 347 expectStartWith(webtorrentFile.fileUrl, ObjectStorageCommand.getMockWebTorrentBaseUrl())
348 } 348 }
349 349
350 for (const hlsFile of video.streamingPlaylists[0].files) { 350 for (const hlsFile of video.streamingPlaylists[0].files) {
351 expectStartWith(hlsFile.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) 351 expectStartWith(hlsFile.fileUrl, ObjectStorageCommand.getMockPlaylistBaseUrl())
352 } 352 }
353 353
354 await checkDuration(server, 9) 354 await checkDuration(server, 9)
diff --git a/server/tests/api/videos/video-static-file-privacy.ts b/server/tests/api/videos/video-static-file-privacy.ts
index e38fdec6e..bdbe85127 100644
--- a/server/tests/api/videos/video-static-file-privacy.ts
+++ b/server/tests/api/videos/video-static-file-privacy.ts
@@ -37,7 +37,7 @@ describe('Test video static file privacy', function () {
37 37
38 function runSuite () { 38 function runSuite () {
39 39
40 async function checkPrivateWebTorrentFiles (uuid: string) { 40 async function checkPrivateFiles (uuid: string) {
41 const video = await server.videos.getWithToken({ id: uuid }) 41 const video = await server.videos.getWithToken({ id: uuid })
42 42
43 for (const file of video.files) { 43 for (const file of video.files) {
@@ -63,7 +63,7 @@ describe('Test video static file privacy', function () {
63 } 63 }
64 } 64 }
65 65
66 async function checkPublicWebTorrentFiles (uuid: string) { 66 async function checkPublicFiles (uuid: string) {
67 const video = await server.videos.get({ id: uuid }) 67 const video = await server.videos.get({ id: uuid })
68 68
69 for (const file of getAllFiles(video)) { 69 for (const file of getAllFiles(video)) {
@@ -98,7 +98,7 @@ describe('Test video static file privacy', function () {
98 const { uuid } = await server.videos.quickUpload({ name: 'video', privacy }) 98 const { uuid } = await server.videos.quickUpload({ name: 'video', privacy })
99 await waitJobs([ server ]) 99 await waitJobs([ server ])
100 100
101 await checkPrivateWebTorrentFiles(uuid) 101 await checkPrivateFiles(uuid)
102 } 102 }
103 }) 103 })
104 104
@@ -112,7 +112,7 @@ describe('Test video static file privacy', function () {
112 await server.videos.update({ id: uuid, attributes: { privacy } }) 112 await server.videos.update({ id: uuid, attributes: { privacy } })
113 await waitJobs([ server ]) 113 await waitJobs([ server ])
114 114
115 await checkPrivateWebTorrentFiles(uuid) 115 await checkPrivateFiles(uuid)
116 } 116 }
117 }) 117 })
118 118
@@ -125,7 +125,7 @@ describe('Test video static file privacy', function () {
125 await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } }) 125 await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } })
126 await waitJobs([ server ]) 126 await waitJobs([ server ])
127 127
128 await checkPublicWebTorrentFiles(uuid) 128 await checkPublicFiles(uuid)
129 }) 129 })
130 130
131 it('Should upload an internal video and update it to public to have a public static path', async function () { 131 it('Should upload an internal video and update it to public to have a public static path', async function () {
@@ -137,7 +137,7 @@ describe('Test video static file privacy', function () {
137 await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } }) 137 await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
138 await waitJobs([ server ]) 138 await waitJobs([ server ])
139 139
140 await checkPublicWebTorrentFiles(uuid) 140 await checkPublicFiles(uuid)
141 }) 141 })
142 142
143 it('Should upload an internal video and schedule a public publish', async function () { 143 it('Should upload an internal video and schedule a public publish', async function () {
@@ -160,7 +160,7 @@ describe('Test video static file privacy', function () {
160 160
161 await waitJobs([ server ]) 161 await waitJobs([ server ])
162 162
163 await checkPublicWebTorrentFiles(uuid) 163 await checkPublicFiles(uuid)
164 }) 164 })
165 } 165 }
166 166
diff --git a/server/tests/cli/create-import-video-file-job.ts b/server/tests/cli/create-import-video-file-job.ts
index a4aa5f699..43f53035b 100644
--- a/server/tests/cli/create-import-video-file-job.ts
+++ b/server/tests/cli/create-import-video-file-job.ts
@@ -1,7 +1,7 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { areObjectStorageTestsDisabled } from '@shared/core-utils' 4import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
5import { HttpStatusCode, VideoDetails, VideoFile, VideoInclude } from '@shared/models' 5import { HttpStatusCode, VideoDetails, VideoFile, VideoInclude } from '@shared/models'
6import { 6import {
7 cleanupTests, 7 cleanupTests,
@@ -27,7 +27,7 @@ function assertVideoProperties (video: VideoFile, resolution: number, extname: s
27 27
28async function checkFiles (video: VideoDetails, objectStorage: boolean) { 28async function checkFiles (video: VideoDetails, objectStorage: boolean) {
29 for (const file of video.files) { 29 for (const file of video.files) {
30 if (objectStorage) expectStartWith(file.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) 30 if (objectStorage) expectStartWith(file.fileUrl, ObjectStorageCommand.getMockWebTorrentBaseUrl())
31 31
32 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) 32 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
33 } 33 }
@@ -43,7 +43,7 @@ function runTests (objectStorage: boolean) {
43 this.timeout(90000) 43 this.timeout(90000)
44 44
45 const config = objectStorage 45 const config = objectStorage
46 ? ObjectStorageCommand.getDefaultConfig() 46 ? ObjectStorageCommand.getDefaultMockConfig()
47 : {} 47 : {}
48 48
49 // Run server 2 to have transcoding enabled 49 // Run server 2 to have transcoding enabled
@@ -52,7 +52,7 @@ function runTests (objectStorage: boolean) {
52 52
53 await doubleFollow(servers[0], servers[1]) 53 await doubleFollow(servers[0], servers[1])
54 54
55 if (objectStorage) await ObjectStorageCommand.prepareDefaultBuckets() 55 if (objectStorage) await ObjectStorageCommand.prepareDefaultMockBuckets()
56 56
57 // Upload two videos for our needs 57 // Upload two videos for our needs
58 { 58 {
@@ -157,7 +157,7 @@ describe('Test create import video jobs', function () {
157 }) 157 })
158 158
159 describe('On object storage', function () { 159 describe('On object storage', function () {
160 if (areObjectStorageTestsDisabled()) return 160 if (areMockObjectStorageTestsDisabled()) return
161 161
162 runTests(true) 162 runTests(true)
163 }) 163 })
diff --git a/server/tests/cli/create-move-video-storage-job.ts b/server/tests/cli/create-move-video-storage-job.ts
index ecdd75b76..c357f501b 100644
--- a/server/tests/cli/create-move-video-storage-job.ts
+++ b/server/tests/cli/create-move-video-storage-job.ts
@@ -1,6 +1,6 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import { areObjectStorageTestsDisabled } from '@shared/core-utils' 3import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
4import { HttpStatusCode, VideoDetails } from '@shared/models' 4import { HttpStatusCode, VideoDetails } from '@shared/models'
5import { 5import {
6 cleanupTests, 6 cleanupTests,
@@ -17,7 +17,7 @@ import { expectStartWith } from '../shared'
17async function checkFiles (origin: PeerTubeServer, video: VideoDetails, inObjectStorage: boolean) { 17async function checkFiles (origin: PeerTubeServer, video: VideoDetails, inObjectStorage: boolean) {
18 for (const file of video.files) { 18 for (const file of video.files) {
19 const start = inObjectStorage 19 const start = inObjectStorage
20 ? ObjectStorageCommand.getWebTorrentBaseUrl() 20 ? ObjectStorageCommand.getMockWebTorrentBaseUrl()
21 : origin.url 21 : origin.url
22 22
23 expectStartWith(file.fileUrl, start) 23 expectStartWith(file.fileUrl, start)
@@ -26,7 +26,7 @@ async function checkFiles (origin: PeerTubeServer, video: VideoDetails, inObject
26 } 26 }
27 27
28 const start = inObjectStorage 28 const start = inObjectStorage
29 ? ObjectStorageCommand.getPlaylistBaseUrl() 29 ? ObjectStorageCommand.getMockPlaylistBaseUrl()
30 : origin.url 30 : origin.url
31 31
32 const hls = video.streamingPlaylists[0] 32 const hls = video.streamingPlaylists[0]
@@ -41,7 +41,7 @@ async function checkFiles (origin: PeerTubeServer, video: VideoDetails, inObject
41} 41}
42 42
43describe('Test create move video storage job', function () { 43describe('Test create move video storage job', function () {
44 if (areObjectStorageTestsDisabled()) return 44 if (areMockObjectStorageTestsDisabled()) return
45 45
46 let servers: PeerTubeServer[] = [] 46 let servers: PeerTubeServer[] = []
47 const uuids: string[] = [] 47 const uuids: string[] = []
@@ -55,7 +55,7 @@ describe('Test create move video storage job', function () {
55 55
56 await doubleFollow(servers[0], servers[1]) 56 await doubleFollow(servers[0], servers[1])
57 57
58 await ObjectStorageCommand.prepareDefaultBuckets() 58 await ObjectStorageCommand.prepareDefaultMockBuckets()
59 59
60 await servers[0].config.enableTranscoding() 60 await servers[0].config.enableTranscoding()
61 61
@@ -67,14 +67,14 @@ describe('Test create move video storage job', function () {
67 await waitJobs(servers) 67 await waitJobs(servers)
68 68
69 await servers[0].kill() 69 await servers[0].kill()
70 await servers[0].run(ObjectStorageCommand.getDefaultConfig()) 70 await servers[0].run(ObjectStorageCommand.getDefaultMockConfig())
71 }) 71 })
72 72
73 it('Should move only one file', async function () { 73 it('Should move only one file', async function () {
74 this.timeout(120000) 74 this.timeout(120000)
75 75
76 const command = `npm run create-move-video-storage-job -- --to-object-storage -v ${uuids[1]}` 76 const command = `npm run create-move-video-storage-job -- --to-object-storage -v ${uuids[1]}`
77 await servers[0].cli.execWithEnv(command, ObjectStorageCommand.getDefaultConfig()) 77 await servers[0].cli.execWithEnv(command, ObjectStorageCommand.getDefaultMockConfig())
78 await waitJobs(servers) 78 await waitJobs(servers)
79 79
80 for (const server of servers) { 80 for (const server of servers) {
@@ -94,7 +94,7 @@ describe('Test create move video storage job', function () {
94 this.timeout(120000) 94 this.timeout(120000)
95 95
96 const command = `npm run create-move-video-storage-job -- --to-object-storage --all-videos` 96 const command = `npm run create-move-video-storage-job -- --to-object-storage --all-videos`
97 await servers[0].cli.execWithEnv(command, ObjectStorageCommand.getDefaultConfig()) 97 await servers[0].cli.execWithEnv(command, ObjectStorageCommand.getDefaultMockConfig())
98 await waitJobs(servers) 98 await waitJobs(servers)
99 99
100 for (const server of servers) { 100 for (const server of servers) {
diff --git a/server/tests/cli/create-transcoding-job.ts b/server/tests/cli/create-transcoding-job.ts
index 51bf04a80..38b737829 100644
--- a/server/tests/cli/create-transcoding-job.ts
+++ b/server/tests/cli/create-transcoding-job.ts
@@ -1,7 +1,7 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { areObjectStorageTestsDisabled } from '@shared/core-utils' 4import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
5import { HttpStatusCode, VideoFile } from '@shared/models' 5import { HttpStatusCode, VideoFile } from '@shared/models'
6import { 6import {
7 cleanupTests, 7 cleanupTests,
@@ -18,8 +18,8 @@ import { checkResolutionsInMasterPlaylist, expectStartWith } from '../shared'
18async function checkFilesInObjectStorage (files: VideoFile[], type: 'webtorrent' | 'playlist') { 18async function checkFilesInObjectStorage (files: VideoFile[], type: 'webtorrent' | 'playlist') {
19 for (const file of files) { 19 for (const file of files) {
20 const shouldStartWith = type === 'webtorrent' 20 const shouldStartWith = type === 'webtorrent'
21 ? ObjectStorageCommand.getWebTorrentBaseUrl() 21 ? ObjectStorageCommand.getMockWebTorrentBaseUrl()
22 : ObjectStorageCommand.getPlaylistBaseUrl() 22 : ObjectStorageCommand.getMockPlaylistBaseUrl()
23 23
24 expectStartWith(file.fileUrl, shouldStartWith) 24 expectStartWith(file.fileUrl, shouldStartWith)
25 25
@@ -36,7 +36,7 @@ function runTests (objectStorage: boolean) {
36 this.timeout(120000) 36 this.timeout(120000)
37 37
38 const config = objectStorage 38 const config = objectStorage
39 ? ObjectStorageCommand.getDefaultConfig() 39 ? ObjectStorageCommand.getDefaultMockConfig()
40 : {} 40 : {}
41 41
42 // Run server 2 to have transcoding enabled 42 // Run server 2 to have transcoding enabled
@@ -47,7 +47,7 @@ function runTests (objectStorage: boolean) {
47 47
48 await doubleFollow(servers[0], servers[1]) 48 await doubleFollow(servers[0], servers[1])
49 49
50 if (objectStorage) await ObjectStorageCommand.prepareDefaultBuckets() 50 if (objectStorage) await ObjectStorageCommand.prepareDefaultMockBuckets()
51 51
52 for (let i = 1; i <= 5; i++) { 52 for (let i = 1; i <= 5; i++) {
53 const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'video' + i } }) 53 const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'video' + i } })
@@ -255,7 +255,7 @@ describe('Test create transcoding jobs', function () {
255 }) 255 })
256 256
257 describe('On object storage', function () { 257 describe('On object storage', function () {
258 if (areObjectStorageTestsDisabled()) return 258 if (areMockObjectStorageTestsDisabled()) return
259 259
260 runTests(true) 260 runTests(true)
261 }) 261 })
diff --git a/server/tests/shared/live.ts b/server/tests/shared/live.ts
index da3691711..78e29f575 100644
--- a/server/tests/shared/live.ts
+++ b/server/tests/shared/live.ts
@@ -50,7 +50,7 @@ async function testVideoResolutions (options: {
50 }) 50 })
51 51
52 if (objectStorage) { 52 if (objectStorage) {
53 expect(hlsPlaylist.playlistUrl).to.contain(ObjectStorageCommand.getPlaylistBaseUrl()) 53 expect(hlsPlaylist.playlistUrl).to.contain(ObjectStorageCommand.getMockPlaylistBaseUrl())
54 } 54 }
55 55
56 for (let i = 0; i < resolutions.length; i++) { 56 for (let i = 0; i < resolutions.length; i++) {
@@ -65,11 +65,11 @@ async function testVideoResolutions (options: {
65 }) 65 })
66 66
67 const baseUrl = objectStorage 67 const baseUrl = objectStorage
68 ? ObjectStorageCommand.getPlaylistBaseUrl() + 'hls' 68 ? ObjectStorageCommand.getMockPlaylistBaseUrl() + 'hls'
69 : originServer.url + '/static/streaming-playlists/hls' 69 : originServer.url + '/static/streaming-playlists/hls'
70 70
71 if (objectStorage) { 71 if (objectStorage) {
72 expect(hlsPlaylist.segmentsSha256Url).to.contain(ObjectStorageCommand.getPlaylistBaseUrl()) 72 expect(hlsPlaylist.segmentsSha256Url).to.contain(ObjectStorageCommand.getMockPlaylistBaseUrl())
73 } 73 }
74 74
75 const subPlaylist = await originServer.streamingPlaylists.get({ 75 const subPlaylist = await originServer.streamingPlaylists.get({
diff --git a/server/tests/shared/mock-servers/mock-object-storage.ts b/server/tests/shared/mock-servers/mock-object-storage.ts
index 99d68e014..8c325bf11 100644
--- a/server/tests/shared/mock-servers/mock-object-storage.ts
+++ b/server/tests/shared/mock-servers/mock-object-storage.ts
@@ -12,7 +12,7 @@ export class MockObjectStorage {
12 const app = express() 12 const app = express()
13 13
14 app.get('/:bucketName/:path(*)', (req: express.Request, res: express.Response, next: express.NextFunction) => { 14 app.get('/:bucketName/:path(*)', (req: express.Request, res: express.Response, next: express.NextFunction) => {
15 const url = `http://${req.params.bucketName}.${ObjectStorageCommand.getEndpointHost()}/${req.params.path}` 15 const url = `http://${req.params.bucketName}.${ObjectStorageCommand.getMockEndpointHost()}/${req.params.path}`
16 16
17 if (process.env.DEBUG) { 17 if (process.env.DEBUG) {
18 console.log('Receiving request on mocked server %s.', req.url) 18 console.log('Receiving request on mocked server %s.', req.url)
diff --git a/server/types/express.d.ts b/server/types/express.d.ts
index 27d60da72..3738ffc47 100644
--- a/server/types/express.d.ts
+++ b/server/types/express.d.ts
@@ -97,7 +97,7 @@ declare module 'express' {
97 97
98 title?: string 98 title?: string
99 status?: number 99 status?: number
100 type?: ServerErrorCode 100 type?: ServerErrorCode | string
101 instance?: string 101 instance?: string
102 102
103 data?: PeerTubeProblemDocumentData 103 data?: PeerTubeProblemDocumentData
diff --git a/shared/core-utils/common/env.ts b/shared/core-utils/common/env.ts
index 38c96b152..973f895d4 100644
--- a/shared/core-utils/common/env.ts
+++ b/shared/core-utils/common/env.ts
@@ -14,7 +14,7 @@ function areHttpImportTestsDisabled () {
14 return disabled 14 return disabled
15} 15}
16 16
17function areObjectStorageTestsDisabled () { 17function areMockObjectStorageTestsDisabled () {
18 const disabled = process.env.ENABLE_OBJECT_STORAGE_TESTS !== 'true' 18 const disabled = process.env.ENABLE_OBJECT_STORAGE_TESTS !== 'true'
19 19
20 if (disabled) console.log('ENABLE_OBJECT_STORAGE_TESTS env is not set to "true" so object storage tests are disabled') 20 if (disabled) console.log('ENABLE_OBJECT_STORAGE_TESTS env is not set to "true" so object storage tests are disabled')
@@ -22,9 +22,25 @@ function areObjectStorageTestsDisabled () {
22 return disabled 22 return disabled
23} 23}
24 24
25function areScalewayObjectStorageTestsDisabled () {
26 if (areMockObjectStorageTestsDisabled()) return true
27
28 const enabled = process.env.OBJECT_STORAGE_SCALEWAY_KEY_ID && process.env.OBJECT_STORAGE_SCALEWAY_ACCESS_KEY
29 if (!enabled) {
30 console.log(
31 'OBJECT_STORAGE_SCALEWAY_KEY_ID and/or OBJECT_STORAGE_SCALEWAY_ACCESS_KEY are not set, so scaleway object storage tests are disabled'
32 )
33
34 return true
35 }
36
37 return false
38}
39
25export { 40export {
26 parallelTests, 41 parallelTests,
27 isGithubCI, 42 isGithubCI,
28 areHttpImportTestsDisabled, 43 areHttpImportTestsDisabled,
29 areObjectStorageTestsDisabled 44 areMockObjectStorageTestsDisabled,
45 areScalewayObjectStorageTestsDisabled
30} 46}
diff --git a/shared/core-utils/videos/privacy.ts b/shared/core-utils/videos/common.ts
index f33487b49..2c6efdb7f 100644
--- a/shared/core-utils/videos/privacy.ts
+++ b/shared/core-utils/videos/common.ts
@@ -1,5 +1,6 @@
1import { VideoDetails } from '../../models/videos/video.model' 1import { VideoStreamingPlaylistType } from '@shared/models'
2import { VideoPrivacy } from '../../models/videos/video-privacy.enum' 2import { VideoPrivacy } from '../../models/videos/video-privacy.enum'
3import { VideoDetails } from '../../models/videos/video.model'
3 4
4function getAllPrivacies () { 5function getAllPrivacies () {
5 return [ VideoPrivacy.PUBLIC, VideoPrivacy.INTERNAL, VideoPrivacy.PRIVATE, VideoPrivacy.UNLISTED ] 6 return [ VideoPrivacy.PUBLIC, VideoPrivacy.INTERNAL, VideoPrivacy.PRIVATE, VideoPrivacy.UNLISTED ]
@@ -8,14 +9,18 @@ function getAllPrivacies () {
8function getAllFiles (video: Partial<Pick<VideoDetails, 'files' | 'streamingPlaylists'>>) { 9function getAllFiles (video: Partial<Pick<VideoDetails, 'files' | 'streamingPlaylists'>>) {
9 const files = video.files 10 const files = video.files
10 11
11 if (video.streamingPlaylists[0]) { 12 const hls = getHLS(video)
12 return files.concat(video.streamingPlaylists[0].files) 13 if (hls) return files.concat(hls.files)
13 }
14 14
15 return files 15 return files
16} 16}
17 17
18function getHLS (video: Partial<Pick<VideoDetails, 'streamingPlaylists'>>) {
19 return video.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
20}
21
18export { 22export {
19 getAllPrivacies, 23 getAllPrivacies,
20 getAllFiles 24 getAllFiles,
25 getHLS
21} 26}
diff --git a/shared/core-utils/videos/index.ts b/shared/core-utils/videos/index.ts
index 620e3a716..2cf319395 100644
--- a/shared/core-utils/videos/index.ts
+++ b/shared/core-utils/videos/index.ts
@@ -1,2 +1,2 @@
1export * from './bitrate' 1export * from './bitrate'
2export * from './privacy' 2export * from './common'
diff --git a/shared/server-commands/miscs/sql-command.ts b/shared/server-commands/miscs/sql-command.ts
index 09a99f834..b0d9ce56d 100644
--- a/shared/server-commands/miscs/sql-command.ts
+++ b/shared/server-commands/miscs/sql-command.ts
@@ -23,6 +23,11 @@ export class SQLCommand extends AbstractCommand {
23 return parseInt(total, 10) 23 return parseInt(total, 10)
24 } 24 }
25 25
26 async getInternalFileUrl (fileId: number) {
27 return this.selectQuery(`SELECT "fileUrl" FROM "videoFile" WHERE id = ${fileId}`)
28 .then(rows => rows[0].fileUrl as string)
29 }
30
26 setActorField (to: string, field: string, value: string) { 31 setActorField (to: string, field: string, value: string) {
27 const seq = this.getSequelize() 32 const seq = this.getSequelize()
28 33
diff --git a/shared/server-commands/server/object-storage-command.ts b/shared/server-commands/server/object-storage-command.ts
index b4de8f4cb..405e1b043 100644
--- a/shared/server-commands/server/object-storage-command.ts
+++ b/shared/server-commands/server/object-storage-command.ts
@@ -4,74 +4,121 @@ import { makePostBodyRequest } from '../requests'
4import { AbstractCommand } from '../shared' 4import { AbstractCommand } from '../shared'
5 5
6export class ObjectStorageCommand extends AbstractCommand { 6export class ObjectStorageCommand extends AbstractCommand {
7 static readonly DEFAULT_PLAYLIST_BUCKET = 'streaming-playlists' 7 static readonly DEFAULT_PLAYLIST_MOCK_BUCKET = 'streaming-playlists'
8 static readonly DEFAULT_WEBTORRENT_BUCKET = 'videos' 8 static readonly DEFAULT_WEBTORRENT_MOCK_BUCKET = 'videos'
9 9
10 static getDefaultConfig () { 10 static readonly DEFAULT_SCALEWAY_BUCKET = 'peertube-ci-test'
11
12 // ---------------------------------------------------------------------------
13
14 static getDefaultMockConfig () {
11 return { 15 return {
12 object_storage: { 16 object_storage: {
13 enabled: true, 17 enabled: true,
14 endpoint: 'http://' + this.getEndpointHost(), 18 endpoint: 'http://' + this.getMockEndpointHost(),
15 region: this.getRegion(), 19 region: this.getMockRegion(),
16 20
17 credentials: this.getCredentialsConfig(), 21 credentials: this.getMockCredentialsConfig(),
18 22
19 streaming_playlists: { 23 streaming_playlists: {
20 bucket_name: this.DEFAULT_PLAYLIST_BUCKET 24 bucket_name: this.DEFAULT_PLAYLIST_MOCK_BUCKET
21 }, 25 },
22 26
23 videos: { 27 videos: {
24 bucket_name: this.DEFAULT_WEBTORRENT_BUCKET 28 bucket_name: this.DEFAULT_WEBTORRENT_MOCK_BUCKET
25 } 29 }
26 } 30 }
27 } 31 }
28 } 32 }
29 33
30 static getCredentialsConfig () { 34 static getMockCredentialsConfig () {
31 return { 35 return {
32 access_key_id: 'AKIAIOSFODNN7EXAMPLE', 36 access_key_id: 'AKIAIOSFODNN7EXAMPLE',
33 secret_access_key: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY' 37 secret_access_key: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
34 } 38 }
35 } 39 }
36 40
37 static getEndpointHost () { 41 static getMockEndpointHost () {
38 return 'localhost:9444' 42 return 'localhost:9444'
39 } 43 }
40 44
41 static getRegion () { 45 static getMockRegion () {
42 return 'us-east-1' 46 return 'us-east-1'
43 } 47 }
44 48
45 static getWebTorrentBaseUrl () { 49 static getMockWebTorrentBaseUrl () {
46 return `http://${this.DEFAULT_WEBTORRENT_BUCKET}.${this.getEndpointHost()}/` 50 return `http://${this.DEFAULT_WEBTORRENT_MOCK_BUCKET}.${this.getMockEndpointHost()}/`
47 } 51 }
48 52
49 static getPlaylistBaseUrl () { 53 static getMockPlaylistBaseUrl () {
50 return `http://${this.DEFAULT_PLAYLIST_BUCKET}.${this.getEndpointHost()}/` 54 return `http://${this.DEFAULT_PLAYLIST_MOCK_BUCKET}.${this.getMockEndpointHost()}/`
51 } 55 }
52 56
53 static async prepareDefaultBuckets () { 57 static async prepareDefaultMockBuckets () {
54 await this.createBucket(this.DEFAULT_PLAYLIST_BUCKET) 58 await this.createMockBucket(this.DEFAULT_PLAYLIST_MOCK_BUCKET)
55 await this.createBucket(this.DEFAULT_WEBTORRENT_BUCKET) 59 await this.createMockBucket(this.DEFAULT_WEBTORRENT_MOCK_BUCKET)
56 } 60 }
57 61
58 static async createBucket (name: string) { 62 static async createMockBucket (name: string) {
59 await makePostBodyRequest({ 63 await makePostBodyRequest({
60 url: this.getEndpointHost(), 64 url: this.getMockEndpointHost(),
61 path: '/ui/' + name + '?delete', 65 path: '/ui/' + name + '?delete',
62 expectedStatus: HttpStatusCode.TEMPORARY_REDIRECT_307 66 expectedStatus: HttpStatusCode.TEMPORARY_REDIRECT_307
63 }) 67 })
64 68
65 await makePostBodyRequest({ 69 await makePostBodyRequest({
66 url: this.getEndpointHost(), 70 url: this.getMockEndpointHost(),
67 path: '/ui/' + name + '?create', 71 path: '/ui/' + name + '?create',
68 expectedStatus: HttpStatusCode.TEMPORARY_REDIRECT_307 72 expectedStatus: HttpStatusCode.TEMPORARY_REDIRECT_307
69 }) 73 })
70 74
71 await makePostBodyRequest({ 75 await makePostBodyRequest({
72 url: this.getEndpointHost(), 76 url: this.getMockEndpointHost(),
73 path: '/ui/' + name + '?make-public', 77 path: '/ui/' + name + '?make-public',
74 expectedStatus: HttpStatusCode.TEMPORARY_REDIRECT_307 78 expectedStatus: HttpStatusCode.TEMPORARY_REDIRECT_307
75 }) 79 })
76 } 80 }
81
82 // ---------------------------------------------------------------------------
83
84 static getDefaultScalewayConfig (serverNumber: number) {
85 return {
86 object_storage: {
87 enabled: true,
88 endpoint: this.getScalewayEndpointHost(),
89 region: this.getScalewayRegion(),
90
91 credentials: this.getScalewayCredentialsConfig(),
92
93 streaming_playlists: {
94 bucket_name: this.DEFAULT_SCALEWAY_BUCKET,
95 prefix: `test:server-${serverNumber}-streaming-playlists:`
96 },
97
98 videos: {
99 bucket_name: this.DEFAULT_SCALEWAY_BUCKET,
100 prefix: `test:server-${serverNumber}-videos:`
101 }
102 }
103 }
104 }
105
106 static getScalewayCredentialsConfig () {
107 return {
108 access_key_id: process.env.OBJECT_STORAGE_SCALEWAY_KEY_ID,
109 secret_access_key: process.env.OBJECT_STORAGE_SCALEWAY_ACCESS_KEY
110 }
111 }
112
113 static getScalewayEndpointHost () {
114 return 's3.fr-par.scw.cloud'
115 }
116
117 static getScalewayRegion () {
118 return 'fr-par'
119 }
120
121 static getScalewayBaseUrl () {
122 return `https://${this.DEFAULT_SCALEWAY_BUCKET}.${this.getScalewayEndpointHost()}/`
123 }
77} 124}
diff --git a/shared/server-commands/videos/live-command.ts b/shared/server-commands/videos/live-command.ts
index de193fa49..cc9502c6f 100644
--- a/shared/server-commands/videos/live-command.ts
+++ b/shared/server-commands/videos/live-command.ts
@@ -197,7 +197,7 @@ export class LiveCommand extends AbstractCommand {
197 197
198 const segmentName = `${playlistNumber}-00000${segment}.ts` 198 const segmentName = `${playlistNumber}-00000${segment}.ts`
199 const baseUrl = objectStorage 199 const baseUrl = objectStorage
200 ? ObjectStorageCommand.getPlaylistBaseUrl() + 'hls' 200 ? ObjectStorageCommand.getMockPlaylistBaseUrl() + 'hls'
201 : server.url + '/static/streaming-playlists/hls' 201 : server.url + '/static/streaming-playlists/hls'
202 202
203 let error = true 203 let error = true
@@ -253,7 +253,7 @@ export class LiveCommand extends AbstractCommand {
253 253
254 const segmentName = `${playlistNumber}-00000${segment}.ts` 254 const segmentName = `${playlistNumber}-00000${segment}.ts`
255 const baseUrl = objectStorage 255 const baseUrl = objectStorage
256 ? ObjectStorageCommand.getPlaylistBaseUrl() 256 ? ObjectStorageCommand.getMockPlaylistBaseUrl()
257 : `${this.server.url}/static/streaming-playlists/hls` 257 : `${this.server.url}/static/streaming-playlists/hls`
258 258
259 const url = `${baseUrl}/${videoUUID}/${segmentName}` 259 const url = `${baseUrl}/${videoUUID}/${segmentName}`
@@ -275,7 +275,7 @@ export class LiveCommand extends AbstractCommand {
275 const { playlistName, videoUUID, objectStorage = false } = options 275 const { playlistName, videoUUID, objectStorage = false } = options
276 276
277 const baseUrl = objectStorage 277 const baseUrl = objectStorage
278 ? ObjectStorageCommand.getPlaylistBaseUrl() 278 ? ObjectStorageCommand.getMockPlaylistBaseUrl()
279 : `${this.server.url}/static/streaming-playlists/hls` 279 : `${this.server.url}/static/streaming-playlists/hls`
280 280
281 const url = `${baseUrl}/${videoUUID}/${playlistName}` 281 const url = `${baseUrl}/${videoUUID}/${playlistName}`
diff --git a/yarn.lock b/yarn.lock
index 64966f808..0dde0a362 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -139,720 +139,740 @@
139 "@aws-sdk/util-utf8-browser" "^3.0.0" 139 "@aws-sdk/util-utf8-browser" "^3.0.0"
140 tslib "^1.11.1" 140 tslib "^1.11.1"
141 141
142"@aws-sdk/abort-controller@3.162.0": 142"@aws-sdk/abort-controller@3.190.0":
143 version "3.162.0" 143 version "3.190.0"
144 resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.162.0.tgz#c49c08e61e87c1e6bcba8214177228ecf4007535" 144 resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.190.0.tgz#284263db7ba051f31dda64e077b68e45cca7a7b3"
145 integrity sha512-8j1f/g+pNny3HkOojl+6phwd1yQE0FmM6EdssRJPA/IpR+SE0qTva2psKfZA9DivAg+/iTBozVCQU5GUJY1F2A== 145 integrity sha512-M6qo2exTzEfHT5RuW7K090OgesUojhb2JyWiV4ulu7ngY4DWBUBMKUqac696sHRUZvGE5CDzSi0606DMboM+kA==
146 dependencies: 146 dependencies:
147 "@aws-sdk/types" "3.162.0" 147 "@aws-sdk/types" "3.190.0"
148 tslib "^2.3.1" 148 tslib "^2.3.1"
149 149
150"@aws-sdk/chunked-blob-reader-native@3.109.0": 150"@aws-sdk/chunked-blob-reader-native@3.188.0":
151 version "3.109.0" 151 version "3.188.0"
152 resolved "https://registry.yarnpkg.com/@aws-sdk/chunked-blob-reader-native/-/chunked-blob-reader-native-3.109.0.tgz#4db2ec81faf38fe33cf9dd6f75641afe0826dcfd" 152 resolved "https://registry.yarnpkg.com/@aws-sdk/chunked-blob-reader-native/-/chunked-blob-reader-native-3.188.0.tgz#a5c3a778b23af761703317ef286a083a43fb510f"
153 integrity sha512-Ybn3vDZ3CqGyprL2qdF6QZqoqlx8lA3qOJepobjuKKDRw+KgGxjUY4NvWe0R2MdRoduyaDj6uvhIay0S1MOSJQ== 153 integrity sha512-WielYjaAHfT/HAOW7Tj6yVeNdaOtts3aUm9Sf/3D+ElbCTGyaaMNfE4x0a+qn6dJZXewf1eAxybOIU5ftIeSGw==
154 dependencies: 154 dependencies:
155 "@aws-sdk/util-base64-browser" "3.109.0" 155 "@aws-sdk/util-base64-browser" "3.188.0"
156 tslib "^2.3.1" 156 tslib "^2.3.1"
157 157
158"@aws-sdk/chunked-blob-reader@3.55.0": 158"@aws-sdk/chunked-blob-reader@3.188.0":
159 version "3.55.0" 159 version "3.188.0"
160 resolved "https://registry.yarnpkg.com/@aws-sdk/chunked-blob-reader/-/chunked-blob-reader-3.55.0.tgz#db240c78e7c4c826e707f0ca32a4d221c41cf6a0" 160 resolved "https://registry.yarnpkg.com/@aws-sdk/chunked-blob-reader/-/chunked-blob-reader-3.188.0.tgz#18181b27511ab512e56b9f2cef30d2abbef639dc"
161 integrity sha512-o/xjMCq81opAjSBjt7YdHJwIJcGVG5XIV9+C2KXcY5QwVimkOKPybWTv0mXPvSwSilSx+EhpLNhkcJuXdzhw4w== 161 integrity sha512-zkPRFZZPL3eH+kH86LDYYXImiClA1/sW60zYOjse9Pgka+eDJlvBN6hcYxwDEKjcwATYiSRR1aVQHcfCinlGXg==
162 dependencies: 162 dependencies:
163 tslib "^2.3.1" 163 tslib "^2.3.1"
164 164
165"@aws-sdk/client-s3@^3.23.0": 165"@aws-sdk/client-s3@^3.190.0":
166 version "3.165.0" 166 version "3.190.0"
167 resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.165.0.tgz#62555e00ca5df1736c36682e39da272a9d6cf013" 167 resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.190.0.tgz#7d97da023d68fd19c1b2f9a8a6a162a75ff32daf"
168 integrity sha512-vVTIxf6OJoX0t2Ur64r0gQXKfSeK7VnHq4m5O6QM8IDmOuVP7jyeEt5sw1PaDC4amarVa215u/IZWsaIEDlrsw== 168 integrity sha512-ngF92/X+odFt5Zbs5AWTozI+35fwFkHghbDABi5uSWNtgs2alSc/A94/yexbDdvVrVnuUa/FAMkvYX8duGZ9ig==
169 dependencies: 169 dependencies:
170 "@aws-crypto/sha1-browser" "2.0.0" 170 "@aws-crypto/sha1-browser" "2.0.0"
171 "@aws-crypto/sha256-browser" "2.0.0" 171 "@aws-crypto/sha256-browser" "2.0.0"
172 "@aws-crypto/sha256-js" "2.0.0" 172 "@aws-crypto/sha256-js" "2.0.0"
173 "@aws-sdk/client-sts" "3.165.0" 173 "@aws-sdk/client-sts" "3.190.0"
174 "@aws-sdk/config-resolver" "3.163.0" 174 "@aws-sdk/config-resolver" "3.190.0"
175 "@aws-sdk/credential-provider-node" "3.165.0" 175 "@aws-sdk/credential-provider-node" "3.190.0"
176 "@aws-sdk/eventstream-serde-browser" "3.162.0" 176 "@aws-sdk/eventstream-serde-browser" "3.190.0"
177 "@aws-sdk/eventstream-serde-config-resolver" "3.162.0" 177 "@aws-sdk/eventstream-serde-config-resolver" "3.190.0"
178 "@aws-sdk/eventstream-serde-node" "3.162.0" 178 "@aws-sdk/eventstream-serde-node" "3.190.0"
179 "@aws-sdk/fetch-http-handler" "3.162.0" 179 "@aws-sdk/fetch-http-handler" "3.190.0"
180 "@aws-sdk/hash-blob-browser" "3.162.0" 180 "@aws-sdk/hash-blob-browser" "3.190.0"
181 "@aws-sdk/hash-node" "3.162.0" 181 "@aws-sdk/hash-node" "3.190.0"
182 "@aws-sdk/hash-stream-node" "3.162.0" 182 "@aws-sdk/hash-stream-node" "3.190.0"
183 "@aws-sdk/invalid-dependency" "3.162.0" 183 "@aws-sdk/invalid-dependency" "3.190.0"
184 "@aws-sdk/md5-js" "3.162.0" 184 "@aws-sdk/md5-js" "3.190.0"
185 "@aws-sdk/middleware-bucket-endpoint" "3.162.0" 185 "@aws-sdk/middleware-bucket-endpoint" "3.190.0"
186 "@aws-sdk/middleware-content-length" "3.162.0" 186 "@aws-sdk/middleware-content-length" "3.190.0"
187 "@aws-sdk/middleware-expect-continue" "3.162.0" 187 "@aws-sdk/middleware-expect-continue" "3.190.0"
188 "@aws-sdk/middleware-flexible-checksums" "3.162.0" 188 "@aws-sdk/middleware-flexible-checksums" "3.190.0"
189 "@aws-sdk/middleware-host-header" "3.162.0" 189 "@aws-sdk/middleware-host-header" "3.190.0"
190 "@aws-sdk/middleware-location-constraint" "3.162.0" 190 "@aws-sdk/middleware-location-constraint" "3.190.0"
191 "@aws-sdk/middleware-logger" "3.162.0" 191 "@aws-sdk/middleware-logger" "3.190.0"
192 "@aws-sdk/middleware-recursion-detection" "3.162.0" 192 "@aws-sdk/middleware-recursion-detection" "3.190.0"
193 "@aws-sdk/middleware-retry" "3.162.0" 193 "@aws-sdk/middleware-retry" "3.190.0"
194 "@aws-sdk/middleware-sdk-s3" "3.165.0" 194 "@aws-sdk/middleware-sdk-s3" "3.190.0"
195 "@aws-sdk/middleware-serde" "3.162.0" 195 "@aws-sdk/middleware-serde" "3.190.0"
196 "@aws-sdk/middleware-signing" "3.163.0" 196 "@aws-sdk/middleware-signing" "3.190.0"
197 "@aws-sdk/middleware-ssec" "3.162.0" 197 "@aws-sdk/middleware-ssec" "3.190.0"
198 "@aws-sdk/middleware-stack" "3.162.0" 198 "@aws-sdk/middleware-stack" "3.190.0"
199 "@aws-sdk/middleware-user-agent" "3.162.0" 199 "@aws-sdk/middleware-user-agent" "3.190.0"
200 "@aws-sdk/node-config-provider" "3.162.0" 200 "@aws-sdk/node-config-provider" "3.190.0"
201 "@aws-sdk/node-http-handler" "3.162.0" 201 "@aws-sdk/node-http-handler" "3.190.0"
202 "@aws-sdk/protocol-http" "3.162.0" 202 "@aws-sdk/protocol-http" "3.190.0"
203 "@aws-sdk/signature-v4-multi-region" "3.163.0" 203 "@aws-sdk/signature-v4-multi-region" "3.190.0"
204 "@aws-sdk/smithy-client" "3.162.0" 204 "@aws-sdk/smithy-client" "3.190.0"
205 "@aws-sdk/types" "3.162.0" 205 "@aws-sdk/types" "3.190.0"
206 "@aws-sdk/url-parser" "3.162.0" 206 "@aws-sdk/url-parser" "3.190.0"
207 "@aws-sdk/util-base64-browser" "3.109.0" 207 "@aws-sdk/util-base64-browser" "3.188.0"
208 "@aws-sdk/util-base64-node" "3.55.0" 208 "@aws-sdk/util-base64-node" "3.188.0"
209 "@aws-sdk/util-body-length-browser" "3.154.0" 209 "@aws-sdk/util-body-length-browser" "3.188.0"
210 "@aws-sdk/util-body-length-node" "3.55.0" 210 "@aws-sdk/util-body-length-node" "3.188.0"
211 "@aws-sdk/util-defaults-mode-browser" "3.162.0" 211 "@aws-sdk/util-defaults-mode-browser" "3.190.0"
212 "@aws-sdk/util-defaults-mode-node" "3.163.0" 212 "@aws-sdk/util-defaults-mode-node" "3.190.0"
213 "@aws-sdk/util-stream-browser" "3.162.0" 213 "@aws-sdk/util-stream-browser" "3.190.0"
214 "@aws-sdk/util-stream-node" "3.162.0" 214 "@aws-sdk/util-stream-node" "3.190.0"
215 "@aws-sdk/util-user-agent-browser" "3.162.0" 215 "@aws-sdk/util-user-agent-browser" "3.190.0"
216 "@aws-sdk/util-user-agent-node" "3.162.0" 216 "@aws-sdk/util-user-agent-node" "3.190.0"
217 "@aws-sdk/util-utf8-browser" "3.109.0" 217 "@aws-sdk/util-utf8-browser" "3.188.0"
218 "@aws-sdk/util-utf8-node" "3.109.0" 218 "@aws-sdk/util-utf8-node" "3.188.0"
219 "@aws-sdk/util-waiter" "3.162.0" 219 "@aws-sdk/util-waiter" "3.190.0"
220 "@aws-sdk/xml-builder" "3.142.0" 220 "@aws-sdk/xml-builder" "3.188.0"
221 entities "2.2.0" 221 fast-xml-parser "4.0.11"
222 fast-xml-parser "3.19.0"
223 tslib "^2.3.1" 222 tslib "^2.3.1"
224 223
225"@aws-sdk/client-sso@3.165.0": 224"@aws-sdk/client-sso@3.190.0":
226 version "3.165.0" 225 version "3.190.0"
227 resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.165.0.tgz#655e74e4673b79ab167d228a0ad9de8d08a88845" 226 resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.190.0.tgz#d3435bf406bd7cedf705e9e876da49dd5a2bc17f"
228 integrity sha512-Cizf03z6UFgHWOIQYOjZdNwUhoh6yhT5B2dH+mh1q+Naq1zsLmD2PUvx7SM+0fZsN9MhOICLyBSE/nSSE7E8Kg== 227 integrity sha512-joEKRjJEzgvXnEih/x2UDDCPlvXWCO3MAHmqi44yJ36Ph4YsFS299mOjPdVLuzUtpQ+cST1nRO7hXNFrulW2jQ==
229 dependencies: 228 dependencies:
230 "@aws-crypto/sha256-browser" "2.0.0" 229 "@aws-crypto/sha256-browser" "2.0.0"
231 "@aws-crypto/sha256-js" "2.0.0" 230 "@aws-crypto/sha256-js" "2.0.0"
232 "@aws-sdk/config-resolver" "3.163.0" 231 "@aws-sdk/config-resolver" "3.190.0"
233 "@aws-sdk/fetch-http-handler" "3.162.0" 232 "@aws-sdk/fetch-http-handler" "3.190.0"
234 "@aws-sdk/hash-node" "3.162.0" 233 "@aws-sdk/hash-node" "3.190.0"
235 "@aws-sdk/invalid-dependency" "3.162.0" 234 "@aws-sdk/invalid-dependency" "3.190.0"
236 "@aws-sdk/middleware-content-length" "3.162.0" 235 "@aws-sdk/middleware-content-length" "3.190.0"
237 "@aws-sdk/middleware-host-header" "3.162.0" 236 "@aws-sdk/middleware-host-header" "3.190.0"
238 "@aws-sdk/middleware-logger" "3.162.0" 237 "@aws-sdk/middleware-logger" "3.190.0"
239 "@aws-sdk/middleware-recursion-detection" "3.162.0" 238 "@aws-sdk/middleware-recursion-detection" "3.190.0"
240 "@aws-sdk/middleware-retry" "3.162.0" 239 "@aws-sdk/middleware-retry" "3.190.0"
241 "@aws-sdk/middleware-serde" "3.162.0" 240 "@aws-sdk/middleware-serde" "3.190.0"
242 "@aws-sdk/middleware-stack" "3.162.0" 241 "@aws-sdk/middleware-stack" "3.190.0"
243 "@aws-sdk/middleware-user-agent" "3.162.0" 242 "@aws-sdk/middleware-user-agent" "3.190.0"
244 "@aws-sdk/node-config-provider" "3.162.0" 243 "@aws-sdk/node-config-provider" "3.190.0"
245 "@aws-sdk/node-http-handler" "3.162.0" 244 "@aws-sdk/node-http-handler" "3.190.0"
246 "@aws-sdk/protocol-http" "3.162.0" 245 "@aws-sdk/protocol-http" "3.190.0"
247 "@aws-sdk/smithy-client" "3.162.0" 246 "@aws-sdk/smithy-client" "3.190.0"
248 "@aws-sdk/types" "3.162.0" 247 "@aws-sdk/types" "3.190.0"
249 "@aws-sdk/url-parser" "3.162.0" 248 "@aws-sdk/url-parser" "3.190.0"
250 "@aws-sdk/util-base64-browser" "3.109.0" 249 "@aws-sdk/util-base64-browser" "3.188.0"
251 "@aws-sdk/util-base64-node" "3.55.0" 250 "@aws-sdk/util-base64-node" "3.188.0"
252 "@aws-sdk/util-body-length-browser" "3.154.0" 251 "@aws-sdk/util-body-length-browser" "3.188.0"
253 "@aws-sdk/util-body-length-node" "3.55.0" 252 "@aws-sdk/util-body-length-node" "3.188.0"
254 "@aws-sdk/util-defaults-mode-browser" "3.162.0" 253 "@aws-sdk/util-defaults-mode-browser" "3.190.0"
255 "@aws-sdk/util-defaults-mode-node" "3.163.0" 254 "@aws-sdk/util-defaults-mode-node" "3.190.0"
256 "@aws-sdk/util-user-agent-browser" "3.162.0" 255 "@aws-sdk/util-user-agent-browser" "3.190.0"
257 "@aws-sdk/util-user-agent-node" "3.162.0" 256 "@aws-sdk/util-user-agent-node" "3.190.0"
258 "@aws-sdk/util-utf8-browser" "3.109.0" 257 "@aws-sdk/util-utf8-browser" "3.188.0"
259 "@aws-sdk/util-utf8-node" "3.109.0" 258 "@aws-sdk/util-utf8-node" "3.188.0"
260 tslib "^2.3.1" 259 tslib "^2.3.1"
261 260
262"@aws-sdk/client-sts@3.165.0": 261"@aws-sdk/client-sts@3.190.0":
263 version "3.165.0" 262 version "3.190.0"
264 resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.165.0.tgz#1d9824aba899af5c9e6712543916fa63bfb3a2bf" 263 resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.190.0.tgz#835a471daec37aa12e073f425aeab60fc1b3f9e5"
265 integrity sha512-pizXLuaIRDdC1zseB0v/YQ3IKxzJfD/bVBgOhQNCNVr4d7O7/oDXU3I+GhESmKpWopQADg1s1Q3NGtkUoJJUew== 264 integrity sha512-s5MqfxqWxHAl1RhfQ6swjawsVPBqmq5F+SfzZcGLBCnVv03GaSL8J9K42O1Cc0+HwPQH2miY+Avy0zAr6VpY+Q==
266 dependencies: 265 dependencies:
267 "@aws-crypto/sha256-browser" "2.0.0" 266 "@aws-crypto/sha256-browser" "2.0.0"
268 "@aws-crypto/sha256-js" "2.0.0" 267 "@aws-crypto/sha256-js" "2.0.0"
269 "@aws-sdk/config-resolver" "3.163.0" 268 "@aws-sdk/config-resolver" "3.190.0"
270 "@aws-sdk/credential-provider-node" "3.165.0" 269 "@aws-sdk/credential-provider-node" "3.190.0"
271 "@aws-sdk/fetch-http-handler" "3.162.0" 270 "@aws-sdk/fetch-http-handler" "3.190.0"
272 "@aws-sdk/hash-node" "3.162.0" 271 "@aws-sdk/hash-node" "3.190.0"
273 "@aws-sdk/invalid-dependency" "3.162.0" 272 "@aws-sdk/invalid-dependency" "3.190.0"
274 "@aws-sdk/middleware-content-length" "3.162.0" 273 "@aws-sdk/middleware-content-length" "3.190.0"
275 "@aws-sdk/middleware-host-header" "3.162.0" 274 "@aws-sdk/middleware-host-header" "3.190.0"
276 "@aws-sdk/middleware-logger" "3.162.0" 275 "@aws-sdk/middleware-logger" "3.190.0"
277 "@aws-sdk/middleware-recursion-detection" "3.162.0" 276 "@aws-sdk/middleware-recursion-detection" "3.190.0"
278 "@aws-sdk/middleware-retry" "3.162.0" 277 "@aws-sdk/middleware-retry" "3.190.0"
279 "@aws-sdk/middleware-sdk-sts" "3.163.0" 278 "@aws-sdk/middleware-sdk-sts" "3.190.0"
280 "@aws-sdk/middleware-serde" "3.162.0" 279 "@aws-sdk/middleware-serde" "3.190.0"
281 "@aws-sdk/middleware-signing" "3.163.0" 280 "@aws-sdk/middleware-signing" "3.190.0"
282 "@aws-sdk/middleware-stack" "3.162.0" 281 "@aws-sdk/middleware-stack" "3.190.0"
283 "@aws-sdk/middleware-user-agent" "3.162.0" 282 "@aws-sdk/middleware-user-agent" "3.190.0"
284 "@aws-sdk/node-config-provider" "3.162.0" 283 "@aws-sdk/node-config-provider" "3.190.0"
285 "@aws-sdk/node-http-handler" "3.162.0" 284 "@aws-sdk/node-http-handler" "3.190.0"
286 "@aws-sdk/protocol-http" "3.162.0" 285 "@aws-sdk/protocol-http" "3.190.0"
287 "@aws-sdk/smithy-client" "3.162.0" 286 "@aws-sdk/smithy-client" "3.190.0"
288 "@aws-sdk/types" "3.162.0" 287 "@aws-sdk/types" "3.190.0"
289 "@aws-sdk/url-parser" "3.162.0" 288 "@aws-sdk/url-parser" "3.190.0"
290 "@aws-sdk/util-base64-browser" "3.109.0" 289 "@aws-sdk/util-base64-browser" "3.188.0"
291 "@aws-sdk/util-base64-node" "3.55.0" 290 "@aws-sdk/util-base64-node" "3.188.0"
292 "@aws-sdk/util-body-length-browser" "3.154.0" 291 "@aws-sdk/util-body-length-browser" "3.188.0"
293 "@aws-sdk/util-body-length-node" "3.55.0" 292 "@aws-sdk/util-body-length-node" "3.188.0"
294 "@aws-sdk/util-defaults-mode-browser" "3.162.0" 293 "@aws-sdk/util-defaults-mode-browser" "3.190.0"
295 "@aws-sdk/util-defaults-mode-node" "3.163.0" 294 "@aws-sdk/util-defaults-mode-node" "3.190.0"
296 "@aws-sdk/util-user-agent-browser" "3.162.0" 295 "@aws-sdk/util-user-agent-browser" "3.190.0"
297 "@aws-sdk/util-user-agent-node" "3.162.0" 296 "@aws-sdk/util-user-agent-node" "3.190.0"
298 "@aws-sdk/util-utf8-browser" "3.109.0" 297 "@aws-sdk/util-utf8-browser" "3.188.0"
299 "@aws-sdk/util-utf8-node" "3.109.0" 298 "@aws-sdk/util-utf8-node" "3.188.0"
300 entities "2.2.0" 299 fast-xml-parser "4.0.11"
301 fast-xml-parser "3.19.0"
302 tslib "^2.3.1" 300 tslib "^2.3.1"
303 301
304"@aws-sdk/config-resolver@3.163.0": 302"@aws-sdk/config-resolver@3.190.0":
305 version "3.163.0" 303 version "3.190.0"
306 resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.163.0.tgz#65ae429a02d65a8a9d2fe321cc88fa9117c6ecae" 304 resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.190.0.tgz#cb068fef70360c227698b670a2f1224467b523b4"
307 integrity sha512-iBl5Zc3+VRGJy6n+aMcg++7tzYi4G1bHia6v/eF93SvdKxtRv40M9QnqoNfaNUuw9U2ltwKOHepw7J3bkOA8cQ== 305 integrity sha512-K+VnDtjTgjpf7yHEdDB0qgGbHToF0pIL0pQMSnmk2yc8BoB3LGG/gg1T0Ki+wRlrFnDCJ6L+8zUdawY2qDsbyw==
308 dependencies: 306 dependencies:
309 "@aws-sdk/signature-v4" "3.163.0" 307 "@aws-sdk/signature-v4" "3.190.0"
310 "@aws-sdk/types" "3.162.0" 308 "@aws-sdk/types" "3.190.0"
311 "@aws-sdk/util-config-provider" "3.109.0" 309 "@aws-sdk/util-config-provider" "3.188.0"
312 "@aws-sdk/util-middleware" "3.162.0" 310 "@aws-sdk/util-middleware" "3.190.0"
313 tslib "^2.3.1" 311 tslib "^2.3.1"
314 312
315"@aws-sdk/credential-provider-env@3.162.0": 313"@aws-sdk/credential-provider-env@3.190.0":
316 version "3.162.0" 314 version "3.190.0"
317 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.162.0.tgz#be2bf9587d9e7b2a10b1c2530c5984b60efc11bd" 315 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.190.0.tgz#b0be7325508529ec1d910b1f18c5a6cc98186dcd"
318 integrity sha512-yzCJXiAAbZZHB4iThi4I+rs+gTYwBSetdU4Z1D89a2xjcOjCa8IhdQKm3GO/uJMScy4VtW3EEFG4/zZ7dVQPOw== 316 integrity sha512-GTY7l3SJhTmRGFpWddbdJOihSqoMN8JMo3CsCtIjk4/h3xirBi02T4GSvbrMyP7FP3Fdl4NAdT+mHJ4q2Bvzxw==
319 dependencies: 317 dependencies:
320 "@aws-sdk/property-provider" "3.162.0" 318 "@aws-sdk/property-provider" "3.190.0"
321 "@aws-sdk/types" "3.162.0" 319 "@aws-sdk/types" "3.190.0"
322 tslib "^2.3.1" 320 tslib "^2.3.1"
323 321
324"@aws-sdk/credential-provider-imds@3.162.0": 322"@aws-sdk/credential-provider-imds@3.190.0":
325 version "3.162.0" 323 version "3.190.0"
326 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.162.0.tgz#bb8002a37c42e6f2f42fcafff3a8e4262b6aac4a" 324 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.190.0.tgz#15aee396b321e01ede0f0aa88f643e43c42ad879"
327 integrity sha512-ohrHMIu2MNauPjbE8mEMKtlEQH/VZdpNswPigaEejUGVumz0NSft9PlIn2X79sNX5Y+uXopynMQF4MZj773hTw== 325 integrity sha512-gI5pfBqGYCKdmx8igPvq+jLzyE2kuNn9Q5u73pdM/JZxiq7GeWYpE/MqqCubHxPtPcTFgAwxCxCFoXlUTBh/2g==
328 dependencies: 326 dependencies:
329 "@aws-sdk/node-config-provider" "3.162.0" 327 "@aws-sdk/node-config-provider" "3.190.0"
330 "@aws-sdk/property-provider" "3.162.0" 328 "@aws-sdk/property-provider" "3.190.0"
331 "@aws-sdk/types" "3.162.0" 329 "@aws-sdk/types" "3.190.0"
332 "@aws-sdk/url-parser" "3.162.0" 330 "@aws-sdk/url-parser" "3.190.0"
333 tslib "^2.3.1" 331 tslib "^2.3.1"
334 332
335"@aws-sdk/credential-provider-ini@3.165.0": 333"@aws-sdk/credential-provider-ini@3.190.0":
336 version "3.165.0" 334 version "3.190.0"
337 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.165.0.tgz#eee4131ef1b8a0f815f53e6be5452b547e839d04" 335 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.190.0.tgz#b12b9620aeb30c87d99dd234ba7c80b983688167"
338 integrity sha512-NrLe29bdhmpNPsEsYxUxb0hTxNMXCmz5pH2l/T9COT6SMxom1wpbB/aKwf9897Z1xvhoFi6flDQjmu//599BZw== 336 integrity sha512-Z7NN/evXJk59hBQlfOSWDfHntwmxwryu6uclgv7ECI6SEVtKt1EKIlPuCLUYgQ4lxb9bomyO5lQAl/1WutNT5w==
339 dependencies: 337 dependencies:
340 "@aws-sdk/credential-provider-env" "3.162.0" 338 "@aws-sdk/credential-provider-env" "3.190.0"
341 "@aws-sdk/credential-provider-imds" "3.162.0" 339 "@aws-sdk/credential-provider-imds" "3.190.0"
342 "@aws-sdk/credential-provider-sso" "3.165.0" 340 "@aws-sdk/credential-provider-sso" "3.190.0"
343 "@aws-sdk/credential-provider-web-identity" "3.162.0" 341 "@aws-sdk/credential-provider-web-identity" "3.190.0"
344 "@aws-sdk/property-provider" "3.162.0" 342 "@aws-sdk/property-provider" "3.190.0"
345 "@aws-sdk/shared-ini-file-loader" "3.162.0" 343 "@aws-sdk/shared-ini-file-loader" "3.190.0"
346 "@aws-sdk/types" "3.162.0" 344 "@aws-sdk/types" "3.190.0"
347 tslib "^2.3.1" 345 tslib "^2.3.1"
348 346
349"@aws-sdk/credential-provider-node@3.165.0": 347"@aws-sdk/credential-provider-node@3.190.0":
350 version "3.165.0" 348 version "3.190.0"
351 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.165.0.tgz#ff3aa22df468ded2d370955f0b2c0548860583d4" 349 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.190.0.tgz#7de69d65c694e26191414ddde978df929bd632b7"
352 integrity sha512-emUd3kqAvV8Qydn5pJ+YKo47UJ+B5RXNyQXMasNQsw1jxrB60j8QAIL9JGM019SzZBnHZuW3DrHClA17OVC+xQ== 350 integrity sha512-ctCG5+TsIK2gVgvvFiFjinPjc5nGpSypU3nQKCaihtPh83wDN6gCx4D0p9M8+fUrlPa5y+o/Y7yHo94ATepM8w==
353 dependencies: 351 dependencies:
354 "@aws-sdk/credential-provider-env" "3.162.0" 352 "@aws-sdk/credential-provider-env" "3.190.0"
355 "@aws-sdk/credential-provider-imds" "3.162.0" 353 "@aws-sdk/credential-provider-imds" "3.190.0"
356 "@aws-sdk/credential-provider-ini" "3.165.0" 354 "@aws-sdk/credential-provider-ini" "3.190.0"
357 "@aws-sdk/credential-provider-process" "3.162.0" 355 "@aws-sdk/credential-provider-process" "3.190.0"
358 "@aws-sdk/credential-provider-sso" "3.165.0" 356 "@aws-sdk/credential-provider-sso" "3.190.0"
359 "@aws-sdk/credential-provider-web-identity" "3.162.0" 357 "@aws-sdk/credential-provider-web-identity" "3.190.0"
360 "@aws-sdk/property-provider" "3.162.0" 358 "@aws-sdk/property-provider" "3.190.0"
361 "@aws-sdk/shared-ini-file-loader" "3.162.0" 359 "@aws-sdk/shared-ini-file-loader" "3.190.0"
362 "@aws-sdk/types" "3.162.0" 360 "@aws-sdk/types" "3.190.0"
363 tslib "^2.3.1" 361 tslib "^2.3.1"
364 362
365"@aws-sdk/credential-provider-process@3.162.0": 363"@aws-sdk/credential-provider-process@3.190.0":
366 version "3.162.0" 364 version "3.190.0"
367 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.162.0.tgz#e54db5f3ac5a5200a6f04803b05278c028a54447" 365 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.190.0.tgz#b1a4aa9fc83984bf2219cfc027a78deaca417c59"
368 integrity sha512-KtmYjlCMAa0XF3IJo4dxSF+OWmRoHbrdEHGEZw+j6iCZ3Nz6Y6xCsdxun5rAKdom1QRNMDR4wX0hRAdPYobW2w== 366 integrity sha512-sIJhICR80n5XY1kW/EFHTh5ZzBHb5X+744QCH3StcbKYI44mOZvNKfFdeRL2fQ7yLgV7npte2HJRZzQPWpZUrw==
369 dependencies: 367 dependencies:
370 "@aws-sdk/property-provider" "3.162.0" 368 "@aws-sdk/property-provider" "3.190.0"
371 "@aws-sdk/shared-ini-file-loader" "3.162.0" 369 "@aws-sdk/shared-ini-file-loader" "3.190.0"
372 "@aws-sdk/types" "3.162.0" 370 "@aws-sdk/types" "3.190.0"
373 tslib "^2.3.1" 371 tslib "^2.3.1"
374 372
375"@aws-sdk/credential-provider-sso@3.165.0": 373"@aws-sdk/credential-provider-sso@3.190.0":
376 version "3.165.0" 374 version "3.190.0"
377 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.165.0.tgz#7da83675149983e25345c05ee1113e64485b5b19" 375 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.190.0.tgz#285895dc38c09033154906ce253ff6f0bdca86ab"
378 integrity sha512-b2BuYyUSmnfChhz5ZbnqOaLSAsnzYcwpEPEUbQUdNGPSE3QcMd0SPl3woH82095WYlXTFjwgxlOPn5ad5hdBpA== 376 integrity sha512-uarU9vk471MHHT+GJj3KWFSmaaqLNL5n1KcMer2CCAZfjs+mStAi8+IjZuuKXB4vqVs5DxdH8cy5aLaJcBlXwQ==
379 dependencies: 377 dependencies:
380 "@aws-sdk/client-sso" "3.165.0" 378 "@aws-sdk/client-sso" "3.190.0"
381 "@aws-sdk/property-provider" "3.162.0" 379 "@aws-sdk/property-provider" "3.190.0"
382 "@aws-sdk/shared-ini-file-loader" "3.162.0" 380 "@aws-sdk/shared-ini-file-loader" "3.190.0"
383 "@aws-sdk/types" "3.162.0" 381 "@aws-sdk/types" "3.190.0"
384 tslib "^2.3.1" 382 tslib "^2.3.1"
385 383
386"@aws-sdk/credential-provider-web-identity@3.162.0": 384"@aws-sdk/credential-provider-web-identity@3.190.0":
387 version "3.162.0" 385 version "3.190.0"
388 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.162.0.tgz#0b06aee91777b16c362ad565e9f1fdf77de7e8f6" 386 resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.190.0.tgz#c41fe6f1ebb814581b010c0f82e5232da85c90b7"
389 integrity sha512-vy86OS5/h+Vfk1bxvWjbayyUtFNdwU+mfALin3zxJbFqneSxRBydNBomt/guJjapZE+h865lkteyOsqsYMskzQ== 387 integrity sha512-nlIBeK9hGHKWC874h+ITAfPZ9Eaok+x/ydZQVKsLHiQ9PH3tuQ8AaGqhuCwBSH0hEAHZ/BiKeEx5VyWAE8/x+Q==
390 dependencies: 388 dependencies:
391 "@aws-sdk/property-provider" "3.162.0" 389 "@aws-sdk/property-provider" "3.190.0"
392 "@aws-sdk/types" "3.162.0" 390 "@aws-sdk/types" "3.190.0"
393 tslib "^2.3.1" 391 tslib "^2.3.1"
394 392
395"@aws-sdk/eventstream-codec@3.162.0": 393"@aws-sdk/eventstream-codec@3.190.0":
396 version "3.162.0" 394 version "3.190.0"
397 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-codec/-/eventstream-codec-3.162.0.tgz#c105a2d3081b0b74a3d1be6c49bd489a677102ad" 395 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-codec/-/eventstream-codec-3.190.0.tgz#7e9705ed5ffd2b7b77c0eca868c1c64a8a2d2941"
398 integrity sha512-DllkOwvOFO28nuFyY+Klu31aRwHp1Db6G6BfMfRFACId5RIE9LNVgEoNnR/uluZqQ9IN7k7kyp7ycztyn18tUA== 396 integrity sha512-F1ux94fMKUrlOfJR/1x8p5+lisfemKizNSRtMnj0kcR+Y9vIt9bUodFyuDF8tJl/7iwnop6EPiGc3QA1IKjBKA==
399 dependencies: 397 dependencies:
400 "@aws-crypto/crc32" "2.0.0" 398 "@aws-crypto/crc32" "2.0.0"
401 "@aws-sdk/types" "3.162.0" 399 "@aws-sdk/types" "3.190.0"
402 "@aws-sdk/util-hex-encoding" "3.109.0" 400 "@aws-sdk/util-hex-encoding" "3.188.0"
403 tslib "^2.3.1" 401 tslib "^2.3.1"
404 402
405"@aws-sdk/eventstream-serde-browser@3.162.0": 403"@aws-sdk/eventstream-serde-browser@3.190.0":
406 version "3.162.0" 404 version "3.190.0"
407 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-browser/-/eventstream-serde-browser-3.162.0.tgz#d84952d5c65b247b3e01c4ee59c42a716338ce38" 405 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-browser/-/eventstream-serde-browser-3.190.0.tgz#cb53132a6340742c2dd1a767da4442d3b5a6c866"
408 integrity sha512-99xPbUs3JS+uwdKe+pZu3UOc/GeI9qPk4epramssgaLKzQGkO4ylN3CD9ts4xeMXkE+VS0p0lEKeg80/fkzqzA== 406 integrity sha512-aUsbLLPi3dtafnpIJtGbpCe8fhABIsVV49V1jJx6gQDAs6HG5IhO3LfndF05H6UbMyt8sDS6223wSt6HFUSHjQ==
409 dependencies: 407 dependencies:
410 "@aws-sdk/eventstream-serde-universal" "3.162.0" 408 "@aws-sdk/eventstream-serde-universal" "3.190.0"
411 "@aws-sdk/types" "3.162.0" 409 "@aws-sdk/types" "3.190.0"
412 tslib "^2.3.1" 410 tslib "^2.3.1"
413 411
414"@aws-sdk/eventstream-serde-config-resolver@3.162.0": 412"@aws-sdk/eventstream-serde-config-resolver@3.190.0":
415 version "3.162.0" 413 version "3.190.0"
416 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.162.0.tgz#2c5f749262575d44b8ebebff96e243d9c0bbcf38" 414 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.190.0.tgz#9c05e4bd73157d0933bfa7b834ad34138cbac9c1"
417 integrity sha512-1G4IUPrcONzZ0o60CLbv3dOZT9UhT1iOCSRXzdy7XiTQ4rNLpqZVLG8GxNdu2ZpuDoW0ZdpjRDfmnzX+IXAILA== 415 integrity sha512-etlsbvG8KSFQpGzoNazJoNPnN3P/i+IgIo/5D8pEl4R7gkjLAHZYnbk299xfv59olDWn9SVdrZfVx8lS+lUWHA==
418 dependencies: 416 dependencies:
419 "@aws-sdk/types" "3.162.0" 417 "@aws-sdk/types" "3.190.0"
420 tslib "^2.3.1" 418 tslib "^2.3.1"
421 419
422"@aws-sdk/eventstream-serde-node@3.162.0": 420"@aws-sdk/eventstream-serde-node@3.190.0":
423 version "3.162.0" 421 version "3.190.0"
424 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-node/-/eventstream-serde-node-3.162.0.tgz#06676c14b9cea5f179586d47bdbac9c60966efb4" 422 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-node/-/eventstream-serde-node-3.190.0.tgz#de910debb967258be370e10fc8f2b970d936de8e"
425 integrity sha512-bXfgIR/6ZBdu022sTr0dRjEWMI1Z0UKCARYuywygwQ7GtAzhyHaRKrLk59foDX9NkLTExlQCfIRcsW6rMjL+hA== 423 integrity sha512-CmZ1jZJPar1uZAbfMrv00fzGk4NIc+1w4lRxOc0oow18pPSXsUAmefJKcW5ETX609xaH47nO5b7pTuHU8eGgzg==
426 dependencies: 424 dependencies:
427 "@aws-sdk/eventstream-serde-universal" "3.162.0" 425 "@aws-sdk/eventstream-serde-universal" "3.190.0"
428 "@aws-sdk/types" "3.162.0" 426 "@aws-sdk/types" "3.190.0"
429 tslib "^2.3.1" 427 tslib "^2.3.1"
430 428
431"@aws-sdk/eventstream-serde-universal@3.162.0": 429"@aws-sdk/eventstream-serde-universal@3.190.0":
432 version "3.162.0" 430 version "3.190.0"
433 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-universal/-/eventstream-serde-universal-3.162.0.tgz#cf515746715baed3efc9bdac9e28ed29e8546142" 431 resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-universal/-/eventstream-serde-universal-3.190.0.tgz#28eb59946db104e15e63a117b9b3327b21c4da03"
434 integrity sha512-EnZGRWUkZ8d07OuoN+WG1u+ta42b6szf06F+SE2pKhsiAfnHHN3MsfxsnUN/ZYsgSXv6COxdp+acHR8CnjzRMQ== 432 integrity sha512-pioZzWDjjhfCfRIUr5oQdghUMdQV6KtP3lBrOO6rBCFCBOQjnQafqH+a+xRjEw19YvBpMX3tFUrVrUytCN9TDQ==
435 dependencies: 433 dependencies:
436 "@aws-sdk/eventstream-codec" "3.162.0" 434 "@aws-sdk/eventstream-codec" "3.190.0"
437 "@aws-sdk/types" "3.162.0" 435 "@aws-sdk/types" "3.190.0"
438 tslib "^2.3.1" 436 tslib "^2.3.1"
439 437
440"@aws-sdk/fetch-http-handler@3.162.0": 438"@aws-sdk/fetch-http-handler@3.190.0":
441 version "3.162.0" 439 version "3.190.0"
442 resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.162.0.tgz#d90d3f179ff11bedf69b971d22a7c00abba650d9" 440 resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.190.0.tgz#9943c8c9ec3bd9eb9121d3a6c1d356f24f0931a9"
443 integrity sha512-DZLxxEqSMXqKteYohO4w6uoORabpETWso6wBdIFMul1BbEseqLjub1594D5RA18cqkcM2dV4ttw+boPPzOjSAw== 441 integrity sha512-5riRpKydARXAPLesTZm6eP6QKJ4HJGQ3k0Tepi3nvxHVx3UddkRNoX0pLS3rvbajkykWPNC2qdfRGApWlwOYsA==
444 dependencies: 442 dependencies:
445 "@aws-sdk/protocol-http" "3.162.0" 443 "@aws-sdk/protocol-http" "3.190.0"
446 "@aws-sdk/querystring-builder" "3.162.0" 444 "@aws-sdk/querystring-builder" "3.190.0"
447 "@aws-sdk/types" "3.162.0" 445 "@aws-sdk/types" "3.190.0"
448 "@aws-sdk/util-base64-browser" "3.109.0" 446 "@aws-sdk/util-base64-browser" "3.188.0"
449 tslib "^2.3.1" 447 tslib "^2.3.1"
450 448
451"@aws-sdk/hash-blob-browser@3.162.0": 449"@aws-sdk/hash-blob-browser@3.190.0":
452 version "3.162.0" 450 version "3.190.0"
453 resolved "https://registry.yarnpkg.com/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.162.0.tgz#75d1ff18dc3181231b35a131adadfe85cc227e63" 451 resolved "https://registry.yarnpkg.com/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.190.0.tgz#75e7e69bbab4cda4b9f69ef208fc7e1d5f695ca0"
454 integrity sha512-m6d9jSQvV0eNWUOaUEHeP5N5AgjKs+wag+sY+Obr1zQlX1hp5boIauCEhTnm2sJxL5Z2M0bSleb/I0V8RFvYHw== 452 integrity sha512-qRIoUGsy6S6kmqi0LQ+Ma9L5HKm8lIt002z+Yhb4kRTf6PFBWa/A0mDyrcj6L3MV71QGKfAEacV5nrVMF/aIhw==
455 dependencies: 453 dependencies:
456 "@aws-sdk/chunked-blob-reader" "3.55.0" 454 "@aws-sdk/chunked-blob-reader" "3.188.0"
457 "@aws-sdk/chunked-blob-reader-native" "3.109.0" 455 "@aws-sdk/chunked-blob-reader-native" "3.188.0"
458 "@aws-sdk/types" "3.162.0" 456 "@aws-sdk/types" "3.190.0"
459 tslib "^2.3.1" 457 tslib "^2.3.1"
460 458
461"@aws-sdk/hash-node@3.162.0": 459"@aws-sdk/hash-node@3.190.0":
462 version "3.162.0" 460 version "3.190.0"
463 resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.162.0.tgz#72eeba4fe923fc96103740600bcb5a217dc8d338" 461 resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.190.0.tgz#0ecad888142e8c097e13701f7bafc69e3e7ce91e"
464 integrity sha512-lfyyAb0Cd084QnUNLTkYowD8RW3L5Tb9lNnIMH6HY7uSE/obw1j/OnLUPqpey628WJ5DPyyvNBah3Vu+JVZ5Mw== 462 integrity sha512-DNwVT3O8zc9Jk/bXiXcN0WsD98r+JJWryw9F1/ZZbuzbf6rx2qhI8ZK+nh5X6WMtYPU84luQMcF702fJt/1bzg==
465 dependencies: 463 dependencies:
466 "@aws-sdk/types" "3.162.0" 464 "@aws-sdk/types" "3.190.0"
467 "@aws-sdk/util-buffer-from" "3.55.0" 465 "@aws-sdk/util-buffer-from" "3.188.0"
468 tslib "^2.3.1" 466 tslib "^2.3.1"
469 467
470"@aws-sdk/hash-stream-node@3.162.0": 468"@aws-sdk/hash-stream-node@3.190.0":
471 version "3.162.0" 469 version "3.190.0"
472 resolved "https://registry.yarnpkg.com/@aws-sdk/hash-stream-node/-/hash-stream-node-3.162.0.tgz#cfb1e8cc36df4772a339416a5c4c5138064a8648" 470 resolved "https://registry.yarnpkg.com/@aws-sdk/hash-stream-node/-/hash-stream-node-3.190.0.tgz#3173e1febfccfcbc63e581dd355df26f94de2ec9"
473 integrity sha512-WnaKxaK+RIl+MOm3oohyKy1rDduNRTxMhSuLpo9NsZVc6tqZBXQ4Y4fTfND80YP6iyAcao1Gv96Ph8H6wY7yzA== 471 integrity sha512-Itdqn0tRx5bS9A1vy/GzvAtg+KeBwg1MTeiefJQrGsIzh7KitvbFpcDlHZBvId6HPLI0c0aIORucwi9ayEOqjQ==
474 dependencies: 472 dependencies:
475 "@aws-sdk/types" "3.162.0" 473 "@aws-sdk/types" "3.190.0"
476 tslib "^2.3.1" 474 tslib "^2.3.1"
477 475
478"@aws-sdk/invalid-dependency@3.162.0": 476"@aws-sdk/invalid-dependency@3.190.0":
479 version "3.162.0" 477 version "3.190.0"
480 resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.162.0.tgz#a75b29aae362854041ebc4d282746041231109e4" 478 resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.190.0.tgz#a4caa91ce50554f99fbfcba062eca233bb79e280"
481 integrity sha512-ENZ7Jf2EcxMMdAX9/sRrt/1rzeA2WwqAKrjIacKGT9KEGQNU+omWF/h+8stLCu0Uxcg0XswFXgQCXcI1IQuZjg== 479 integrity sha512-crCh63e8d/Uw9y3dQlVTPja7+IZiXpNXyH6oSuAadTDQwMq6KK87Av1/SDzVf6bAo2KgAOo41MyO2joaCEk0dQ==
482 dependencies: 480 dependencies:
483 "@aws-sdk/types" "3.162.0" 481 "@aws-sdk/types" "3.190.0"
484 tslib "^2.3.1" 482 tslib "^2.3.1"
485 483
486"@aws-sdk/is-array-buffer@3.55.0": 484"@aws-sdk/is-array-buffer@3.188.0":
487 version "3.55.0" 485 version "3.188.0"
488 resolved "https://registry.yarnpkg.com/@aws-sdk/is-array-buffer/-/is-array-buffer-3.55.0.tgz#c46122c5636f01d5895e5256a587768c3425ea7a" 486 resolved "https://registry.yarnpkg.com/@aws-sdk/is-array-buffer/-/is-array-buffer-3.188.0.tgz#2e969b2e799490e3bbd5008554aa346c58e3a9b6"
489 integrity sha512-NbiPHVYuPxdqdFd6FxzzN3H1BQn/iWA3ri3Ry7AyLeP/tGs1yzEWMwf8BN8TSMALI0GXT6Sh0GDWy3Ok5xB6DA== 487 integrity sha512-n69N4zJZCNd87Rf4NzufPzhactUeM877Y0Tp/F3KiHqGeTnVjYUa4Lv1vLBjqtfjYb2HWT3NKlYn5yzrhaEwiQ==
490 dependencies: 488 dependencies:
491 tslib "^2.3.1" 489 tslib "^2.3.1"
492 490
493"@aws-sdk/lib-storage@^3.72.0": 491"@aws-sdk/lib-storage@^3.190.0":
494 version "3.165.0" 492 version "3.190.0"
495 resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.165.0.tgz#810dec9b649656ae663ef14b7e1a5a5032363044" 493 resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.190.0.tgz#a7550ab703dc3e45421ad41599c59fb72df81802"
496 integrity sha512-6eM4xQgq4VfIFI8hLnrGXhnynFDnTdIGksE9ejOb6sloOVcqhsrffnWuhGRc4AkK2/LuExY8E+jKbiQjM0h3aQ== 494 integrity sha512-dmjtkMZlIncDOeYHPXEv/wxqT2V8z3l7eYHoILSnT/T1238dYOk06yGH6SyCdIdDxTJq5f06NQIzSCRtzN48EA==
497 dependencies: 495 dependencies:
498 "@aws-sdk/smithy-client" "3.162.0" 496 "@aws-sdk/middleware-endpoint" "3.190.0"
497 "@aws-sdk/smithy-client" "3.190.0"
499 buffer "5.6.0" 498 buffer "5.6.0"
500 events "3.3.0" 499 events "3.3.0"
501 stream-browserify "3.0.0" 500 stream-browserify "3.0.0"
502 tslib "^2.3.1" 501 tslib "^2.3.1"
503 502
504"@aws-sdk/md5-js@3.162.0": 503"@aws-sdk/md5-js@3.190.0":
505 version "3.162.0" 504 version "3.190.0"
506 resolved "https://registry.yarnpkg.com/@aws-sdk/md5-js/-/md5-js-3.162.0.tgz#f469e9dca0eea77ce9d87cf157dc034b834f1144" 505 resolved "https://registry.yarnpkg.com/@aws-sdk/md5-js/-/md5-js-3.190.0.tgz#6d6992a5f2012d36473c39356c89f499e87d33f0"
507 integrity sha512-8rODeZjopffWtnvGOOn3JZghztvxZBAF9a8I6rAUFUveOvyZbxhDZRxdqfGbnNesYBKxZRjU4hjt9dvfmRVSvw== 506 integrity sha512-zeyHnFzKYOgpAS1O+RfLyTRTjo0yLTw3Hooh/GjyuScfjwYG4UqP9kgZHnNLjHS9gXBahtskBOHaBCBGNTVLdw==
508 dependencies: 507 dependencies:
509 "@aws-sdk/types" "3.162.0" 508 "@aws-sdk/types" "3.190.0"
510 "@aws-sdk/util-utf8-browser" "3.109.0" 509 "@aws-sdk/util-utf8-browser" "3.188.0"
511 "@aws-sdk/util-utf8-node" "3.109.0" 510 "@aws-sdk/util-utf8-node" "3.188.0"
512 tslib "^2.3.1" 511 tslib "^2.3.1"
513 512
514"@aws-sdk/middleware-bucket-endpoint@3.162.0": 513"@aws-sdk/middleware-bucket-endpoint@3.190.0":
515 version "3.162.0" 514 version "3.190.0"
516 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.162.0.tgz#7930aa6ecc2248c578996e43b00b4cddd77b8904" 515 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.190.0.tgz#ddb703cdfaf5780351a4f7657bd3fa0e27899c8a"
517 integrity sha512-WkT8BqBN1GzAAzQnkhmyIIhRrZucCY2LdLgXfArYNgzdxFphUJXk19JuKlT8xQHBNENMnCiX+OHupn4prKXQaA== 516 integrity sha512-p1ItehR+NEEBpfPxRpq6VB12qIMWvs/D9ROLRltnIPC6Cf5H0rqWFf2ewT36PkkpL17+rjbt89N7AXLkBgU9NA==
518 dependencies: 517 dependencies:
519 "@aws-sdk/protocol-http" "3.162.0" 518 "@aws-sdk/protocol-http" "3.190.0"
520 "@aws-sdk/types" "3.162.0" 519 "@aws-sdk/types" "3.190.0"
521 "@aws-sdk/util-arn-parser" "3.55.0" 520 "@aws-sdk/util-arn-parser" "3.188.0"
522 "@aws-sdk/util-config-provider" "3.109.0" 521 "@aws-sdk/util-config-provider" "3.188.0"
523 tslib "^2.3.1" 522 tslib "^2.3.1"
524 523
525"@aws-sdk/middleware-content-length@3.162.0": 524"@aws-sdk/middleware-content-length@3.190.0":
526 version "3.162.0" 525 version "3.190.0"
527 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.162.0.tgz#987d77a843598aa52d1045745dbae7e79e763464" 526 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.190.0.tgz#640d2dfeeb1c715a93f8a03048a8458aaf153973"
528 integrity sha512-gwuxHPBNNkr9Ah9gTNHqJ3uIp3zeY+VC2H810+RqkG5QrxU1bGAN/zezIIbcAlXjMM9vTSfO0rxGI04nhTx0BQ== 527 integrity sha512-sSU347SuC6I8kWum1jlJlpAqeV23KP7enG+ToWcEcgFrJhm3AvuqB//NJxDbkKb2DNroRvJjBckBvrwNAjQnBQ==
529 dependencies: 528 dependencies:
530 "@aws-sdk/protocol-http" "3.162.0" 529 "@aws-sdk/protocol-http" "3.190.0"
531 "@aws-sdk/types" "3.162.0" 530 "@aws-sdk/types" "3.190.0"
532 tslib "^2.3.1" 531 tslib "^2.3.1"
533 532
534"@aws-sdk/middleware-expect-continue@3.162.0": 533"@aws-sdk/middleware-endpoint@3.190.0":
535 version "3.162.0" 534 version "3.190.0"
536 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.162.0.tgz#4d3695f82cf950c6b47d227d8382a145e6992053" 535 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.190.0.tgz#dfee34aece9a67598d2aebed1fd0565f740eb806"
537 integrity sha512-6AVKtODhV0mfwAONc67haulkPVlrxNkcgw4gEc4iXTT9ZQiyz4WHUU8hELB0Bkj+7or94BU15fCpUD3rK1VXeQ== 536 integrity sha512-jpsfQ1MuXVOBXtlMAkM/Dy5Qrv70K1V0FkRPYI6zftqfhDSf2sWb5Uc887m904bWwwQE4hIlkQJIPByZVkT0+g==
537 dependencies:
538 "@aws-sdk/middleware-serde" "3.190.0"
539 "@aws-sdk/protocol-http" "3.190.0"
540 "@aws-sdk/signature-v4" "3.190.0"
541 "@aws-sdk/types" "3.190.0"
542 "@aws-sdk/url-parser" "3.190.0"
543 "@aws-sdk/util-config-provider" "3.188.0"
544 "@aws-sdk/util-middleware" "3.190.0"
545 tslib "^2.3.1"
546
547"@aws-sdk/middleware-expect-continue@3.190.0":
548 version "3.190.0"
549 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.190.0.tgz#09167fa3206f663e6e605e11125529b162211df7"
550 integrity sha512-ZE3WY6RQ1uNuFgDn2KHfJXiLbwYgK/a4LX3SWNsO5gCrf9qchHTotkAc8PjFS5x4WV7TkddvhL2i57eikf1cYg==
538 dependencies: 551 dependencies:
539 "@aws-sdk/protocol-http" "3.162.0" 552 "@aws-sdk/protocol-http" "3.190.0"
540 "@aws-sdk/types" "3.162.0" 553 "@aws-sdk/types" "3.190.0"
541 tslib "^2.3.1" 554 tslib "^2.3.1"
542 555
543"@aws-sdk/middleware-flexible-checksums@3.162.0": 556"@aws-sdk/middleware-flexible-checksums@3.190.0":
544 version "3.162.0" 557 version "3.190.0"
545 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.162.0.tgz#f218775cf65c4b28705a72a6f4968df7a48ca171" 558 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.190.0.tgz#e453d92c95b594b05c9515387daa80d09368599f"
546 integrity sha512-KMOOJB+ntqSBVbsNln55Cm+wrPxP0+6dWdRcjuq1NnQqsTHoADiJ+o9+BBYgAFUQR4Q/zWcvxZQ7gTan0W+PLQ== 559 integrity sha512-YcZC2KX5G00RPhZpzFHBru2t27OelKYFG96Tc4cNOnjFmi++t7p5m5ZItFgovv9gUI9vTiI/XBQ+kc1XQ769Xw==
547 dependencies: 560 dependencies:
548 "@aws-crypto/crc32" "2.0.0" 561 "@aws-crypto/crc32" "2.0.0"
549 "@aws-crypto/crc32c" "2.0.0" 562 "@aws-crypto/crc32c" "2.0.0"
550 "@aws-sdk/is-array-buffer" "3.55.0" 563 "@aws-sdk/is-array-buffer" "3.188.0"
551 "@aws-sdk/protocol-http" "3.162.0" 564 "@aws-sdk/protocol-http" "3.190.0"
552 "@aws-sdk/types" "3.162.0" 565 "@aws-sdk/types" "3.190.0"
553 tslib "^2.3.1" 566 tslib "^2.3.1"
554 567
555"@aws-sdk/middleware-host-header@3.162.0": 568"@aws-sdk/middleware-host-header@3.190.0":
556 version "3.162.0" 569 version "3.190.0"
557 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.162.0.tgz#c59015c83f6c574bde72534919022b3a90c3cd2a" 570 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.190.0.tgz#47a01bd9b7db526114097db4659ef7e578881b62"
558 integrity sha512-gw5xe22P62N9yZPvrVXewM2vp70w9mLRWC1vh6pRDs0hEudAlsbXoWjB/z6jpG6ucA4Y1IOuXy5yGr9lND+zhg== 571 integrity sha512-cL7Vo/QSpGx/DDmFxjeV0Qlyi1atvHQDPn3MLBBmi1icu+3GKZkCMAJwzsrV3U4+WoVoDYT9FJ9yMQf2HaIjeQ==
559 dependencies: 572 dependencies:
560 "@aws-sdk/protocol-http" "3.162.0" 573 "@aws-sdk/protocol-http" "3.190.0"
561 "@aws-sdk/types" "3.162.0" 574 "@aws-sdk/types" "3.190.0"
562 tslib "^2.3.1" 575 tslib "^2.3.1"
563 576
564"@aws-sdk/middleware-location-constraint@3.162.0": 577"@aws-sdk/middleware-location-constraint@3.190.0":
565 version "3.162.0" 578 version "3.190.0"
566 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.162.0.tgz#201f3f97099e6d771f7456cec526c235b608c7d3" 579 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.190.0.tgz#bd624370daadb0b47982ea83b7e0ce001286654c"
567 integrity sha512-CnCx4TA8wZa4fnXYiyj37CIkOnppBKokZFu+mbiG6shxXb4tVA8p4PgptOnDRYJHLzgeD4v7B/zMFpUP3o7a8g== 580 integrity sha512-dJ9u7Jb51z9YZLlpvT61og4bzsArJ81cox1t1P990Bbbi+pvJWoiwhwTdLDZhGqTYYg9ZuPd1ajmM2d9NAG/CQ==
568 dependencies: 581 dependencies:
569 "@aws-sdk/types" "3.162.0" 582 "@aws-sdk/types" "3.190.0"
570 tslib "^2.3.1" 583 tslib "^2.3.1"
571 584
572"@aws-sdk/middleware-logger@3.162.0": 585"@aws-sdk/middleware-logger@3.190.0":
573 version "3.162.0" 586 version "3.190.0"
574 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.162.0.tgz#10b2d552d7aa2c48b91061a418224cc47984272c" 587 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.190.0.tgz#022c1c6da76d95b3d04e32179c5b1bdfb3944295"
575 integrity sha512-3YysLwpTZdfZkve2ytKFIwEc/WqDkxoI5kUXQq2hjsHAjLW7pEhUV00o+LJbgKjNxh38eSmmKeFlr5jnIjXHiQ== 588 integrity sha512-rrfLGYSZCBtiXNrIa8pJ2uwUoUMyj6Q82E8zmduTvqKWviCr6ZKes0lttGIkWhjvhql2m4CbjG5MPBnY7RXL4A==
576 dependencies: 589 dependencies:
577 "@aws-sdk/types" "3.162.0" 590 "@aws-sdk/types" "3.190.0"
578 tslib "^2.3.1" 591 tslib "^2.3.1"
579 592
580"@aws-sdk/middleware-recursion-detection@3.162.0": 593"@aws-sdk/middleware-recursion-detection@3.190.0":
581 version "3.162.0" 594 version "3.190.0"
582 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.162.0.tgz#6c13e90ec9cc7b7adcb98bcb3d02eb37cef37b5c" 595 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.190.0.tgz#6b8480ff62d141312f10940b0a0fe44f651e3f8a"
583 integrity sha512-AqoTnSX0JgoFuKPyWy0S+WUJqgfkVz6Os50azi32snjHmluEgLOmfeF0ixfxGFUVGxZp8WDuu/JVhwgTRKVuUA== 596 integrity sha512-5tc1AIIZe5jDNdyuJW+7vIFmQOxz3q031ZVrEtUEIF7cz2ySho2lkOWziz+v+UGSLhjHGKMz3V26+aN1FLZNxQ==
584 dependencies: 597 dependencies:
585 "@aws-sdk/protocol-http" "3.162.0" 598 "@aws-sdk/protocol-http" "3.190.0"
586 "@aws-sdk/types" "3.162.0" 599 "@aws-sdk/types" "3.190.0"
587 tslib "^2.3.1" 600 tslib "^2.3.1"
588 601
589"@aws-sdk/middleware-retry@3.162.0": 602"@aws-sdk/middleware-retry@3.190.0":
590 version "3.162.0" 603 version "3.190.0"
591 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.162.0.tgz#0601882f9105fc440b902a937f630da65914bd99" 604 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.190.0.tgz#935d4097d5785ae14b98272af69aed7ff066786b"
592 integrity sha512-9ZuTim8tnTgP7wNgj+RIdYzGhNgou6QBBX85qMIvngksRUgsd1CGR17HQTyYDZTKlZs7GvLt/L5FaJcOlpPUxA== 605 integrity sha512-h1bPopkncf2ue/erJdhqvgR2AEh0bIvkNsIHhx93DckWKotZd/GAVDq0gpKj7/f/7B+teHH8Fg5GDOwOOGyKcg==
593 dependencies: 606 dependencies:
594 "@aws-sdk/protocol-http" "3.162.0" 607 "@aws-sdk/protocol-http" "3.190.0"
595 "@aws-sdk/service-error-classification" "3.162.0" 608 "@aws-sdk/service-error-classification" "3.190.0"
596 "@aws-sdk/types" "3.162.0" 609 "@aws-sdk/types" "3.190.0"
597 "@aws-sdk/util-middleware" "3.162.0" 610 "@aws-sdk/util-middleware" "3.190.0"
598 tslib "^2.3.1" 611 tslib "^2.3.1"
599 uuid "^8.3.2" 612 uuid "^8.3.2"
600 613
601"@aws-sdk/middleware-sdk-s3@3.165.0": 614"@aws-sdk/middleware-sdk-s3@3.190.0":
602 version "3.165.0" 615 version "3.190.0"
603 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.165.0.tgz#7181f9f2efec56fd85d98c845bf996d8d109d5e3" 616 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.190.0.tgz#27f5d760896d76ea66e9fa4531b7cb3fb80654d4"
604 integrity sha512-OaCQqrgvJLdCVmBwSvQ/woYyDfYuOHUY4i7hl/DDH20QGq1n/CE8g7BBvFVqEaptin0dunFVHOOgzopmVpmOUQ== 617 integrity sha512-ixN3OOnF95Pla2Q9c4EyUpZk0TR5yYGbV1/eZqz5M9n2Iy1t6H11ZYSmK0BH3YjWG6Tdqva0AIwCfuvoUXWGZg==
605 dependencies: 618 dependencies:
606 "@aws-sdk/middleware-bucket-endpoint" "3.162.0" 619 "@aws-sdk/middleware-bucket-endpoint" "3.190.0"
607 "@aws-sdk/protocol-http" "3.162.0" 620 "@aws-sdk/protocol-http" "3.190.0"
608 "@aws-sdk/types" "3.162.0" 621 "@aws-sdk/types" "3.190.0"
609 "@aws-sdk/util-arn-parser" "3.55.0" 622 "@aws-sdk/util-arn-parser" "3.188.0"
610 tslib "^2.3.1" 623 tslib "^2.3.1"
611 624
612"@aws-sdk/middleware-sdk-sts@3.163.0": 625"@aws-sdk/middleware-sdk-sts@3.190.0":
613 version "3.163.0" 626 version "3.190.0"
614 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.163.0.tgz#362eedb0739c3b4e98aa1154cc5c6f38d7e18f68" 627 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.190.0.tgz#4606c41658f6d0ff2ff9b11bd2fc3a35f8ebd1ea"
615 integrity sha512-3UV0O5D3HPF5xHsIrDiygs06wmGVnoAXsyrqcZSPkYig9eGP6lTL1I8YS8JIG9/VojQDKjDUpQZMC3Om0+C7hA== 628 integrity sha512-eUHrsr35mkD/cAFKoYuFYz0zE7QPBWvSzMzqmEJC+YXzAF6IABP3FL/htAFpWkje5XDl5dQ6dAxzV+ebK8RNXQ==
616 dependencies: 629 dependencies:
617 "@aws-sdk/middleware-signing" "3.163.0" 630 "@aws-sdk/middleware-signing" "3.190.0"
618 "@aws-sdk/property-provider" "3.162.0" 631 "@aws-sdk/property-provider" "3.190.0"
619 "@aws-sdk/protocol-http" "3.162.0" 632 "@aws-sdk/protocol-http" "3.190.0"
620 "@aws-sdk/signature-v4" "3.163.0" 633 "@aws-sdk/signature-v4" "3.190.0"
621 "@aws-sdk/types" "3.162.0" 634 "@aws-sdk/types" "3.190.0"
622 tslib "^2.3.1" 635 tslib "^2.3.1"
623 636
624"@aws-sdk/middleware-serde@3.162.0": 637"@aws-sdk/middleware-serde@3.190.0":
625 version "3.162.0" 638 version "3.190.0"
626 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.162.0.tgz#e83201bffd46500ed4ea71bb3ceda63505f31f96" 639 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.190.0.tgz#85f17432facfa8453564a5b5cd2d24e722eeff9f"
627 integrity sha512-Vdgxbl7/o99CjeljQx3mTpY4cX7rc8YQykD49L2S61D6+Gkk9Zc4DMvaJDcxvR7ZUzRwjMTcMHlxbopcp1+UBA== 640 integrity sha512-S132hEOK4jwbtZ1bGAgSuQ0DMFG4TiD4ulAwbQRBYooC7tiWZbRiR0Pkt2hV8d7WhOHgUpg7rvqlA7/HXXBAsA==
628 dependencies: 641 dependencies:
629 "@aws-sdk/types" "3.162.0" 642 "@aws-sdk/types" "3.190.0"
630 tslib "^2.3.1" 643 tslib "^2.3.1"
631 644
632"@aws-sdk/middleware-signing@3.163.0": 645"@aws-sdk/middleware-signing@3.190.0":
633 version "3.163.0" 646 version "3.190.0"
634 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.163.0.tgz#9ecc4bdeb1e2b67ab777808818f86ebde9e64578" 647 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.190.0.tgz#32fc668c6ea7e632c1dd0eaacd78c71ff522dc77"
635 integrity sha512-Uj5vdejYUJOCJAx5u/SHWQTp75bd7GVqnXazO3QFHRjhSCMT55wsm8D+7LKRNbp4SjavO49m9kubXf+pLpqlJQ== 648 integrity sha512-Xj5MmXZq8UIpY8wOwyqei5q6MgqKxsO9Plo2zUgW7JR0w7R21MlqY2kzzvcM9R0FFhi9dqhniFT2ZMRUb1v73w==
636 dependencies: 649 dependencies:
637 "@aws-sdk/property-provider" "3.162.0" 650 "@aws-sdk/property-provider" "3.190.0"
638 "@aws-sdk/protocol-http" "3.162.0" 651 "@aws-sdk/protocol-http" "3.190.0"
639 "@aws-sdk/signature-v4" "3.163.0" 652 "@aws-sdk/signature-v4" "3.190.0"
640 "@aws-sdk/types" "3.162.0" 653 "@aws-sdk/types" "3.190.0"
654 "@aws-sdk/util-middleware" "3.190.0"
641 tslib "^2.3.1" 655 tslib "^2.3.1"
642 656
643"@aws-sdk/middleware-ssec@3.162.0": 657"@aws-sdk/middleware-ssec@3.190.0":
644 version "3.162.0" 658 version "3.190.0"
645 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.162.0.tgz#2fcda524b9582a3fcec4124037b3cc3e2d81c453" 659 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.190.0.tgz#8519077c258ed503953220bb004b2e338ecdd19d"
646 integrity sha512-hCPivyliCIQ3nncVJmwxhLiWiuMpk3aQYclhhg//KW8xke7UFr9Q6WD8wzINMWFnBOmsNq1guRi3uVjz6K9m2g== 660 integrity sha512-nwggMCfXBmhcDIrV/oPeSeuE1FRk0xvi/2PBuYYhM+xnkfUYovYUcdJhGkNqt7U1Mk0+CR2VVwozreigfcLesg==
647 dependencies: 661 dependencies:
648 "@aws-sdk/types" "3.162.0" 662 "@aws-sdk/types" "3.190.0"
649 tslib "^2.3.1" 663 tslib "^2.3.1"
650 664
651"@aws-sdk/middleware-stack@3.162.0": 665"@aws-sdk/middleware-stack@3.190.0":
652 version "3.162.0" 666 version "3.190.0"
653 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.162.0.tgz#26b37e6241ca5c1a5e50bb2b1367a39eabd2b5ad" 667 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.190.0.tgz#15572c938bf3bbe9d275870e541360fdc7997fab"
654 integrity sha512-e/by4QvDl9qMQHdBnLz6n8PRglswPb3eS23qT2Wt32KVLUehMUGAf1cdns6YmYSHATK/ivFmT2QHHEnNIc+n5w== 668 integrity sha512-h1mqiWNJdi1OTSEY8QovpiHgDQEeRG818v8yShpqSYXJKEqdn54MA3Z1D2fg/Wv/8ZJsFrBCiI7waT1JUYOmCg==
655 dependencies: 669 dependencies:
656 tslib "^2.3.1" 670 tslib "^2.3.1"
657 671
658"@aws-sdk/middleware-user-agent@3.162.0": 672"@aws-sdk/middleware-user-agent@3.190.0":
659 version "3.162.0" 673 version "3.190.0"
660 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.162.0.tgz#da374bd9c66efc563ee9a2f6d1fff29c5ebea965" 674 resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.190.0.tgz#791eb451b01846184140eeda63dd51153f911c2c"
661 integrity sha512-aSCQk+oQbMPVHdncuend4jmd4MguLWjvi67OwKqdZjIKsSQfObCO8vwlfDM+ED3HcOfA0LwSxsFeSfQxC+WHxA== 675 integrity sha512-y/2cTE1iYHKR0nkb3DvR3G8vt12lcTP95r/iHp8ZO+Uzpc25jM/AyMHWr2ZjqQiHKNlzh8uRw1CmQtgg4sBxXQ==
662 dependencies: 676 dependencies:
663 "@aws-sdk/protocol-http" "3.162.0" 677 "@aws-sdk/protocol-http" "3.190.0"
664 "@aws-sdk/types" "3.162.0" 678 "@aws-sdk/types" "3.190.0"
665 tslib "^2.3.1" 679 tslib "^2.3.1"
666 680
667"@aws-sdk/node-config-provider@3.162.0": 681"@aws-sdk/node-config-provider@3.190.0":
668 version "3.162.0" 682 version "3.190.0"
669 resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.162.0.tgz#9637996fd5ef18ce4619b927744727d2aff0d508" 683 resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.190.0.tgz#a6005c5d3393970e1682c2561c5622d36d05c35d"
670 integrity sha512-PgaekXCCyz/gKkbukt9zYLBJDEVgmCm0l78q5J84yJbu0FhcZY4LaAgCHdzhsgEYWTX497hokzNc3rgLdVu46A== 684 integrity sha512-TJPUchyeK5KeEXWrwb6oW5/OkY3STCSGR1QIlbPcaTGkbo4kXAVyQmmZsY4KtRPuDM6/HlfUQV17bD716K65rQ==
671 dependencies: 685 dependencies:
672 "@aws-sdk/property-provider" "3.162.0" 686 "@aws-sdk/property-provider" "3.190.0"
673 "@aws-sdk/shared-ini-file-loader" "3.162.0" 687 "@aws-sdk/shared-ini-file-loader" "3.190.0"
674 "@aws-sdk/types" "3.162.0" 688 "@aws-sdk/types" "3.190.0"
675 tslib "^2.3.1" 689 tslib "^2.3.1"
676 690
677"@aws-sdk/node-http-handler@3.162.0", "@aws-sdk/node-http-handler@^3.82.0": 691"@aws-sdk/node-http-handler@3.190.0", "@aws-sdk/node-http-handler@^3.190.0":
678 version "3.162.0" 692 version "3.190.0"
679 resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.162.0.tgz#771370fe09cc3b030666a6654cf1e461e6fe3cf1" 693 resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.190.0.tgz#db14e265a5d42587b3edca0e71fa47f530d8c81b"
680 integrity sha512-9jNk9SU3nNLZ1OW+fd6zHGdByUDm0FEO3Hy+J62DvbFe16x09TnVnPAoHfZ69kjz5ZNS7Gg0wmdKjUHi9T3lJQ== 694 integrity sha512-3Klkr73TpZkCzcnSP+gmFF0Baluzk3r7BaWclJHqt2LcFUWfIJzYlnbBQNZ4t3EEq7ZlBJX85rIDHBRlS+rUyA==
681 dependencies: 695 dependencies:
682 "@aws-sdk/abort-controller" "3.162.0" 696 "@aws-sdk/abort-controller" "3.190.0"
683 "@aws-sdk/protocol-http" "3.162.0" 697 "@aws-sdk/protocol-http" "3.190.0"
684 "@aws-sdk/querystring-builder" "3.162.0" 698 "@aws-sdk/querystring-builder" "3.190.0"
685 "@aws-sdk/types" "3.162.0" 699 "@aws-sdk/types" "3.190.0"
686 tslib "^2.3.1" 700 tslib "^2.3.1"
687 701
688"@aws-sdk/property-provider@3.162.0": 702"@aws-sdk/property-provider@3.190.0":
689 version "3.162.0" 703 version "3.190.0"
690 resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.162.0.tgz#45cdaadfba54bb1c275972f12f33f72c8eb22333" 704 resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.190.0.tgz#99372b7e2fba63d3f47ea368c9659ef003733e57"
691 integrity sha512-kQLpibZRIrF58axcKY4Pr17YGoVBKBOWKol8jI8vlDhbFJqn14pVLohv4wZ8TzG2kKhWCF+t25YQCefWz2/lkg== 705 integrity sha512-uzdKjHE2blbuceTC5zeBgZ0+Uo/hf9pH20CHpJeVNtrrtF3GALtu4Y1Gu5QQVIQBz8gjHnqANx0XhfYzorv69Q==
692 dependencies: 706 dependencies:
693 "@aws-sdk/types" "3.162.0" 707 "@aws-sdk/types" "3.190.0"
694 tslib "^2.3.1" 708 tslib "^2.3.1"
695 709
696"@aws-sdk/protocol-http@3.162.0": 710"@aws-sdk/protocol-http@3.190.0":
697 version "3.162.0" 711 version "3.190.0"
698 resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.162.0.tgz#3657cb6627576180d8c5a9a37d6c3f2984d70f92" 712 resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.190.0.tgz#6f777f4f5193fc83402fdce29d8fc2bd0c93fb05"
699 integrity sha512-xMFFxwcO+x5QoQX/LRGb3BpLCIBWC9cBOULm34rYGBySd/zQqebVJOhiKTPzaRL02WZTDNxsEEQHg97Lpe8CNw== 713 integrity sha512-s5MVfeONpfZYRzCSbqQ+wJ3GxKED+aSS7+CQoeaYoD6HDTDxaMGNv9aiPxVCzW02sgG7py7f29Q6Vw+5taZXZA==
700 dependencies: 714 dependencies:
701 "@aws-sdk/types" "3.162.0" 715 "@aws-sdk/types" "3.190.0"
702 tslib "^2.3.1" 716 tslib "^2.3.1"
703 717
704"@aws-sdk/querystring-builder@3.162.0": 718"@aws-sdk/querystring-builder@3.190.0":
705 version "3.162.0" 719 version "3.190.0"
706 resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.162.0.tgz#c1667eebeb0e15ac6cae2523afa5ea3a8ca8aa00" 720 resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.190.0.tgz#5c115eb30343cc28ea8fc6ab1ca945907533403a"
707 integrity sha512-3urwxCEpnQwa1B6fKmcr8R2Qmzr8VDttRSay5CgD/stbZ4XUzNsA6G1V36+EL1Vq4vMr1aZhriARioLDlhcz+g== 721 integrity sha512-w9mTKkCsaLIBC8EA4RAHrqethNGbf60CbpPzN/QM7yCV3ZZJAXkppFfjTVVOMbPaI8GUEOptJtzgqV68CRB7ow==
708 dependencies: 722 dependencies:
709 "@aws-sdk/types" "3.162.0" 723 "@aws-sdk/types" "3.190.0"
710 "@aws-sdk/util-uri-escape" "3.55.0" 724 "@aws-sdk/util-uri-escape" "3.188.0"
711 tslib "^2.3.1" 725 tslib "^2.3.1"
712 726
713"@aws-sdk/querystring-parser@3.162.0": 727"@aws-sdk/querystring-parser@3.190.0":
714 version "3.162.0" 728 version "3.190.0"
715 resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.162.0.tgz#d4f0522cfe2a44d2f242a2e5c9c9cf928930938e" 729 resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.190.0.tgz#e96fab0ac834ab57777d736790eb2509491bd3fa"
716 integrity sha512-0ccaGsR1O7e3BsprdYBMwGf8gmycTv1Dfz2EB5R6MiTqzcuQJ/lxpIcRh3jhUJaD1TPlUziyrBEAxtLka3HDDQ== 730 integrity sha512-vCKP0s33VtS47LSYzEWRRr2aTbi3qNkUuQyIrc5LMqBfS5hsy79P1HL4Q7lCVqZB5fe61N8fKzOxDxWRCF0sXg==
717 dependencies: 731 dependencies:
718 "@aws-sdk/types" "3.162.0" 732 "@aws-sdk/types" "3.190.0"
719 tslib "^2.3.1" 733 tslib "^2.3.1"
720 734
721"@aws-sdk/service-error-classification@3.162.0": 735"@aws-sdk/service-error-classification@3.190.0":
722 version "3.162.0" 736 version "3.190.0"
723 resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.162.0.tgz#b07ed4ef541ec4d3d3cfe93efae054e3d39b5a1b" 737 resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.190.0.tgz#b1e232abfdc98fcf6f12dcbe50f9b9141fe53d42"
724 integrity sha512-AD9XL3CHFzwVWNEzdTo9aRnJl1ImqrRLlJ5zR/5ihTIJ68ZTYEiYP4vNKSCV6UfQ+vaaRNgLwiAx7JXzY54awg== 738 integrity sha512-g+s6xtaMa5fCMA2zJQC4BiFGMP7FN5/L1V/UwxCnKy8skCwaN0K5A1tFffBjjbYiPI7Gu7LVorWD2A0Y4xl01Q==
725 739
726"@aws-sdk/shared-ini-file-loader@3.162.0": 740"@aws-sdk/shared-ini-file-loader@3.190.0":
727 version "3.162.0" 741 version "3.190.0"
728 resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.162.0.tgz#53bc40d774f4411200104e415cbe27a3dea110f7" 742 resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.190.0.tgz#23efb053ae56f7cb96cb1cb64e8afeffafac963c"
729 integrity sha512-AGxISXns+1o6Pw+SPizFJDTw4Lwm+JSwhycCNhFU3JfdLsKfLY08JV4JHlcc+TyY4a8HhnGvE3r5t2f2dPLIsA== 743 integrity sha512-CZC/xsGReUEl5w+JgfancrxfkaCbEisyIFy6HALUYrioWQe80WMqLAdUMZSXHWjIaNK9mH0J/qvcSV2MuIoMzQ==
730 dependencies: 744 dependencies:
745 "@aws-sdk/types" "3.190.0"
731 tslib "^2.3.1" 746 tslib "^2.3.1"
732 747
733"@aws-sdk/signature-v4-multi-region@3.163.0": 748"@aws-sdk/signature-v4-multi-region@3.190.0":
734 version "3.163.0" 749 version "3.190.0"
735 resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.163.0.tgz#e1d58d6dd40c4530d6ae83f8ebc0ad33a64f5d7c" 750 resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.190.0.tgz#f3971e238362b3128dcf536142277f4123ddafed"
736 integrity sha512-SIb6e1dFNchvWziKudh7+BbYjUDW7WAEWWz419pKj/WDGdZNaA7dj7rr4IAB9vbi6QqzkECGDszdMqriWbJrDg== 751 integrity sha512-i9BpqlY3kAF8l8amqJ4skyjrlBy4B3hhO4RPu1D1wF4+GsJ5JGZ638Y5bYMH90k7A7ycTDDgFWHJcAsm1b0fEQ==
737 dependencies: 752 dependencies:
738 "@aws-sdk/protocol-http" "3.162.0" 753 "@aws-sdk/protocol-http" "3.190.0"
739 "@aws-sdk/signature-v4" "3.163.0" 754 "@aws-sdk/signature-v4" "3.190.0"
740 "@aws-sdk/types" "3.162.0" 755 "@aws-sdk/types" "3.190.0"
741 "@aws-sdk/util-arn-parser" "3.55.0" 756 "@aws-sdk/util-arn-parser" "3.188.0"
742 tslib "^2.3.1" 757 tslib "^2.3.1"
743 758
744"@aws-sdk/signature-v4@3.163.0": 759"@aws-sdk/signature-v4@3.190.0":
745 version "3.163.0" 760 version "3.190.0"
746 resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.163.0.tgz#6a083fd0fe285b07ca71fc88990c7a9440b7c0b2" 761 resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.190.0.tgz#ed5a408465723021648fd95440234898e114e2f6"
747 integrity sha512-1iein+7iAHKcRIXaZhl/lG6JrOR/Qmk27zMqfARzxDF7o/W5arSs3DHIKytO1sOEn9zV6Mqm21dRAumD21VCCg== 762 integrity sha512-L/R/1X2T+/Kg2k/sjoYyDFulVUGrVcRfyEKKVFIUNg0NwUtw5UKa1/gS7geTKcg4q8M2pd/v+OCBrge2X7phUw==
748 dependencies: 763 dependencies:
749 "@aws-sdk/is-array-buffer" "3.55.0" 764 "@aws-sdk/is-array-buffer" "3.188.0"
750 "@aws-sdk/types" "3.162.0" 765 "@aws-sdk/types" "3.190.0"
751 "@aws-sdk/util-hex-encoding" "3.109.0" 766 "@aws-sdk/util-hex-encoding" "3.188.0"
752 "@aws-sdk/util-middleware" "3.162.0" 767 "@aws-sdk/util-middleware" "3.190.0"
753 "@aws-sdk/util-uri-escape" "3.55.0" 768 "@aws-sdk/util-uri-escape" "3.188.0"
754 tslib "^2.3.1" 769 tslib "^2.3.1"
755 770
756"@aws-sdk/smithy-client@3.162.0": 771"@aws-sdk/smithy-client@3.190.0":
757 version "3.162.0" 772 version "3.190.0"
758 resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.162.0.tgz#2646b05c287a609a1abb7d28a7009f3314c26803" 773 resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.190.0.tgz#4a951a7f3470fe148330e3a3e68cf9020b148e64"
759 integrity sha512-o7CwdhPvzYMvHY5dTzL2kqN8Zsl2D8pZ1mG2dPdQW9hYnutLOFK1HVv5dIzoSkp3jUwVGh6AXd1i4ZSb2d0LrA== 774 integrity sha512-f5EoCwjBLXMyuN491u1NmEutbolL0cJegaJbtgK9OJw2BLuRHiBknjDF4OEVuK/WqK0kz2JLMGi9xwVPl4BKCA==
760 dependencies: 775 dependencies:
761 "@aws-sdk/middleware-stack" "3.162.0" 776 "@aws-sdk/middleware-stack" "3.190.0"
762 "@aws-sdk/types" "3.162.0" 777 "@aws-sdk/types" "3.190.0"
763 tslib "^2.3.1" 778 tslib "^2.3.1"
764 779
765"@aws-sdk/types@3.162.0", "@aws-sdk/types@^3.1.0", "@aws-sdk/types@^3.110.0": 780"@aws-sdk/types@3.190.0":
781 version "3.190.0"
782 resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.190.0.tgz#ef22549c81ea6a7dd2c57e5869e787fea40c4434"
783 integrity sha512-mkeZ+vJZzElP6OdRXvuLKWHSlDQxZP9u8BjQB9N0Rw0pCXTzYS0vzIhN1pL0uddWp5fMrIE68snto9xNR6BQuA==
784
785"@aws-sdk/types@^3.1.0", "@aws-sdk/types@^3.110.0":
766 version "3.162.0" 786 version "3.162.0"
767 resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.162.0.tgz#e908ff1a5de6bd06d7d6b88a648b384592acf7e2" 787 resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.162.0.tgz#e908ff1a5de6bd06d7d6b88a648b384592acf7e2"
768 integrity sha512-NBmuwVujH8fURDMvBHkHrYu/JAfG6Js/Bu0mC4o2Kdo5mRa3fD/N9kK0dEAxU1Rxp4wY2E++V9j2ZCw1KBGrSg== 788 integrity sha512-NBmuwVujH8fURDMvBHkHrYu/JAfG6Js/Bu0mC4o2Kdo5mRa3fD/N9kK0dEAxU1Rxp4wY2E++V9j2ZCw1KBGrSg==
769 789
770"@aws-sdk/url-parser@3.162.0": 790"@aws-sdk/url-parser@3.190.0":
771 version "3.162.0" 791 version "3.190.0"
772 resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.162.0.tgz#ce341d3b6dbcaf52f00b80aff56b24b5ab8c1e82" 792 resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.190.0.tgz#d3c40dd0d01fb97c2c7f610baf1be2f045ae5582"
773 integrity sha512-aJQ2awXYDceLAzPMQETpvI1XQd8oYuqH1EriFzXHqoJTNmYnHb7awtKSqwaS8pq48x1rS/eVtJAi85BG93fXyw== 793 integrity sha512-FKFDtxA9pvHmpfWmNVK5BAVRpDgkWMz3u4Sg9UzB+WAFN6UexRypXXUZCFAo8S04FbPKfYOR3O0uVlw7kzmj9g==
774 dependencies: 794 dependencies:
775 "@aws-sdk/querystring-parser" "3.162.0" 795 "@aws-sdk/querystring-parser" "3.190.0"
776 "@aws-sdk/types" "3.162.0" 796 "@aws-sdk/types" "3.190.0"
777 tslib "^2.3.1" 797 tslib "^2.3.1"
778 798
779"@aws-sdk/util-arn-parser@3.55.0": 799"@aws-sdk/util-arn-parser@3.188.0":
780 version "3.55.0" 800 version "3.188.0"
781 resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.55.0.tgz#6672eb2975e798a460bedfaf6b5618d4e4b262e1" 801 resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.188.0.tgz#4df0144c00dce3490666da7d55e6e13c9a3f21b2"
782 integrity sha512-76KJxp4MRWufHYWys7DFl64znr5yeJ3AIQNAPCKKw1sP0hzO7p6Kx0PaJnw9x+CPSzOrT4NbuApL6/srYhKDGg== 802 integrity sha512-q4nZzt/g3sRY9a3sj1PaNFwql5bXfKSW4fRy0zLdbZHcYdgq2oQfVsJTIlL9lUNjifkXiIsmk61Q16JExtrLyw==
783 dependencies: 803 dependencies:
784 tslib "^2.3.1" 804 tslib "^2.3.1"
785 805
786"@aws-sdk/util-base64-browser@3.109.0": 806"@aws-sdk/util-base64-browser@3.188.0":
787 version "3.109.0" 807 version "3.188.0"
788 resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64-browser/-/util-base64-browser-3.109.0.tgz#e7faf5c4cbb88bc39b9c1c5a1a79e4c869e9f645" 808 resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64-browser/-/util-base64-browser-3.188.0.tgz#581c85dc157aff88ca81e42d9c79d87c95db8d03"
789 integrity sha512-lAZ6fyDGiRLaIsKT9qh7P9FGuNyZ4gAbr1YOSQk/5mHtaTuUvxlPptZuInNM/0MPQm6lpcot00D8IWTucn4PbA== 809 integrity sha512-qlH+5NZBLiyKziL335BEPedYxX6j+p7KFRWXvDQox9S+s+gLCayednpK+fteOhBenCcR9fUZOVuAPScy1I8qCg==
790 dependencies: 810 dependencies:
791 tslib "^2.3.1" 811 tslib "^2.3.1"
792 812
793"@aws-sdk/util-base64-node@3.55.0": 813"@aws-sdk/util-base64-node@3.188.0":
794 version "3.55.0" 814 version "3.188.0"
795 resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64-node/-/util-base64-node-3.55.0.tgz#da9a3fd6752be49163572144793e6b23d0186ff4" 815 resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64-node/-/util-base64-node-3.188.0.tgz#1d2413f68c8ad1cca0903fc11d92af88ba70e14d"
796 integrity sha512-UQ/ZuNoAc8CFMpSiRYmevaTsuRKzLwulZTnM8LNlIt9Wx1tpNvqp80cfvVj7yySKROtEi20wq29h31dZf1eYNQ== 816 integrity sha512-r1dccRsRjKq+OhVRUfqFiW3sGgZBjHbMeHLbrAs9jrOjU2PTQ8PSzAXLvX/9lmp7YjmX17Qvlsg0NCr1tbB9OA==
797 dependencies: 817 dependencies:
798 "@aws-sdk/util-buffer-from" "3.55.0" 818 "@aws-sdk/util-buffer-from" "3.188.0"
799 tslib "^2.3.1" 819 tslib "^2.3.1"
800 820
801"@aws-sdk/util-body-length-browser@3.154.0": 821"@aws-sdk/util-body-length-browser@3.188.0":
802 version "3.154.0" 822 version "3.188.0"
803 resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.154.0.tgz#8c4c5d08c1923deeedf46006dc4db820ca606f56" 823 resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz#e1d949318c10a621b38575a9ef01e39f9857ddb0"
804 integrity sha512-TUuy7paVkBRQrB/XFCsL8iTW6g/ma0S3N8dYOiIMJdeTqTFryeyOGkBpYBgYFQL6zRMZpyu0jOM7GYEffGFOXw== 824 integrity sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==
805 dependencies: 825 dependencies:
806 tslib "^2.3.1" 826 tslib "^2.3.1"
807 827
808"@aws-sdk/util-body-length-node@3.55.0": 828"@aws-sdk/util-body-length-node@3.188.0":
809 version "3.55.0" 829 version "3.188.0"
810 resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-node/-/util-body-length-node-3.55.0.tgz#67049bbb6c62d794a1bb5a13b9a678988c925489" 830 resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-node/-/util-body-length-node-3.188.0.tgz#3fc2a820b9be0efcbdf962d8f980b9000b98ddba"
811 integrity sha512-lU1d4I+9wJwydduXs0SxSfd+mHKjxeyd39VwOv6i2KSwWkPbji9UQqpflKLKw+r45jL7+xU/zfeTUg5Tt/3Gew== 831 integrity sha512-XwqP3vxk60MKp4YDdvDeCD6BPOiG2e+/Ou4AofZOy5/toB6NKz2pFNibQIUg2+jc7mPMnGnvOW3MQEgSJ+gu/Q==
812 dependencies: 832 dependencies:
813 tslib "^2.3.1" 833 tslib "^2.3.1"
814 834
815"@aws-sdk/util-buffer-from@3.55.0": 835"@aws-sdk/util-buffer-from@3.188.0":
816 version "3.55.0" 836 version "3.188.0"
817 resolved "https://registry.yarnpkg.com/@aws-sdk/util-buffer-from/-/util-buffer-from-3.55.0.tgz#e7c927974b07a29502aa1ad58509b91d0d7cf0f7" 837 resolved "https://registry.yarnpkg.com/@aws-sdk/util-buffer-from/-/util-buffer-from-3.188.0.tgz#a062ccd990571df4353990e8b78aebec5a14547d"
818 integrity sha512-uVzKG1UgvnV7XX2FPTylBujYMKBPBaq/qFBxfl0LVNfrty7YjpfieQxAe6yRLD+T0Kir/WDQwGvYC+tOYG3IGA== 838 integrity sha512-NX1WXZ8TH20IZb4jPFT2CnLKSqZWddGxtfiWxD9M47YOtq/SSQeR82fhqqVjJn4P8w2F5E28f+Du4ntg/sGcxA==
819 dependencies: 839 dependencies:
820 "@aws-sdk/is-array-buffer" "3.55.0" 840 "@aws-sdk/is-array-buffer" "3.188.0"
821 tslib "^2.3.1" 841 tslib "^2.3.1"
822 842
823"@aws-sdk/util-config-provider@3.109.0": 843"@aws-sdk/util-config-provider@3.188.0":
824 version "3.109.0" 844 version "3.188.0"
825 resolved "https://registry.yarnpkg.com/@aws-sdk/util-config-provider/-/util-config-provider-3.109.0.tgz#7828b8894b2b23c289ffc5c106cbced7a5d6ee86" 845 resolved "https://registry.yarnpkg.com/@aws-sdk/util-config-provider/-/util-config-provider-3.188.0.tgz#f7a365e6cbfe728c1224f0b39926636619b669e0"
826 integrity sha512-GrAZl/aBv0A28LkyNyq8SPJ5fmViCwz80fWLMeWx/6q5AbivuILogjlWwEZSvZ9zrlHOcFC0+AnCa5pQrjaslw== 846 integrity sha512-LBA7tLbi7v4uvbOJhSnjJrxbcRifKK/1ZVK94JTV2MNSCCyNkFotyEI5UWDl10YKriTIUyf7o5cakpiDZ3O4xg==
827 dependencies: 847 dependencies:
828 tslib "^2.3.1" 848 tslib "^2.3.1"
829 849
830"@aws-sdk/util-defaults-mode-browser@3.162.0": 850"@aws-sdk/util-defaults-mode-browser@3.190.0":
831 version "3.162.0" 851 version "3.190.0"
832 resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.162.0.tgz#41625d5ea4d3d347df00cc5647a0808fcb059c94" 852 resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.190.0.tgz#b544c978ae4e5a7cf12bb7975c0199dbe3517c85"
833 integrity sha512-BjhuriainNy0ezFqCK//380Wc4xsJJOnq1tmPlHScQxp3g8ucfClvjOUi96XQaTrEf8c8EsYp77+JNsvrHytmw== 853 integrity sha512-FKxTU4tIbFk2pdUbBNneStF++j+/pB4NYJ1HRSEAb/g4D2+kxikR/WKIv3p0JTVvAkwcuX/ausILYEPUyDZ4HQ==
834 dependencies: 854 dependencies:
835 "@aws-sdk/property-provider" "3.162.0" 855 "@aws-sdk/property-provider" "3.190.0"
836 "@aws-sdk/types" "3.162.0" 856 "@aws-sdk/types" "3.190.0"
837 bowser "^2.11.0" 857 bowser "^2.11.0"
838 tslib "^2.3.1" 858 tslib "^2.3.1"
839 859
840"@aws-sdk/util-defaults-mode-node@3.163.0": 860"@aws-sdk/util-defaults-mode-node@3.190.0":
841 version "3.163.0" 861 version "3.190.0"
842 resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.163.0.tgz#9cb4d5b0b1beb9573b11289eee46c762d3a9c0bd" 862 resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.190.0.tgz#67acd5a3dba7f30ac2fb30084dd2b9ff77612c15"
843 integrity sha512-IM5BVeUXzLpb9m8qBSpUc2iO+topP1F7Ojq1GNrl5G/b22f7b1FCL5qkTem/UIXkkgI+efI7jr05xPRGiU73Hg== 863 integrity sha512-qBiIMjNynqAP7p6urG1+ZattYkFaylhyinofVcLEiDvM9a6zGt6GZsxru2Loq0kRAXXGew9E9BWGt45HcDc20g==
844 dependencies: 864 dependencies:
845 "@aws-sdk/config-resolver" "3.163.0" 865 "@aws-sdk/config-resolver" "3.190.0"
846 "@aws-sdk/credential-provider-imds" "3.162.0" 866 "@aws-sdk/credential-provider-imds" "3.190.0"
847 "@aws-sdk/node-config-provider" "3.162.0" 867 "@aws-sdk/node-config-provider" "3.190.0"
848 "@aws-sdk/property-provider" "3.162.0" 868 "@aws-sdk/property-provider" "3.190.0"
849 "@aws-sdk/types" "3.162.0" 869 "@aws-sdk/types" "3.190.0"
850 tslib "^2.3.1" 870 tslib "^2.3.1"
851 871
852"@aws-sdk/util-hex-encoding@3.109.0": 872"@aws-sdk/util-hex-encoding@3.188.0":
853 version "3.109.0" 873 version "3.188.0"
854 resolved "https://registry.yarnpkg.com/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.109.0.tgz#93b20acc27c0a1d7d80f653bf19d3dd01c2ccc65" 874 resolved "https://registry.yarnpkg.com/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.188.0.tgz#c2d8b02b952db58acbd5f53718109657c69c460f"
855 integrity sha512-s8CgTNrn3cLkrdiohfxLuOYPCanzvHn/aH5RW6DaMoeQiG5Hl9QUiP/WtdQ9QQx3xvpQFpmvxIaSBwSgFNLQxA== 875 integrity sha512-QyWovTtjQ2RYxqVM+STPh65owSqzuXURnfoof778spyX4iQ4z46wOge1YV2ZtwS8w5LWd9eeVvDrLu5POPYOnA==
856 dependencies: 876 dependencies:
857 tslib "^2.3.1" 877 tslib "^2.3.1"
858 878
@@ -863,88 +883,95 @@
863 dependencies: 883 dependencies:
864 tslib "^2.3.1" 884 tslib "^2.3.1"
865 885
866"@aws-sdk/util-middleware@3.162.0": 886"@aws-sdk/util-middleware@3.190.0":
867 version "3.162.0" 887 version "3.190.0"
868 resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.162.0.tgz#5e38b45b52b731ec4be7b3eb65e8097e70a8a844" 888 resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.190.0.tgz#9c594987f107af05b770f2ac2e70c0391d0cb5b5"
869 integrity sha512-jDqZZ5nst+NtzvAPIQBdQqGY14Z3HeGANGm5NUoxWp8IlHnEV7GhTFDjFgubf8mgTBCzHnvbuBY1bfkzAeXWBA== 889 integrity sha512-qzTJ/qhFDzHZS+iXdHydQ/0sWAuNIB5feeLm55Io/I8Utv3l3TKYOhbgGwTsXY+jDk7oD+YnAi7hLN5oEBCwpg==
870 dependencies: 890 dependencies:
871 tslib "^2.3.1" 891 tslib "^2.3.1"
872 892
873"@aws-sdk/util-stream-browser@3.162.0": 893"@aws-sdk/util-stream-browser@3.190.0":
874 version "3.162.0" 894 version "3.190.0"
875 resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-browser/-/util-stream-browser-3.162.0.tgz#9fbde6fee82bdef40b36f2529f99378f3899ec4e" 895 resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-browser/-/util-stream-browser-3.190.0.tgz#ebb14f63dffe05a09a670cf14a307920d736c803"
876 integrity sha512-1GCOvu6bIQNo3ql/ULobztaJTGxUsWBIgSxftATU0vuCI1Rf4ReluENvpXzdbTEi6mv+k1YUrBBLVzSmFwwxrw== 896 integrity sha512-BqHUD+Bz780LM6lD2YLYsX1PZ+BqwkRYtSaw+ch8IvrnMWeAB1hzQWXRh+2NhMpe2IBw18IrrYB3kVmcyGgUtg==
877 dependencies: 897 dependencies:
878 "@aws-sdk/fetch-http-handler" "3.162.0" 898 "@aws-sdk/fetch-http-handler" "3.190.0"
879 "@aws-sdk/types" "3.162.0" 899 "@aws-sdk/types" "3.190.0"
880 "@aws-sdk/util-base64-browser" "3.109.0" 900 "@aws-sdk/util-base64-browser" "3.188.0"
881 "@aws-sdk/util-hex-encoding" "3.109.0" 901 "@aws-sdk/util-hex-encoding" "3.188.0"
882 "@aws-sdk/util-utf8-browser" "3.109.0" 902 "@aws-sdk/util-utf8-browser" "3.188.0"
883 tslib "^2.3.1" 903 tslib "^2.3.1"
884 904
885"@aws-sdk/util-stream-node@3.162.0": 905"@aws-sdk/util-stream-node@3.190.0":
886 version "3.162.0" 906 version "3.190.0"
887 resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-node/-/util-stream-node-3.162.0.tgz#fcc6e8db77c1785033f3f120a2700affee304b7b" 907 resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-node/-/util-stream-node-3.190.0.tgz#30f7a3a81e3ad379f9bbf60d197686ca6fa6138e"
888 integrity sha512-MWHF8HIsEdircxXb00/y+SesLugetGiU47xOVQtg40yWdoJyPWzP6kBK6+SWT8uR0r1IYdW7fwyxMbc9TccYcQ== 908 integrity sha512-RJ7iQB43fSfGW+aPhdT5LfG5GtbenB7q8mQLiTdIoj4Hw+gwa90JagMX+NxZv6DEkT4IgbT4q9liPQ48M83/YA==
889 dependencies: 909 dependencies:
890 "@aws-sdk/node-http-handler" "3.162.0" 910 "@aws-sdk/node-http-handler" "3.190.0"
891 "@aws-sdk/types" "3.162.0" 911 "@aws-sdk/types" "3.190.0"
892 "@aws-sdk/util-buffer-from" "3.55.0" 912 "@aws-sdk/util-buffer-from" "3.188.0"
893 tslib "^2.3.1" 913 tslib "^2.3.1"
894 914
895"@aws-sdk/util-uri-escape@3.55.0": 915"@aws-sdk/util-uri-escape@3.188.0":
896 version "3.55.0" 916 version "3.188.0"
897 resolved "https://registry.yarnpkg.com/@aws-sdk/util-uri-escape/-/util-uri-escape-3.55.0.tgz#ee57743c628a1c9f942dfe73205ce890ec011916" 917 resolved "https://registry.yarnpkg.com/@aws-sdk/util-uri-escape/-/util-uri-escape-3.188.0.tgz#6dbd4322f6cdc3252a75c6f729e1082369c468c0"
898 integrity sha512-mmdDLUpFCN2nkfwlLdOM54lTD528GiGSPN1qb8XtGLgZsJUmg3uJSFIN2lPeSbEwJB3NFjVas/rnQC48i7mV8w== 918 integrity sha512-4Y6AYZMT483Tiuq8dxz5WHIiPNdSFPGrl6tRTo2Oi2FcwypwmFhqgEGcqxeXDUJktvaCBxeA08DLr/AemVhPCg==
899 dependencies: 919 dependencies:
900 tslib "^2.3.1" 920 tslib "^2.3.1"
901 921
902"@aws-sdk/util-user-agent-browser@3.162.0": 922"@aws-sdk/util-user-agent-browser@3.190.0":
903 version "3.162.0" 923 version "3.190.0"
904 resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.162.0.tgz#735a3611e65df0c4b8a416bbb096e56d0b43f5c9" 924 resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.190.0.tgz#efb7eda04b94b260ae8e8ff5f623eeb9318f2bfd"
905 integrity sha512-FNmC2ywy1u3tbUSVCSkCwLvcbjIvj5EzAtF6I2wrMTI5PfaxVIQapKn2EecoVQgf4lsZqvGjyTxbl7SYvf9fxw== 925 integrity sha512-c074wjsD+/u9vT7DVrBLkwVhn28I+OEHuHaqpTVCvAIjpueZ3oms0e99YJLfpdpEgdLavOroAsNFtAuRrrTZZw==
906 dependencies: 926 dependencies:
907 "@aws-sdk/types" "3.162.0" 927 "@aws-sdk/types" "3.190.0"
908 bowser "^2.11.0" 928 bowser "^2.11.0"
909 tslib "^2.3.1" 929 tslib "^2.3.1"
910 930
911"@aws-sdk/util-user-agent-node@3.162.0": 931"@aws-sdk/util-user-agent-node@3.190.0":
912 version "3.162.0" 932 version "3.190.0"
913 resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.162.0.tgz#3c589c1ad1ce2821c9568dd12bb5632b8eb776be" 933 resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.190.0.tgz#b4bdc523d63ca418f5ca54e26f836db91fe55c43"
914 integrity sha512-OIbZlccBFwITDQJoymU0V+yqqyPEbJUExJzeiP9bxJ58h7Jxj/da24cxCMaVDYvjhP/PoflOmC5Xblonaeg+oQ== 934 integrity sha512-R36BMvvPX8frqFhU4lAsrOJ/2PJEHH/Jz1WZzO3GWmVSEAQQdHmo8tVPE3KOM7mZWe5Hj1dZudFAIxWHHFYKJA==
915 dependencies: 935 dependencies:
916 "@aws-sdk/node-config-provider" "3.162.0" 936 "@aws-sdk/node-config-provider" "3.190.0"
917 "@aws-sdk/types" "3.162.0" 937 "@aws-sdk/types" "3.190.0"
918 tslib "^2.3.1" 938 tslib "^2.3.1"
919 939
920"@aws-sdk/util-utf8-browser@3.109.0", "@aws-sdk/util-utf8-browser@^3.0.0": 940"@aws-sdk/util-utf8-browser@3.188.0":
941 version "3.188.0"
942 resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz#484762bd600401350e148277731d6744a4a92225"
943 integrity sha512-jt627x0+jE+Ydr9NwkFstg3cUvgWh56qdaqAMDsqgRlKD21md/6G226z/Qxl7lb1VEW2LlmCx43ai/37Qwcj2Q==
944 dependencies:
945 tslib "^2.3.1"
946
947"@aws-sdk/util-utf8-browser@^3.0.0":
921 version "3.109.0" 948 version "3.109.0"
922 resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.109.0.tgz#d013272e1981b23a4c84ac06f154db686c0cf84e" 949 resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.109.0.tgz#d013272e1981b23a4c84ac06f154db686c0cf84e"
923 integrity sha512-FmcGSz0v7Bqpl1SE8G1Gc0CtDpug+rvqNCG/szn86JApD/f5x8oByjbEiAyTU2ZH2VevUntx6EW68ulHyH+x+w== 950 integrity sha512-FmcGSz0v7Bqpl1SE8G1Gc0CtDpug+rvqNCG/szn86JApD/f5x8oByjbEiAyTU2ZH2VevUntx6EW68ulHyH+x+w==
924 dependencies: 951 dependencies:
925 tslib "^2.3.1" 952 tslib "^2.3.1"
926 953
927"@aws-sdk/util-utf8-node@3.109.0": 954"@aws-sdk/util-utf8-node@3.188.0":
928 version "3.109.0" 955 version "3.188.0"
929 resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-node/-/util-utf8-node-3.109.0.tgz#89e06d916f5b246c7265f59bac742973ac0767ac" 956 resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-node/-/util-utf8-node-3.188.0.tgz#935bc58a71f2792ac6a4ec881f72bf9ceee008b4"
930 integrity sha512-Ti/ZBdvz2eSTElsucjzNmzpyg2MwfD1rXmxD0hZuIF8bPON/0+sZYnWd5CbDw9kgmhy28dmKue086tbZ1G0iLQ== 957 integrity sha512-hCgP4+C0Lekjpjt2zFJ2R/iHes5sBGljXa5bScOFAEkRUc0Qw0VNgTv7LpEbIOAwGmqyxBoCwBW0YHPW1DfmYQ==
931 dependencies: 958 dependencies:
932 "@aws-sdk/util-buffer-from" "3.55.0" 959 "@aws-sdk/util-buffer-from" "3.188.0"
933 tslib "^2.3.1" 960 tslib "^2.3.1"
934 961
935"@aws-sdk/util-waiter@3.162.0": 962"@aws-sdk/util-waiter@3.190.0":
936 version "3.162.0" 963 version "3.190.0"
937 resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.162.0.tgz#369499ec934a47aa8f0340876a9228e6d8989736" 964 resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.190.0.tgz#01348830fbd6a9a1a8e1fb22e87a29185d8e69fc"
938 integrity sha512-RDMimLdgffkBiFjXyGO0DYjUhDisBHx5OZIaj57bCWRqvMj4lSz5+eS3fpVEZaRDFo/P3i/86lvjPEqXStTlZA== 965 integrity sha512-wlc56EElap8ua+9VCSqXaC4QsJQecYmC0C6A5EfFDtFlFyyd+vjpiLMU34juzrqJfVCx6aAUD2c9f+ezvk1G5Q==
939 dependencies: 966 dependencies:
940 "@aws-sdk/abort-controller" "3.162.0" 967 "@aws-sdk/abort-controller" "3.190.0"
941 "@aws-sdk/types" "3.162.0" 968 "@aws-sdk/types" "3.190.0"
942 tslib "^2.3.1" 969 tslib "^2.3.1"
943 970
944"@aws-sdk/xml-builder@3.142.0": 971"@aws-sdk/xml-builder@3.188.0":
945 version "3.142.0" 972 version "3.188.0"
946 resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.142.0.tgz#55d03f1a1d1b3b02f07e26ec05d6855151f94c4e" 973 resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.188.0.tgz#d3f72f5e490be577670b6532343f5682e38ac000"
947 integrity sha512-e8rFjm5y9ngFc/cPwWMNn/CmMMrLx98CajWew9q7OzP6OOXQJ0H6TaRps2uQPM5XUv3/Ab5YQCV3NiaLJLqqNg== 974 integrity sha512-/Hah3gAtrBpEaDInX3eSS0nXw/IUeb+rWiGspXxb5O8bh5kyjQqeu8/sVJQlpOtq4aPDbMDmloH4k696qTqgbw==
948 dependencies: 975 dependencies:
949 tslib "^2.3.1" 976 tslib "^2.3.1"
950 977
@@ -4145,7 +4172,7 @@ engine.io@~6.2.0:
4145 engine.io-parser "~5.0.3" 4172 engine.io-parser "~5.0.3"
4146 ws "~8.2.3" 4173 ws "~8.2.3"
4147 4174
4148entities@2.2.0, entities@^2.0.0: 4175entities@^2.0.0:
4149 version "2.2.0" 4176 version "2.2.0"
4150 resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" 4177 resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
4151 integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== 4178 integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
@@ -4748,10 +4775,12 @@ fast-safe-stringify@^2.1.1:
4748 resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" 4775 resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
4749 integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== 4776 integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==
4750 4777
4751fast-xml-parser@3.19.0: 4778fast-xml-parser@4.0.11:
4752 version "3.19.0" 4779 version "4.0.11"
4753 resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz#cb637ec3f3999f51406dd8ff0e6fc4d83e520d01" 4780 resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz#42332a9aca544520631c8919e6ea871c0185a985"
4754 integrity sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg== 4781 integrity sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==
4782 dependencies:
4783 strnum "^1.0.5"
4755 4784
4756fast-xml-parser@^4.0.0-beta.8: 4785fast-xml-parser@^4.0.0-beta.8:
4757 version "4.0.9" 4786 version "4.0.9"