aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html69
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html20
-rw-r--r--client/src/app/+verify-account/verify-account-email/verify-account-email.component.ts1
-rwxr-xr-xscripts/travis.sh15
-rw-r--r--server.ts6
-rw-r--r--server/helpers/activitypub.ts10
-rw-r--r--server/helpers/ffmpeg-utils.ts2
-rw-r--r--server/helpers/image-utils.ts19
-rw-r--r--server/initializers/database.ts32
-rw-r--r--server/initializers/installer.ts21
-rw-r--r--server/lib/activitypub/actor.ts8
-rw-r--r--server/lib/activitypub/process/process.ts4
-rw-r--r--server/lib/activitypub/share.ts4
-rw-r--r--server/lib/activitypub/video-rates.ts4
-rw-r--r--server/lib/activitypub/videos.ts14
-rw-r--r--server/lib/user.ts11
-rw-r--r--server/models/account/user.ts4
-rw-r--r--server/models/oauth/oauth-token.ts4
-rw-r--r--server/tests/api/activitypub/security.ts5
-rw-r--r--server/tests/api/users/index.ts2
-rw-r--r--server/tests/api/videos/video-blacklist-management.ts3
-rw-r--r--server/tests/api/videos/video-channels.ts6
-rw-r--r--server/tests/api/videos/video-schedule-update.ts1
-rw-r--r--server/tests/api/videos/video-transcoder.ts5
-rw-r--r--shared/utils/requests/check-api-params.ts2
-rw-r--r--shared/utils/search/videos.ts2
-rw-r--r--shared/utils/server/config.ts2
-rw-r--r--shared/utils/server/jobs.ts3
-rw-r--r--shared/utils/server/stats.ts2
-rw-r--r--shared/utils/users/accounts.ts2
-rw-r--r--shared/utils/users/blocklist.ts2
-rw-r--r--shared/utils/users/user-subscriptions.ts2
-rw-r--r--shared/utils/users/users.ts2
-rw-r--r--shared/utils/videos/video-abuses.ts2
-rw-r--r--shared/utils/videos/video-captions.ts4
-rw-r--r--shared/utils/videos/video-channels.ts2
-rw-r--r--shared/utils/videos/video-comments.ts2
-rw-r--r--shared/utils/videos/video-imports.ts3
-rw-r--r--shared/utils/videos/videos.ts5
-rw-r--r--support/doc/api/openapi.yaml11
-rw-r--r--support/doc/api/quickstart.md4
41 files changed, 186 insertions, 136 deletions
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
index dfbbfbb29..fd4d3d9c9 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
@@ -87,15 +87,19 @@
87 87
88 <div i18n class="inner-form-title">Signup</div> 88 <div i18n class="inner-form-title">Signup</div>
89 89
90 <my-peertube-checkbox 90 <div class="form-group">
91 inputName="signupEnabled" formControlName="signupEnabled" 91 <my-peertube-checkbox
92 i18n-labelText labelText="Signup enabled" 92 inputName="signupEnabled" formControlName="signupEnabled"
93 ></my-peertube-checkbox> 93 i18n-labelText labelText="Signup enabled"
94 ></my-peertube-checkbox>
95 </div>
94 96
95 <my-peertube-checkbox *ngIf="isSignupEnabled()" 97 <div class="form-group">
96 inputName="signupRequiresEmailVerification" formControlName="signupRequiresEmailVerification" 98 <my-peertube-checkbox *ngIf="isSignupEnabled()"
97 i18n-labelText labelText="Signup requires email verification" 99 inputName="signupRequiresEmailVerification" formControlName="signupRequiresEmailVerification"
98 ></my-peertube-checkbox> 100 i18n-labelText labelText="Signup requires email verification"
101 ></my-peertube-checkbox>
102 </div>
99 103
100 <div *ngIf="isSignupEnabled()" class="form-group"> 104 <div *ngIf="isSignupEnabled()" class="form-group">
101 <label i18n for="signupLimit">Signup limit</label> 105 <label i18n for="signupLimit">Signup limit</label>
@@ -110,15 +114,19 @@
110 114
111 <div i18n class="inner-form-title">Import</div> 115 <div i18n class="inner-form-title">Import</div>
112 116
113 <my-peertube-checkbox 117 <div class="form-group">
114 inputName="importVideosHttpEnabled" formControlName="importVideosHttpEnabled" 118 <my-peertube-checkbox
115 i18n-labelText labelText="Video import with HTTP URL (i.e. YouTube) enabled" 119 inputName="importVideosHttpEnabled" formControlName="importVideosHttpEnabled"
116 ></my-peertube-checkbox> 120 i18n-labelText labelText="Video import with HTTP URL (i.e. YouTube) enabled"
121 ></my-peertube-checkbox>
122 </div>
117 123
118 <my-peertube-checkbox 124 <div class="form-group">
119 inputName="importVideosTorrentEnabled" formControlName="importVideosTorrentEnabled" 125 <my-peertube-checkbox
120 i18n-labelText labelText="Video import with a torrent file or a magnet URI enabled" 126 inputName="importVideosTorrentEnabled" formControlName="importVideosTorrentEnabled"
121 ></my-peertube-checkbox> 127 i18n-labelText labelText="Video import with a torrent file or a magnet URI enabled"
128 ></my-peertube-checkbox>
129 </div>
122 130
123 <div i18n class="inner-form-title">Administrator</div> 131 <div i18n class="inner-form-title">Administrator</div>
124 132
@@ -184,13 +192,15 @@
184 </div> 192 </div>
185 </div> 193 </div>
186 194
187 <my-peertube-checkbox 195 <div class="form-group">
188 inputName="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted" 196 <my-peertube-checkbox
189 i18n-labelText labelText="Instance whitelisted by Twitter" 197 inputName="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted"
190 i18n-helpHtml helpHtml="If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br /> 198 i18n-labelText labelText="Instance whitelisted by Twitter"
191 If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br /> 199 i18n-helpHtml helpHtml="If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
192 Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a> to see if you instance is whitelisted." 200 If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
193 ></my-peertube-checkbox> 201 Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a> to see if you instance is whitelisted."
202 ></my-peertube-checkbox>
203 </div>
194 </ng-template> 204 </ng-template>
195 </ngb-tab> 205 </ngb-tab>
196 206
@@ -199,11 +209,13 @@
199 209
200 <div i18n class="inner-form-title">Transcoding</div> 210 <div i18n class="inner-form-title">Transcoding</div>
201 211
202 <my-peertube-checkbox 212 <div class="form-group">
203 inputName="transcodingEnabled" formControlName="transcodingEnabled" 213 <my-peertube-checkbox
204 i18n-labelText labelText="Transcoding enabled" 214 inputName="transcodingEnabled" formControlName="transcodingEnabled"
205 i18n-helpHtml helpHtml="If you disable transcoding, many videos from your users will not work!" 215 i18n-labelText labelText="Transcoding enabled"
206 ></my-peertube-checkbox> 216 i18n-helpHtml helpHtml="If you disable transcoding, many videos from your users will not work!"
217 ></my-peertube-checkbox>
218 </div>
207 219
208 <ng-template [ngIf]="isTranscodingEnabled()"> 220 <ng-template [ngIf]="isTranscodingEnabled()">
209 221
@@ -226,7 +238,6 @@
226 [inputName]="getResolutionKey(resolution)" [formControlName]="getResolutionKey(resolution)" 238 [inputName]="getResolutionKey(resolution)" [formControlName]="getResolutionKey(resolution)"
227 i18n-labelText labelText="Resolution {{resolution}} enabled" 239 i18n-labelText labelText="Resolution {{resolution}} enabled"
228 ></my-peertube-checkbox> 240 ></my-peertube-checkbox>
229
230 </div> 241 </div>
231 </ng-template> 242 </ng-template>
232 243
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
index 8be8a66cc..049119fa8 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
@@ -15,15 +15,19 @@
15 </div> 15 </div>
16 </div> 16 </div>
17 17
18 <my-peertube-checkbox 18 <div class="form-group">
19 inputName="webTorrentEnabled" formControlName="webTorrentEnabled" 19 <my-peertube-checkbox
20 i18n-labelText labelText="Use WebTorrent to exchange parts of the video with others" 20 inputName="webTorrentEnabled" formControlName="webTorrentEnabled"
21 ></my-peertube-checkbox> 21 i18n-labelText labelText="Use WebTorrent to exchange parts of the video with others"
22 ></my-peertube-checkbox>
23 </div>
22 24
23 <my-peertube-checkbox 25 <div class="form-group">
24 inputName="autoPlayVideo" formControlName="autoPlayVideo" 26 <my-peertube-checkbox
25 i18n-labelText labelText="Automatically plays video" 27 inputName="autoPlayVideo" formControlName="autoPlayVideo"
26 ></my-peertube-checkbox> 28 i18n-labelText labelText="Automatically plays video"
29 ></my-peertube-checkbox>
30 </div>
27 31
28 <input type="submit" i18n-value value="Save" [disabled]="!form.valid"> 32 <input type="submit" i18n-value value="Save" [disabled]="!form.valid">
29</form> 33</form>
diff --git a/client/src/app/+verify-account/verify-account-email/verify-account-email.component.ts b/client/src/app/+verify-account/verify-account-email/verify-account-email.component.ts
index 26b3bf4b1..e4a5522c8 100644
--- a/client/src/app/+verify-account/verify-account-email/verify-account-email.component.ts
+++ b/client/src/app/+verify-account/verify-account-email/verify-account-email.component.ts
@@ -25,7 +25,6 @@ export class VerifyAccountEmailComponent implements OnInit {
25 } 25 }
26 26
27 ngOnInit () { 27 ngOnInit () {
28
29 this.userId = this.route.snapshot.queryParams['userId'] 28 this.userId = this.route.snapshot.queryParams['userId']
30 this.verificationString = this.route.snapshot.queryParams['verificationString'] 29 this.verificationString = this.route.snapshot.queryParams['verificationString']
31 30
diff --git a/scripts/travis.sh b/scripts/travis.sh
index 49b7233e1..509b40d87 100755
--- a/scripts/travis.sh
+++ b/scripts/travis.sh
@@ -11,28 +11,25 @@ killall -q peertube || true
11 11
12if [ "$1" = "misc" ]; then 12if [ "$1" = "misc" ]; then
13 npm run build -- --light-fr 13 npm run build -- --light-fr
14 mocha --timeout 5000 --exit --require ts-node/register/type-check --bail server/tests/client.ts \ 14 mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/client.ts \
15 server/tests/feeds/index.ts \ 15 server/tests/feeds/index.ts \
16 server/tests/misc-endpoints.ts \ 16 server/tests/misc-endpoints.ts \
17 server/tests/helpers/index.ts 17 server/tests/helpers/index.ts
18elif [ "$1" = "api" ]; then
19 npm run build:server
20 mocha --timeout 5000 --exit --require ts-node/register/type-check --bail server/tests/api/index.ts
21elif [ "$1" = "cli" ]; then 18elif [ "$1" = "cli" ]; then
22 npm run build:server 19 npm run build:server
23 mocha --timeout 5000 --exit --require ts-node/register/type-check --bail server/tests/cli/index.ts 20 mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/cli/index.ts
24elif [ "$1" = "api-1" ]; then 21elif [ "$1" = "api-1" ]; then
25 npm run build:server 22 npm run build:server
26 mocha --timeout 5000 --exit --require ts-node/register/type-check --bail server/tests/api/index-1.ts 23 mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/api/index-1.ts
27elif [ "$1" = "api-2" ]; then 24elif [ "$1" = "api-2" ]; then
28 npm run build:server 25 npm run build:server
29 mocha --timeout 5000 --exit --require ts-node/register/type-check --bail server/tests/api/index-2.ts 26 mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/api/index-2.ts
30elif [ "$1" = "api-3" ]; then 27elif [ "$1" = "api-3" ]; then
31 npm run build:server 28 npm run build:server
32 mocha --timeout 5000 --exit --require ts-node/register/type-check --bail server/tests/api/index-3.ts 29 mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/api/index-3.ts
33elif [ "$1" = "api-4" ]; then 30elif [ "$1" = "api-4" ]; then
34 npm run build:server 31 npm run build:server
35 mocha --timeout 5000 --exit --require ts-node/register/type-check --bail server/tests/api/index-4.ts 32 mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/api/index-4.ts
36elif [ "$1" = "lint" ]; then 33elif [ "$1" = "lint" ]; then
37 npm run tslint -- --project ./tsconfig.json -c ./tslint.json server.ts "server/**/*.ts" "shared/**/*.ts" 34 npm run tslint -- --project ./tsconfig.json -c ./tslint.json server.ts "server/**/*.ts" "shared/**/*.ts"
38 35
diff --git a/server.ts b/server.ts
index f3514cf9c..3025a6fd7 100644
--- a/server.ts
+++ b/server.ts
@@ -204,9 +204,11 @@ async function startApplication () {
204 204
205 // Email initialization 205 // Email initialization
206 Emailer.Instance.init() 206 Emailer.Instance.init()
207 await Emailer.Instance.checkConnectionOrDie()
208 207
209 await JobQueue.Instance.init() 208 await Promise.all([
209 Emailer.Instance.checkConnectionOrDie(),
210 JobQueue.Instance.init()
211 ])
210 212
211 // Caches initializations 213 // Caches initializations
212 VideosPreviewCache.Instance.init(CONFIG.CACHE.PREVIEWS.SIZE, CACHE.PREVIEWS.MAX_AGE) 214 VideosPreviewCache.Instance.init(CONFIG.CACHE.PREVIEWS.SIZE, CACHE.PREVIEWS.MAX_AGE)
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts
index bcbd9be59..79b76fa0b 100644
--- a/server/helpers/activitypub.ts
+++ b/server/helpers/activitypub.ts
@@ -1,7 +1,7 @@
1import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import * as validator from 'validator' 2import * as validator from 'validator'
3import { ResultList } from '../../shared/models' 3import { ResultList } from '../../shared/models'
4import { Activity, ActivityPubActor } from '../../shared/models/activitypub' 4import { Activity } from '../../shared/models/activitypub'
5import { ACTIVITY_PUB } from '../initializers' 5import { ACTIVITY_PUB } from '../initializers'
6import { ActorModel } from '../models/activitypub/actor' 6import { ActorModel } from '../models/activitypub/actor'
7import { signJsonLDObject } from './peertube-crypto' 7import { signJsonLDObject } from './peertube-crypto'
@@ -106,10 +106,10 @@ function buildSignedActivity (byActor: ActorModel, data: Object) {
106 return signJsonLDObject(byActor, activity) as Promise<Activity> 106 return signJsonLDObject(byActor, activity) as Promise<Activity>
107} 107}
108 108
109function getActorUrl (activityActor: string | ActivityPubActor) { 109function getAPUrl (activity: string | { id: string }) {
110 if (typeof activityActor === 'string') return activityActor 110 if (typeof activity === 'string') return activity
111 111
112 return activityActor.id 112 return activity.id
113} 113}
114 114
115function checkUrlsSameHost (url1: string, url2: string) { 115function checkUrlsSameHost (url1: string, url2: string) {
@@ -123,7 +123,7 @@ function checkUrlsSameHost (url1: string, url2: string) {
123 123
124export { 124export {
125 checkUrlsSameHost, 125 checkUrlsSameHost,
126 getActorUrl, 126 getAPUrl,
127 activityPubContextify, 127 activityPubContextify,
128 activityPubCollectionPagination, 128 activityPubCollectionPagination,
129 buildSignedActivity 129 buildSignedActivity
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts
index 8b9045038..b59e7e40e 100644
--- a/server/helpers/ffmpeg-utils.ts
+++ b/server/helpers/ffmpeg-utils.ts
@@ -1,7 +1,7 @@
1import * as ffmpeg from 'fluent-ffmpeg' 1import * as ffmpeg from 'fluent-ffmpeg'
2import { join } from 'path' 2import { join } from 'path'
3import { getTargetBitrate, VideoResolution } from '../../shared/models/videos' 3import { getTargetBitrate, VideoResolution } from '../../shared/models/videos'
4import { CONFIG, FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers' 4import { CONFIG, FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers/constants'
5import { processImage } from './image-utils' 5import { processImage } from './image-utils'
6import { logger } from './logger' 6import { logger } from './logger'
7import { checkFFmpegEncoders } from '../initializers/checker-before-init' 7import { checkFFmpegEncoders } from '../initializers/checker-before-init'
diff --git a/server/helpers/image-utils.ts b/server/helpers/image-utils.ts
index 3eaa674ed..da3285b13 100644
--- a/server/helpers/image-utils.ts
+++ b/server/helpers/image-utils.ts
@@ -1,13 +1,28 @@
1import 'multer' 1import 'multer'
2import * as sharp from 'sharp' 2import * as sharp from 'sharp'
3import { remove } from 'fs-extra' 3import { move, remove } from 'fs-extra'
4 4
5async function processImage ( 5async function processImage (
6 physicalFile: { path: string }, 6 physicalFile: { path: string },
7 destination: string, 7 destination: string,
8 newSize: { width: number, height: number } 8 newSize: { width: number, height: number }
9) { 9) {
10 await sharp(physicalFile.path) 10 if (physicalFile.path === destination) {
11 throw new Error('Sharp needs an input path different that the output path.')
12 }
13
14 const sharpInstance = sharp(physicalFile.path)
15 const metadata = await sharpInstance.metadata()
16
17 // No need to resize
18 if (metadata.width === newSize.width && metadata.height === newSize.height) {
19 await move(physicalFile.path, destination, { overwrite: true })
20 return
21 }
22
23 await remove(destination)
24
25 await sharpInstance
11 .resize(newSize.width, newSize.height) 26 .resize(newSize.width, newSize.height)
12 .toFile(destination) 27 .toFile(destination)
13 28
diff --git a/server/initializers/database.ts b/server/initializers/database.ts
index dd5b9bf67..40cd659ab 100644
--- a/server/initializers/database.ts
+++ b/server/initializers/database.ts
@@ -119,25 +119,27 @@ export {
119// --------------------------------------------------------------------------- 119// ---------------------------------------------------------------------------
120 120
121async function checkPostgresExtensions () { 121async function checkPostgresExtensions () {
122 const extensions = [ 122 const promises = [
123 'pg_trgm', 123 checkPostgresExtension('pg_trgm'),
124 'unaccent' 124 checkPostgresExtension('unaccent')
125 ] 125 ]
126 126
127 for (const extension of extensions) { 127 return Promise.all(promises)
128 const query = `SELECT true AS enabled FROM pg_available_extensions WHERE name = '${extension}' AND installed_version IS NOT NULL;` 128}
129 const [ res ] = await sequelizeTypescript.query(query, { raw: true }) 129
130async function checkPostgresExtension (extension: string) {
131 const query = `SELECT true AS enabled FROM pg_available_extensions WHERE name = '${extension}' AND installed_version IS NOT NULL;`
132 const [ res ] = await sequelizeTypescript.query(query, { raw: true })
130 133
131 if (!res || res.length === 0 || res[ 0 ][ 'enabled' ] !== true) { 134 if (!res || res.length === 0 || res[ 0 ][ 'enabled' ] !== true) {
132 // Try to create the extension ourself 135 // Try to create the extension ourself
133 try { 136 try {
134 await sequelizeTypescript.query(`CREATE EXTENSION ${extension};`, { raw: true }) 137 await sequelizeTypescript.query(`CREATE EXTENSION ${extension};`, { raw: true })
135 138
136 } catch { 139 } catch {
137 const errorMessage = `You need to enable ${extension} extension in PostgreSQL. ` + 140 const errorMessage = `You need to enable ${extension} extension in PostgreSQL. ` +
138 `You can do so by running 'CREATE EXTENSION ${extension};' as a PostgreSQL super user in ${CONFIG.DATABASE.DBNAME} database.` 141 `You can do so by running 'CREATE EXTENSION ${extension};' as a PostgreSQL super user in ${CONFIG.DATABASE.DBNAME} database.`
139 throw new Error(errorMessage) 142 throw new Error(errorMessage)
140 }
141 } 143 }
142 } 144 }
143} 145}
diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts
index c952ad46c..b9a9da183 100644
--- a/server/initializers/installer.ts
+++ b/server/initializers/installer.ts
@@ -12,12 +12,21 @@ import { remove, ensureDir } from 'fs-extra'
12 12
13async function installApplication () { 13async function installApplication () {
14 try { 14 try {
15 await sequelizeTypescript.sync() 15 await Promise.all([
16 await removeCacheDirectories() 16 // Database related
17 await createDirectoriesIfNotExist() 17 sequelizeTypescript.sync()
18 await createApplicationIfNotExist() 18 .then(() => {
19 await createOAuthClientIfNotExist() 19 return Promise.all([
20 await createOAuthAdminIfNotExist() 20 createApplicationIfNotExist(),
21 createOAuthClientIfNotExist(),
22 createOAuthAdminIfNotExist()
23 ])
24 }),
25
26 // Directories
27 removeCacheDirectories()
28 .then(() => createDirectoriesIfNotExist())
29 ])
21 } catch (err) { 30 } catch (err) {
22 logger.error('Cannot install application.', { err }) 31 logger.error('Cannot install application.', { err })
23 process.exit(-1) 32 process.exit(-1)
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts
index 218dbc6a7..504263c99 100644
--- a/server/lib/activitypub/actor.ts
+++ b/server/lib/activitypub/actor.ts
@@ -5,15 +5,15 @@ import * as url from 'url'
5import * as uuidv4 from 'uuid/v4' 5import * as uuidv4 from 'uuid/v4'
6import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' 6import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub'
7import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' 7import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects'
8import { checkUrlsSameHost, getActorUrl } from '../../helpers/activitypub' 8import { checkUrlsSameHost, getAPUrl } from '../../helpers/activitypub'
9import { isActorObjectValid, normalizeActor } from '../../helpers/custom-validators/activitypub/actor' 9import { isActorObjectValid, normalizeActor } from '../../helpers/custom-validators/activitypub/actor'
10import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 10import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
11import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils' 11import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils'
12import { logger } from '../../helpers/logger' 12import { logger } from '../../helpers/logger'
13import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' 13import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto'
14import { doRequest, doRequestAndSaveToFile, downloadImage } from '../../helpers/requests' 14import { doRequest, downloadImage } from '../../helpers/requests'
15import { getUrlFromWebfinger } from '../../helpers/webfinger' 15import { getUrlFromWebfinger } from '../../helpers/webfinger'
16import { AVATARS_SIZE, CONFIG, IMAGE_MIMETYPE_EXT, PREVIEWS_SIZE, sequelizeTypescript } from '../../initializers' 16import { AVATARS_SIZE, CONFIG, IMAGE_MIMETYPE_EXT, sequelizeTypescript } from '../../initializers'
17import { AccountModel } from '../../models/account/account' 17import { AccountModel } from '../../models/account/account'
18import { ActorModel } from '../../models/activitypub/actor' 18import { ActorModel } from '../../models/activitypub/actor'
19import { AvatarModel } from '../../models/avatar/avatar' 19import { AvatarModel } from '../../models/avatar/avatar'
@@ -43,7 +43,7 @@ async function getOrCreateActorAndServerAndModel (
43 recurseIfNeeded = true, 43 recurseIfNeeded = true,
44 updateCollections = false 44 updateCollections = false
45) { 45) {
46 const actorUrl = getActorUrl(activityActor) 46 const actorUrl = getAPUrl(activityActor)
47 let created = false 47 let created = false
48 48
49 let actor = await fetchActorByUrl(actorUrl, fetchType) 49 let actor = await fetchActorByUrl(actorUrl, fetchType)
diff --git a/server/lib/activitypub/process/process.ts b/server/lib/activitypub/process/process.ts
index b9b255ddf..bcc5cac7a 100644
--- a/server/lib/activitypub/process/process.ts
+++ b/server/lib/activitypub/process/process.ts
@@ -1,5 +1,5 @@
1import { Activity, ActivityType } from '../../../../shared/models/activitypub' 1import { Activity, ActivityType } from '../../../../shared/models/activitypub'
2import { checkUrlsSameHost, getActorUrl } from '../../../helpers/activitypub' 2import { checkUrlsSameHost, getAPUrl } from '../../../helpers/activitypub'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { ActorModel } from '../../../models/activitypub/actor' 4import { ActorModel } from '../../../models/activitypub/actor'
5import { processAcceptActivity } from './process-accept' 5import { processAcceptActivity } from './process-accept'
@@ -40,7 +40,7 @@ async function processActivities (
40 continue 40 continue
41 } 41 }
42 42
43 const actorUrl = getActorUrl(activity.actor) 43 const actorUrl = getAPUrl(activity.actor)
44 44
45 // When we fetch remote data, we don't have signature 45 // When we fetch remote data, we don't have signature
46 if (options.signatureActor && actorUrl !== options.signatureActor.url) { 46 if (options.signatureActor && actorUrl !== options.signatureActor.url) {
diff --git a/server/lib/activitypub/share.ts b/server/lib/activitypub/share.ts
index d2649e2d5..5dcba778c 100644
--- a/server/lib/activitypub/share.ts
+++ b/server/lib/activitypub/share.ts
@@ -11,7 +11,7 @@ import { doRequest } from '../../helpers/requests'
11import { getOrCreateActorAndServerAndModel } from './actor' 11import { getOrCreateActorAndServerAndModel } from './actor'
12import { logger } from '../../helpers/logger' 12import { logger } from '../../helpers/logger'
13import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers' 13import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers'
14import { checkUrlsSameHost, getActorUrl } from '../../helpers/activitypub' 14import { checkUrlsSameHost, getAPUrl } from '../../helpers/activitypub'
15 15
16async function shareVideoByServerAndChannel (video: VideoModel, t: Transaction) { 16async function shareVideoByServerAndChannel (video: VideoModel, t: Transaction) {
17 if (video.privacy === VideoPrivacy.PRIVATE) return undefined 17 if (video.privacy === VideoPrivacy.PRIVATE) return undefined
@@ -41,7 +41,7 @@ async function addVideoShares (shareUrls: string[], instance: VideoModel) {
41 }) 41 })
42 if (!body || !body.actor) throw new Error('Body or body actor is invalid') 42 if (!body || !body.actor) throw new Error('Body or body actor is invalid')
43 43
44 const actorUrl = getActorUrl(body.actor) 44 const actorUrl = getAPUrl(body.actor)
45 if (checkUrlsSameHost(shareUrl, actorUrl) !== true) { 45 if (checkUrlsSameHost(shareUrl, actorUrl) !== true) {
46 throw new Error(`Actor url ${actorUrl} has not the same host than the share url ${shareUrl}`) 46 throw new Error(`Actor url ${actorUrl} has not the same host than the share url ${shareUrl}`)
47 } 47 }
diff --git a/server/lib/activitypub/video-rates.ts b/server/lib/activitypub/video-rates.ts
index 1854b44c4..2cce67f0c 100644
--- a/server/lib/activitypub/video-rates.ts
+++ b/server/lib/activitypub/video-rates.ts
@@ -9,7 +9,7 @@ import { AccountVideoRateModel } from '../../models/account/account-video-rate'
9import { logger } from '../../helpers/logger' 9import { logger } from '../../helpers/logger'
10import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers' 10import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers'
11import { doRequest } from '../../helpers/requests' 11import { doRequest } from '../../helpers/requests'
12import { checkUrlsSameHost, getActorUrl } from '../../helpers/activitypub' 12import { checkUrlsSameHost, getAPUrl } from '../../helpers/activitypub'
13import { ActorModel } from '../../models/activitypub/actor' 13import { ActorModel } from '../../models/activitypub/actor'
14import { getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from './url' 14import { getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from './url'
15 15
@@ -26,7 +26,7 @@ async function createRates (ratesUrl: string[], video: VideoModel, rate: VideoRa
26 }) 26 })
27 if (!body || !body.actor) throw new Error('Body or body actor is invalid') 27 if (!body || !body.actor) throw new Error('Body or body actor is invalid')
28 28
29 const actorUrl = getActorUrl(body.actor) 29 const actorUrl = getAPUrl(body.actor)
30 if (checkUrlsSameHost(actorUrl, rateUrl) !== true) { 30 if (checkUrlsSameHost(actorUrl, rateUrl) !== true) {
31 throw new Error(`Rate url ${rateUrl} has not the same host than actor url ${actorUrl}`) 31 throw new Error(`Rate url ${rateUrl} has not the same host than actor url ${actorUrl}`)
32 } 32 }
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index 80de92f24..4cecf9345 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -29,7 +29,7 @@ import { createRates } from './video-rates'
29import { addVideoShares, shareVideoByServerAndChannel } from './share' 29import { addVideoShares, shareVideoByServerAndChannel } from './share'
30import { AccountModel } from '../../models/account/account' 30import { AccountModel } from '../../models/account/account'
31import { fetchVideoByUrl, VideoFetchByUrlType } from '../../helpers/video' 31import { fetchVideoByUrl, VideoFetchByUrlType } from '../../helpers/video'
32import { checkUrlsSameHost } from '../../helpers/activitypub' 32import { checkUrlsSameHost, getAPUrl } from '../../helpers/activitypub'
33 33
34async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) { 34async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) {
35 // If the video is not private and published, we federate it 35 // If the video is not private and published, we federate it
@@ -167,7 +167,7 @@ async function getOrCreateVideoAndAccountAndChannel (options: {
167 const refreshViews = options.refreshViews || false 167 const refreshViews = options.refreshViews || false
168 168
169 // Get video url 169 // Get video url
170 const videoUrl = typeof options.videoObject === 'string' ? options.videoObject : options.videoObject.id 170 const videoUrl = getAPUrl(options.videoObject)
171 171
172 let videoFromDatabase = await fetchVideoByUrl(videoUrl, fetchType) 172 let videoFromDatabase = await fetchVideoByUrl(videoUrl, fetchType)
173 if (videoFromDatabase) { 173 if (videoFromDatabase) {
@@ -242,10 +242,6 @@ async function updateVideoFromAP (options: {
242 if (options.updateViews === true) options.video.set('views', videoData.views) 242 if (options.updateViews === true) options.video.set('views', videoData.views)
243 await options.video.save(sequelizeOptions) 243 await options.video.save(sequelizeOptions)
244 244
245 // Don't block on request
246 generateThumbnailFromUrl(options.video, options.videoObject.icon)
247 .catch(err => logger.warn('Cannot generate thumbnail of %s.', options.videoObject.id, { err }))
248
249 { 245 {
250 const videoFileAttributes = videoFileActivityUrlToDBAttributes(options.video, options.videoObject) 246 const videoFileAttributes = videoFileActivityUrlToDBAttributes(options.video, options.videoObject)
251 const newVideoFiles = videoFileAttributes.map(a => new VideoFileModel(a)) 247 const newVideoFiles = videoFileAttributes.map(a => new VideoFileModel(a))
@@ -293,6 +289,12 @@ async function updateVideoFromAP (options: {
293 logger.debug('Cannot update the remote video.', { err }) 289 logger.debug('Cannot update the remote video.', { err })
294 throw err 290 throw err
295 } 291 }
292
293 try {
294 await generateThumbnailFromUrl(options.video, options.videoObject.icon)
295 } catch (err) {
296 logger.warn('Cannot generate thumbnail of %s.', options.videoObject.id, { err })
297 }
296} 298}
297 299
298export { 300export {
diff --git a/server/lib/user.ts b/server/lib/user.ts
index db29469eb..29d6d087d 100644
--- a/server/lib/user.ts
+++ b/server/lib/user.ts
@@ -18,7 +18,7 @@ async function createUserAccountAndChannel (userToCreate: UserModel, validateUse
18 } 18 }
19 19
20 const userCreated = await userToCreate.save(userOptions) 20 const userCreated = await userToCreate.save(userOptions)
21 const accountCreated = await createLocalAccountWithoutKeys(userToCreate.username, userToCreate.id, null, t) 21 const accountCreated = await createLocalAccountWithoutKeys(userCreated.username, userCreated.id, null, t)
22 userCreated.Account = accountCreated 22 userCreated.Account = accountCreated
23 23
24 let channelName = userCreated.username + '_channel' 24 let channelName = userCreated.username + '_channel'
@@ -37,8 +37,13 @@ async function createUserAccountAndChannel (userToCreate: UserModel, validateUse
37 return { user: userCreated, account: accountCreated, videoChannel } 37 return { user: userCreated, account: accountCreated, videoChannel }
38 }) 38 })
39 39
40 account.Actor = await setAsyncActorKeys(account.Actor) 40 const [ accountKeys, channelKeys ] = await Promise.all([
41 videoChannel.Actor = await setAsyncActorKeys(videoChannel.Actor) 41 setAsyncActorKeys(account.Actor),
42 setAsyncActorKeys(videoChannel.Actor)
43 ])
44
45 account.Actor = accountKeys
46 videoChannel.Actor = channelKeys
42 47
43 return { user, account, videoChannel } as { user: UserModel, account: AccountModel, videoChannel: VideoChannelModel } 48 return { user, account, videoChannel } as { user: UserModel, account: AccountModel, videoChannel: VideoChannelModel }
44} 49}
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 34aafa1a7..1843603f1 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -1,6 +1,6 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import { 2import {
3 AfterDelete, 3 AfterDestroy,
4 AfterUpdate, 4 AfterUpdate,
5 AllowNull, 5 AllowNull,
6 BeforeCreate, 6 BeforeCreate,
@@ -179,7 +179,7 @@ export class UserModel extends Model<UserModel> {
179 } 179 }
180 180
181 @AfterUpdate 181 @AfterUpdate
182 @AfterDelete 182 @AfterDestroy
183 static removeTokenCache (instance: UserModel) { 183 static removeTokenCache (instance: UserModel) {
184 return clearCacheByUserId(instance.id) 184 return clearCacheByUserId(instance.id)
185 } 185 }
diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts
index ecf846821..08d892da4 100644
--- a/server/models/oauth/oauth-token.ts
+++ b/server/models/oauth/oauth-token.ts
@@ -1,5 +1,5 @@
1import { 1import {
2 AfterDelete, 2 AfterDestroy,
3 AfterUpdate, 3 AfterUpdate,
4 AllowNull, 4 AllowNull,
5 BelongsTo, 5 BelongsTo,
@@ -126,7 +126,7 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
126 OAuthClients: OAuthClientModel[] 126 OAuthClients: OAuthClientModel[]
127 127
128 @AfterUpdate 128 @AfterUpdate
129 @AfterDelete 129 @AfterDestroy
130 static removeTokenCache (token: OAuthTokenModel) { 130 static removeTokenCache (token: OAuthTokenModel) {
131 return clearCacheByToken(token.accessToken) 131 return clearCacheByToken(token.accessToken)
132 } 132 }
diff --git a/server/tests/api/activitypub/security.ts b/server/tests/api/activitypub/security.ts
index 69b7c0148..b71a61c8c 100644
--- a/server/tests/api/activitypub/security.ts
+++ b/server/tests/api/activitypub/security.ts
@@ -8,15 +8,12 @@ import {
8 killallServers, 8 killallServers,
9 ServerInfo 9 ServerInfo
10} from '../../../../shared/utils' 10} from '../../../../shared/utils'
11import {
12 makePOSTAPRequest,
13 makeFollowRequest,
14} from '../../utils/requests/activitypub'
15import { HTTP_SIGNATURE } from '../../../initializers' 11import { HTTP_SIGNATURE } from '../../../initializers'
16import { buildDigest, buildGlobalHeaders } from '../../../lib/job-queue/handlers/utils/activitypub-http-utils' 12import { buildDigest, buildGlobalHeaders } from '../../../lib/job-queue/handlers/utils/activitypub-http-utils'
17import * as chai from 'chai' 13import * as chai from 'chai'
18import { setActorField } from '../../utils/miscs/sql' 14import { setActorField } from '../../utils/miscs/sql'
19import { activityPubContextify, buildSignedActivity } from '../../../helpers/activitypub' 15import { activityPubContextify, buildSignedActivity } from '../../../helpers/activitypub'
16import { makeFollowRequest, makePOSTAPRequest } from '../../utils/requests/activitypub'
20 17
21const expect = chai.expect 18const expect = chai.expect
22 19
diff --git a/server/tests/api/users/index.ts b/server/tests/api/users/index.ts
index 0a1b8b0b2..ff433315d 100644
--- a/server/tests/api/users/index.ts
+++ b/server/tests/api/users/index.ts
@@ -1,5 +1,5 @@
1import './blocklist' 1import './blocklist'
2import './user-subscriptions' 2import './user-subscriptions'
3import './users' 3import './users'
4import './users-verification'
5import './users-multiple-servers' 4import './users-multiple-servers'
5import './users-verification'
diff --git a/server/tests/api/videos/video-blacklist-management.ts b/server/tests/api/videos/video-blacklist-management.ts
index 06d80a270..61411e30d 100644
--- a/server/tests/api/videos/video-blacklist-management.ts
+++ b/server/tests/api/videos/video-blacklist-management.ts
@@ -1,7 +1,7 @@
1/* tslint:disable:no-unused-expression */ 1/* tslint:disable:no-unused-expression */
2 2
3import * as chai from 'chai' 3import * as chai from 'chai'
4import * as lodash from 'lodash' 4import { orderBy } from 'lodash'
5import 'mocha' 5import 'mocha'
6import { 6import {
7 addVideoToBlacklist, 7 addVideoToBlacklist,
@@ -22,7 +22,6 @@ import { waitJobs } from '../../../../shared/utils/server/jobs'
22import { VideoAbuse } from '../../../../shared/models/videos' 22import { VideoAbuse } from '../../../../shared/models/videos'
23 23
24const expect = chai.expect 24const expect = chai.expect
25const orderBy = lodash.orderBy
26 25
27describe('Test video blacklist management', function () { 26describe('Test video blacklist management', function () {
28 let servers: ServerInfo[] = [] 27 let servers: ServerInfo[] = []
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts
index 5bffffc66..63514d69c 100644
--- a/server/tests/api/videos/video-channels.ts
+++ b/server/tests/api/videos/video-channels.ts
@@ -7,10 +7,12 @@ import {
7 createUser, 7 createUser,
8 doubleFollow, 8 doubleFollow,
9 flushAndRunMultipleServers, 9 flushAndRunMultipleServers,
10 getVideoChannelVideos, serverLogin, testImage, 10 getVideoChannelVideos,
11 testImage,
11 updateVideo, 12 updateVideo,
12 updateVideoChannelAvatar, 13 updateVideoChannelAvatar,
13 uploadVideo, wait, userLogin 14 uploadVideo,
15 userLogin
14} from '../../../../shared/utils' 16} from '../../../../shared/utils'
15import { 17import {
16 addVideoChannel, 18 addVideoChannel,
diff --git a/server/tests/api/videos/video-schedule-update.ts b/server/tests/api/videos/video-schedule-update.ts
index ecfc5e034..632c4244c 100644
--- a/server/tests/api/videos/video-schedule-update.ts
+++ b/server/tests/api/videos/video-schedule-update.ts
@@ -16,7 +16,6 @@ import {
16 uploadVideo, 16 uploadVideo,
17 wait 17 wait
18} from '../../../../shared/utils' 18} from '../../../../shared/utils'
19import { join } from 'path'
20import { waitJobs } from '../../../../shared/utils/server/jobs' 19import { waitJobs } from '../../../../shared/utils/server/jobs'
21 20
22const expect = chai.expect 21const expect = chai.expect
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts
index f9458f0ec..68cf00194 100644
--- a/server/tests/api/videos/video-transcoder.ts
+++ b/server/tests/api/videos/video-transcoder.ts
@@ -3,13 +3,13 @@
3import * as chai from 'chai' 3import * as chai from 'chai'
4import 'mocha' 4import 'mocha'
5import { omit } from 'lodash' 5import { omit } from 'lodash'
6import * as ffmpeg from 'fluent-ffmpeg'
7import { getMaxBitrate, VideoDetails, VideoResolution, VideoState } from '../../../../shared/models/videos' 6import { getMaxBitrate, VideoDetails, VideoResolution, VideoState } from '../../../../shared/models/videos'
8import { audio, getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils' 7import { audio, getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils'
9import { 8import {
10 buildAbsoluteFixturePath, 9 buildAbsoluteFixturePath,
11 doubleFollow, 10 doubleFollow,
12 flushAndRunMultipleServers, 11 flushAndRunMultipleServers,
12 generateHighBitrateVideo,
13 getMyVideos, 13 getMyVideos,
14 getVideo, 14 getVideo,
15 getVideosList, 15 getVideosList,
@@ -18,8 +18,7 @@ import {
18 ServerInfo, 18 ServerInfo,
19 setAccessTokensToServers, 19 setAccessTokensToServers,
20 uploadVideo, 20 uploadVideo,
21 webtorrentAdd, 21 webtorrentAdd
22 generateHighBitrateVideo
23} from '../../../../shared/utils' 22} from '../../../../shared/utils'
24import { join } from 'path' 23import { join } from 'path'
25import { waitJobs } from '../../../../shared/utils/server/jobs' 24import { waitJobs } from '../../../../shared/utils/server/jobs'
diff --git a/shared/utils/requests/check-api-params.ts b/shared/utils/requests/check-api-params.ts
index edb47e0e9..a2a549682 100644
--- a/shared/utils/requests/check-api-params.ts
+++ b/shared/utils/requests/check-api-params.ts
@@ -1,5 +1,5 @@
1import { makeGetRequest } from './requests' 1import { makeGetRequest } from './requests'
2import { immutableAssign } from '..' 2import { immutableAssign } from '../miscs/miscs'
3 3
4function checkBadStartPagination (url: string, path: string, token?: string, query = {}) { 4function checkBadStartPagination (url: string, path: string, token?: string, query = {}) {
5 return makeGetRequest({ 5 return makeGetRequest({
diff --git a/shared/utils/search/videos.ts b/shared/utils/search/videos.ts
index 115b3ff9a..ba4627017 100644
--- a/shared/utils/search/videos.ts
+++ b/shared/utils/search/videos.ts
@@ -2,7 +2,7 @@
2 2
3import * as request from 'supertest' 3import * as request from 'supertest'
4import { VideosSearchQuery } from '../../models/search' 4import { VideosSearchQuery } from '../../models/search'
5import { immutableAssign } from '..' 5import { immutableAssign } from '../miscs/miscs'
6 6
7function searchVideo (url: string, search: string) { 7function searchVideo (url: string, search: string) {
8 const path = '/api/v1/search/videos' 8 const path = '/api/v1/search/videos'
diff --git a/shared/utils/server/config.ts b/shared/utils/server/config.ts
index 15a94432b..5b888b061 100644
--- a/shared/utils/server/config.ts
+++ b/shared/utils/server/config.ts
@@ -1,4 +1,4 @@
1import { makeDeleteRequest, makeGetRequest, makePutBodyRequest } from '../' 1import { makeDeleteRequest, makeGetRequest, makePutBodyRequest } from '../requests/requests'
2import { CustomConfig } from '../../models/server/custom-config.model' 2import { CustomConfig } from '../../models/server/custom-config.model'
3 3
4function getConfig (url: string) { 4function getConfig (url: string) {
diff --git a/shared/utils/server/jobs.ts b/shared/utils/server/jobs.ts
index 3eec1d7d7..7c7e89824 100644
--- a/shared/utils/server/jobs.ts
+++ b/shared/utils/server/jobs.ts
@@ -1,6 +1,7 @@
1import * as request from 'supertest' 1import * as request from 'supertest'
2import { Job, JobState } from '../../models' 2import { Job, JobState } from '../../models'
3import { ServerInfo, wait } from '../index' 3import { wait } from '../miscs/miscs'
4import { ServerInfo } from './servers'
4 5
5function getJobsList (url: string, accessToken: string, state: JobState) { 6function getJobsList (url: string, accessToken: string, state: JobState) {
6 const path = '/api/v1/jobs/' + state 7 const path = '/api/v1/jobs/' + state
diff --git a/shared/utils/server/stats.ts b/shared/utils/server/stats.ts
index 01989d952..6f079ad18 100644
--- a/shared/utils/server/stats.ts
+++ b/shared/utils/server/stats.ts
@@ -1,4 +1,4 @@
1import { makeGetRequest } from '../' 1import { makeGetRequest } from '../requests/requests'
2 2
3function getStats (url: string, useCache = false) { 3function getStats (url: string, useCache = false) {
4 const path = '/api/v1/server/stats' 4 const path = '/api/v1/server/stats'
diff --git a/shared/utils/users/accounts.ts b/shared/utils/users/accounts.ts
index 5601f2a77..388eb6973 100644
--- a/shared/utils/users/accounts.ts
+++ b/shared/utils/users/accounts.ts
@@ -4,7 +4,7 @@ import { expect } from 'chai'
4import { existsSync, readdir } from 'fs-extra' 4import { existsSync, readdir } from 'fs-extra'
5import { join } from 'path' 5import { join } from 'path'
6import { Account } from '../../models/actors' 6import { Account } from '../../models/actors'
7import { root } from '../index' 7import { root } from '../miscs/miscs'
8import { makeGetRequest } from '../requests/requests' 8import { makeGetRequest } from '../requests/requests'
9 9
10function getAccountsList (url: string, sort = '-createdAt', statusCodeExpected = 200) { 10function getAccountsList (url: string, sort = '-createdAt', statusCodeExpected = 200) {
diff --git a/shared/utils/users/blocklist.ts b/shared/utils/users/blocklist.ts
index 35b537571..0ead5e5f6 100644
--- a/shared/utils/users/blocklist.ts
+++ b/shared/utils/users/blocklist.ts
@@ -1,6 +1,6 @@
1/* tslint:disable:no-unused-expression */ 1/* tslint:disable:no-unused-expression */
2 2
3import { makeDeleteRequest, makePostBodyRequest } from '../index' 3import { makeDeleteRequest, makePostBodyRequest } from '../requests/requests'
4import { makeGetRequest } from '../requests/requests' 4import { makeGetRequest } from '../requests/requests'
5 5
6function getAccountBlocklistByAccount ( 6function getAccountBlocklistByAccount (
diff --git a/shared/utils/users/user-subscriptions.ts b/shared/utils/users/user-subscriptions.ts
index b0e7da7cc..7148fbfca 100644
--- a/shared/utils/users/user-subscriptions.ts
+++ b/shared/utils/users/user-subscriptions.ts
@@ -1,4 +1,4 @@
1import { makeDeleteRequest, makeGetRequest, makePostBodyRequest } from '../' 1import { makeDeleteRequest, makeGetRequest, makePostBodyRequest } from '../requests/requests'
2 2
3function addUserSubscription (url: string, token: string, targetUri: string, statusCodeExpected = 204) { 3function addUserSubscription (url: string, token: string, targetUri: string, statusCodeExpected = 204) {
4 const path = '/api/v1/users/me/subscriptions' 4 const path = '/api/v1/users/me/subscriptions'
diff --git a/shared/utils/users/users.ts b/shared/utils/users/users.ts
index 1b385aaf7..d5d62a507 100644
--- a/shared/utils/users/users.ts
+++ b/shared/utils/users/users.ts
@@ -1,5 +1,5 @@
1import * as request from 'supertest' 1import * as request from 'supertest'
2import { makePostBodyRequest, makePutBodyRequest, updateAvatarRequest } from '../' 2import { makePostBodyRequest, makePutBodyRequest, updateAvatarRequest } from '../requests/requests'
3 3
4import { UserRole } from '../../index' 4import { UserRole } from '../../index'
5import { NSFWPolicyType } from '../../models/videos/nsfw-policy.type' 5import { NSFWPolicyType } from '../../models/videos/nsfw-policy.type'
diff --git a/shared/utils/videos/video-abuses.ts b/shared/utils/videos/video-abuses.ts
index 8be891a9b..7f011ec0f 100644
--- a/shared/utils/videos/video-abuses.ts
+++ b/shared/utils/videos/video-abuses.ts
@@ -1,6 +1,6 @@
1import * as request from 'supertest' 1import * as request from 'supertest'
2import { VideoAbuseUpdate } from '../../models/videos/abuse/video-abuse-update.model' 2import { VideoAbuseUpdate } from '../../models/videos/abuse/video-abuse-update.model'
3import { makeDeleteRequest, makePutBodyRequest } from '..' 3import { makeDeleteRequest, makePutBodyRequest } from '../requests/requests'
4 4
5function reportVideoAbuse (url: string, token: string, videoId: number | string, reason: string, specialStatus = 200) { 5function reportVideoAbuse (url: string, token: string, videoId: number | string, reason: string, specialStatus = 200) {
6 const path = '/api/v1/videos/' + videoId + '/abuse' 6 const path = '/api/v1/videos/' + videoId + '/abuse'
diff --git a/shared/utils/videos/video-captions.ts b/shared/utils/videos/video-captions.ts
index 41e52be07..8d67f617b 100644
--- a/shared/utils/videos/video-captions.ts
+++ b/shared/utils/videos/video-captions.ts
@@ -1,7 +1,7 @@
1import { makeDeleteRequest, makeGetRequest } from '../' 1import { makeDeleteRequest, makeGetRequest, makeUploadRequest } from '../requests/requests'
2import { buildAbsoluteFixturePath, makeUploadRequest } from '../index'
3import * as request from 'supertest' 2import * as request from 'supertest'
4import * as chai from 'chai' 3import * as chai from 'chai'
4import { buildAbsoluteFixturePath } from '../miscs/miscs'
5 5
6const expect = chai.expect 6const expect = chai.expect
7 7
diff --git a/shared/utils/videos/video-channels.ts b/shared/utils/videos/video-channels.ts
index 3d37f0e4c..3935c261e 100644
--- a/shared/utils/videos/video-channels.ts
+++ b/shared/utils/videos/video-channels.ts
@@ -1,6 +1,6 @@
1import * as request from 'supertest' 1import * as request from 'supertest'
2import { VideoChannelCreate, VideoChannelUpdate } from '../../models/videos' 2import { VideoChannelCreate, VideoChannelUpdate } from '../../models/videos'
3import { updateAvatarRequest } from '../index' 3import { updateAvatarRequest } from '../requests/requests'
4 4
5function getVideoChannelsList (url: string, start: number, count: number, sort?: string) { 5function getVideoChannelsList (url: string, start: number, count: number, sort?: string) {
6 const path = '/api/v1/video-channels' 6 const path = '/api/v1/video-channels'
diff --git a/shared/utils/videos/video-comments.ts b/shared/utils/videos/video-comments.ts
index 7d4cae364..0ebf69ced 100644
--- a/shared/utils/videos/video-comments.ts
+++ b/shared/utils/videos/video-comments.ts
@@ -1,5 +1,5 @@
1import * as request from 'supertest' 1import * as request from 'supertest'
2import { makeDeleteRequest } from '../' 2import { makeDeleteRequest } from '../requests/requests'
3 3
4function getVideoCommentThreads (url: string, videoId: number | string, start: number, count: number, sort?: string, token?: string) { 4function getVideoCommentThreads (url: string, videoId: number | string, start: number, count: number, sort?: string, token?: string) {
5 const path = '/api/v1/videos/' + videoId + '/comment-threads' 5 const path = '/api/v1/videos/' + videoId + '/comment-threads'
diff --git a/shared/utils/videos/video-imports.ts b/shared/utils/videos/video-imports.ts
index bf5062cd1..3fa49b432 100644
--- a/shared/utils/videos/video-imports.ts
+++ b/shared/utils/videos/video-imports.ts
@@ -1,5 +1,6 @@
1
1import { VideoImportCreate } from '../../models/videos' 2import { VideoImportCreate } from '../../models/videos'
2import { makeGetRequest, makeUploadRequest } from '..' 3import { makeGetRequest, makeUploadRequest } from '../requests/requests'
3 4
4function getYoutubeVideoUrl () { 5function getYoutubeVideoUrl () {
5 return 'https://youtu.be/msX3jv1XdvM' 6 return 'https://youtu.be/msX3jv1XdvM'
diff --git a/shared/utils/videos/videos.ts b/shared/utils/videos/videos.ts
index b3206e566..1ab3e7c4b 100644
--- a/shared/utils/videos/videos.ts
+++ b/shared/utils/videos/videos.ts
@@ -16,9 +16,10 @@ import {
16 ServerInfo, 16 ServerInfo,
17 testImage 17 testImage
18} from '../' 18} from '../'
19
19import { VideoDetails, VideoPrivacy } from '../../models/videos' 20import { VideoDetails, VideoPrivacy } from '../../models/videos'
20import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../server/initializers' 21import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../server/initializers/constants'
21import { dateIsValid, webtorrentAdd } from '../index' 22import { dateIsValid, webtorrentAdd } from '../miscs/miscs'
22 23
23type VideoAttributes = { 24type VideoAttributes = {
24 name?: string 25 name?: string
diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml
index af829cc62..aa6be7e87 100644
--- a/support/doc/api/openapi.yaml
+++ b/support/doc/api/openapi.yaml
@@ -101,14 +101,13 @@ x-tagGroups:
101 - Video 101 - Video
102 - Video Channel 102 - Video Channel
103 - Video Comment 103 - Video Comment
104 - Video Abuse
105 - Video Following 104 - Video Following
106 - Video Rate 105 - Video Rate
107 - name: Moderation 106 - name: Moderation
108 tags: 107 tags:
109 - Video Abuse 108 - Video Abuse
110 - Video Blacklist 109 - Video Blacklist
111 - name: Public Instance Information 110 - name: Instance Configuration
112 tags: 111 tags:
113 - Config 112 - Config
114 - Server Following 113 - Server Following
@@ -301,7 +300,7 @@ paths:
301 responses: 300 responses:
302 '200': 301 '200':
303 description: successful operation 302 description: successful operation
304 /jobs: 303 /jobs/{state}:
305 get: 304 get:
306 summary: Get list of jobs 305 summary: Get list of jobs
307 security: 306 security:
@@ -316,6 +315,12 @@ paths:
316 description: The state of the job 315 description: The state of the job
317 schema: 316 schema:
318 type: string 317 type: string
318 enum:
319 - active
320 - completed
321 - failed
322 - waiting
323 - delayed
319 - $ref: '#/components/parameters/start' 324 - $ref: '#/components/parameters/start'
320 - $ref: '#/components/parameters/count' 325 - $ref: '#/components/parameters/count'
321 - $ref: '#/components/parameters/sort' 326 - $ref: '#/components/parameters/sort'
diff --git a/support/doc/api/quickstart.md b/support/doc/api/quickstart.md
index 844248a7f..6c19b59ee 100644
--- a/support/doc/api/quickstart.md
+++ b/support/doc/api/quickstart.md
@@ -43,7 +43,7 @@ Response example:
43Just use the `access_token` in the `Authorization` header: 43Just use the `access_token` in the `Authorization` header:
44 44
45``` 45```
46$ curl -H 'Authorization: Bearer 90286a0bdf0f7315d9d3fe8dabf9e1d2be9c97d0' https://peertube.example.com/api/v1/jobs/complete 46$ curl -H 'Authorization: Bearer 90286a0bdf0f7315d9d3fe8dabf9e1d2be9c97d0' https://peertube.example.com/api/v1/jobs/completed
47``` 47```
48 48
49 49
@@ -51,4 +51,4 @@ $ curl -H 'Authorization: Bearer 90286a0bdf0f7315d9d3fe8dabf9e1d2be9c97d0' https
51 51
52``` 52```
53$ curl https://peertube.example.com/api/v1/videos 53$ curl https://peertube.example.com/api/v1/videos
54``` \ No newline at end of file 54```