]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Remove ng2 file upload module
authorChocobozzz <florian.bigard@gmail.com>
Thu, 14 Sep 2017 15:06:31 +0000 (17:06 +0200)
committerChocobozzz <florian.bigard@gmail.com>
Thu, 14 Sep 2017 15:25:36 +0000 (17:25 +0200)
Unmaintained and we don't need it anymore with httpclient

20 files changed:
client/package.json
client/src/app/+admin/friends/friend-add/friend-add.component.ts
client/src/app/+admin/friends/friend-list/friend-list.component.ts
client/src/app/+admin/request-schedulers/request-schedulers-stats/request-schedulers-stats.component.ts
client/src/app/+admin/users/user-list/user-list.component.ts
client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts
client/src/app/app.component.ts
client/src/app/shared/forms/form-validators/video.ts
client/src/app/shared/rest/rest-extractor.service.ts
client/src/app/shared/shared.module.ts
client/src/app/videos/shared/video.service.ts
client/src/app/videos/video-edit/video-add.component.html
client/src/app/videos/video-edit/video-add.component.ts
client/src/app/videos/video-edit/video-update.component.ts
client/src/app/videos/video-watch/video-report.component.ts
client/src/app/videos/video-watch/video-watch.component.ts
client/yarn.lock
server/middlewares/validators/pods.ts
server/middlewares/validators/users.ts
server/middlewares/validators/videos.ts

index caec34e449334cc2c00bdf5cbe320e526964d35c..8a82a294e66241ffc1c4b5120e3052c89aa23107 100644 (file)
@@ -61,7 +61,6 @@
     "intl": "^1.2.4",
     "json-loader": "^0.5.4",
     "ng-router-loader": "^2.0.0",
-    "ng2-file-upload": "^1.1.4-2",
     "ngc-webpack": "3.2.2",
     "ngx-bootstrap": "1.9.1",
     "ngx-chips": "1.5.3",
index e0b73dfa3c6d4bd485d53648c22289e5ae8e16ac..6580e1b881492379ce55ce59abe1d1f493b68ff5 100644 (file)
@@ -98,7 +98,7 @@ export class FriendAddComponent implements OnInit {
             setTimeout(() => this.router.navigate([ '/admin/friends/list' ]), 1000)
           },
 
-          err => this.notificationsService.error('Error', err)
+          err => this.notificationsService.error('Error', err.message)
         )
       }
     )
index 6a8bd492cdecd334ef5a24fe778630a4ca12c7f4..4af39c47e84366bbd6d4eefe04cd8d89f26cfab4 100644 (file)
@@ -40,7 +40,7 @@ export class FriendListComponent implements OnInit {
             this.loadData()
           },
 
-          err => this.notificationsService.error('Error', err)
+          err => this.notificationsService.error('Error', err.message)
         )
       }
     )
@@ -59,7 +59,7 @@ export class FriendListComponent implements OnInit {
             this.loadData()
           },
 
-          err => this.notificationsService.error('Error', err)
+          err => this.notificationsService.error('Error', err.message)
         )
       }
     )
@@ -72,7 +72,7 @@ export class FriendListComponent implements OnInit {
                           this.friends = resultList.data
                         },
 
-                        err => this.notificationsService.error('Error', err)
+                        err => this.notificationsService.error('Error', err.message)
                       )
   }
 }
index 1edeb31febf135126fe5db9c4dcf779c89144c8b..1654827abc0980ab7864c4cdc725d370aaecee60 100644 (file)
@@ -57,7 +57,7 @@ export class RequestSchedulersStatsComponent implements OnInit, OnDestroy {
     this.requestService.getStats().subscribe(
       stats => this.stats = stats,
 
-      err => this.notificationsService.error('Error', err)
+      err => this.notificationsService.error('Error', err.message)
     )
   }
 
index c3fa55825bca613e789943c3f5e53c8fd4917d32..73b5c0ce9899093282f276759bc55c5ff5d6c660 100644 (file)
@@ -47,7 +47,7 @@ export class UserListComponent extends RestTable implements OnInit {
             this.loadData()
           },
 
-          err => this.notificationsService.error('Error', err)
+          err => this.notificationsService.error('Error', err.message)
         )
       }
     )
@@ -65,7 +65,7 @@ export class UserListComponent extends RestTable implements OnInit {
                         this.totalRecords = resultList.total
                       },
 
-                      err => this.notificationsService.error('Error', err)
+                      err => this.notificationsService.error('Error', err.message)
                     )
   }
 }
index 5a0131a814dede72b6a9586b8f9c53b3fc87bb2f..92de11f0e38173af9f6ff5d36b4fcda8b4368f40 100644 (file)
@@ -40,7 +40,7 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
                    this.totalRecords = resultList.total
                  },
 
-                 err => this.notificationsService.error('Error', err)
+                 err => this.notificationsService.error('Error', err.message)
                )
   }
 }
index 57bf64f69d8455e1336d0fcad9e204420778ef43..ae86bc96f035bf2baea5ee669bef5504aed8d74c 100644 (file)
@@ -31,8 +31,7 @@ export class AppComponent implements OnInit {
     private authService: AuthService,
     private configService: ConfigService,
     private userService: UserService,
-    private videoService: VideoService,
-    viewContainerRef: ViewContainerRef
+    private videoService: VideoService
   ) {}
 
   ngOnInit () {
index 6542cf8f6e34db47e0ae57627bff64306446e094..32b1f1c2ebf0fb8fc02dffa9f852450a2383caf0 100644 (file)
@@ -44,3 +44,10 @@ export const VIDEO_TAGS = {
     'maxlength': 'A tag should be less than 10 characters long.'
   }
 }
+
+export const VIDEO_FILE = {
+  VALIDATORS: [ Validators.required ],
+  MESSAGES: {
+    'required': 'Video file is required.'
+  }
+}
index 32dad5c732e00e47cecf3e67710ad7df7d713388..1f6222da82386815383fc7505107b185cbd6d8f2 100644 (file)
@@ -40,19 +40,29 @@ export class RestExtractor {
   handleError (err: HttpErrorResponse) {
     let errorMessage
 
+    console.log(err)
+
     if (err.error instanceof Error) {
       // A client-side or network error occurred. Handle it accordingly.
       errorMessage = err.error.message
       console.error('An error occurred:', errorMessage)
     } else if (err.status !== undefined) {
-      // The backend returned an unsuccessful response code.
-      // The response body may contain clues as to what went wrong,
-      errorMessage = err.error
+      const body = err.error
+      errorMessage = body.error
       console.error(`Backend returned code ${err.status}, body was: ${errorMessage}`)
     } else {
       errorMessage = err
     }
 
-    return Observable.throw(errorMessage)
+    const errorObj = {
+      message: errorMessage,
+      status: undefined
+    }
+
+    if (err.status) {
+      errorObj.status = err.status
+    }
+
+    return Observable.throw(errorObj)
   }
 }
index 118ce822d03f8a1f7b4b7b6b401c421cbef73056..a28ac322da9d534456d2e0cc15ca2d10d2976e7b 100644 (file)
@@ -10,7 +10,6 @@ import { BsDropdownModule } from 'ngx-bootstrap/dropdown'
 import { ProgressbarModule } from 'ngx-bootstrap/progressbar'
 import { PaginationModule } from 'ngx-bootstrap/pagination'
 import { ModalModule } from 'ngx-bootstrap/modal'
-import { FileUploadModule } from 'ng2-file-upload/ng2-file-upload'
 import { DataTableModule, SharedModule as PrimeSharedModule } from 'primeng/primeng'
 
 import { AUTH_INTERCEPTOR_PROVIDER } from './auth'
@@ -32,8 +31,6 @@ import { VideoAbuseService } from './video-abuse'
     PaginationModule.forRoot(),
     ProgressbarModule.forRoot(),
 
-    FileUploadModule,
-
     DataTableModule,
     PrimeSharedModule
   ],
@@ -52,7 +49,6 @@ import { VideoAbuseService } from './video-abuse'
     HttpClientModule,
 
     BsDropdownModule,
-    FileUploadModule,
     ModalModule,
     PaginationModule,
     ProgressbarModule,
index b6d2a06662d3c6982464a9dcb1643cf16ee4fd48..cfce4cb16d6b54ca9420c73f1a2af22e0f724ebc 100644 (file)
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'
 import { Observable } from 'rxjs/Observable'
 import 'rxjs/add/operator/catch'
 import 'rxjs/add/operator/map'
-import { HttpClient, HttpParams } from '@angular/common/http'
+import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'
 
 import { Search } from '../../shared'
 import { SortField } from './sort-field.type'
@@ -14,13 +14,14 @@ import {
 import { Video } from './video.model'
 import { VideoPagination } from './video-pagination.model'
 import {
-UserVideoRate,
-VideoRateType,
-VideoUpdate,
-VideoAbuseCreate,
-UserVideoRateUpdate,
-Video as VideoServerModel,
-ResultList
+  VideoCreate,
+  UserVideoRate,
+  VideoRateType,
+  VideoUpdate,
+  VideoAbuseCreate,
+  UserVideoRateUpdate,
+  Video as VideoServerModel,
+  ResultList
 } from '../../../../../shared'
 
 @Injectable()
@@ -73,6 +74,14 @@ export class VideoService {
                         .catch(this.restExtractor.handleError)
   }
 
+  // uploadVideo (video: VideoCreate) {
+  uploadVideo (video: any) {
+    const req = new HttpRequest('POST', `${VideoService.BASE_VIDEO_URL}/upload`, video, { reportProgress: true })
+
+    return this.authHttp.request(req)
+                        .catch(this.restExtractor.handleError)
+  }
+
   getVideos (videoPagination: VideoPagination, sort: SortField) {
     const pagination = this.videoPaginationToRestPagination(videoPagination)
 
index 7ad671ae7814953b4104108f47f0edf513314d6e..cf8fc2b809ea993c8620a3bf5c49e79c52d2d2d1 100644 (file)
@@ -3,7 +3,7 @@
 
     <h3>Upload a video</h3>
 
-    <div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+    <div *ngIf="error !== undefined" class="alert alert-danger">{{ error }}</div>
 
     <form novalidate [formGroup]="form">
       <div class="form-group">
@@ -62,7 +62,7 @@
       </div>
 
       <div class="form-group">
-        <label for="tags" class="label-tags">Tags</label> <span class="little-information">(press enter to add the tag)</span>
+        <label class="label-tags">Tags</label> <span class="little-information">(press enter to add the tag)</span>
         <tag-input
           [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
           formControlName="tags" maxItems="3" modelAsStrings="true"
 
       <div class="form-group">
         <label for="videofile">File</label>
-        <div class="btn btn-default btn-file" [ngClass]="{ 'disabled': filename !== null }" >
+        <div class="btn btn-default btn-file">
           <span>Select the video...</span>
-          <input
-            type="file" name="videofile" id="videofile"
-            ng2FileSelect [uploader]="uploader" [disabled]="filename !== null"
-            (change)="fileChanged()"
-          >
+          <input #videofileInput type="file" name="videofile" id="videofile" (change)="fileChange($event)" />
+          <input type="hidden" name="videofileHidden" formControlName="videofile"/>
         </div>
       </div>
 
       <div class="file-to-upload">
-        <div class="file" *ngIf="uploader.queue.length > 0">
+        <div class="file" *ngIf="filename">
           <span class="filename">{{ filename }}</span>
           <span class="glyphicon glyphicon-remove" (click)="removeFile()"></span>
         </div>
       </div>
 
-      <div *ngIf="fileError" class="alert alert-danger">
-        {{ fileError }}
+      <div *ngIf="formErrors.videofile" class="alert alert-danger">
+        {{ formErrors.videofile }}
       </div>
 
       <div class="form-group">
       </div>
 
       <div class="progress">
-        <progressbar [value]="uploader.progress" max="100"></progressbar>
+        <progressbar [value]="progressPercent" max="100"></progressbar>
       </div>
 
       <div class="form-group">
index 42b11cd087eb24ee8b0bb1aa3e9eae6bb1443b4f..537ef9bc3ec551aa79fb022ae73513a00ac9c795 100644 (file)
@@ -1,11 +1,9 @@
-import { Component, ElementRef, OnInit } from '@angular/core'
+import { Component, OnInit, ViewChild } from '@angular/core'
 import { FormBuilder, FormGroup } from '@angular/forms'
 import { Router } from '@angular/router'
 
-import { FileUploader } from 'ng2-file-upload/ng2-file-upload'
 import { NotificationsService } from 'angular2-notifications'
 
-import { AuthService } from '../../core'
 import {
   FormReactive,
   VIDEO_NAME,
@@ -17,6 +15,8 @@ import {
 } from '../../shared'
 import { VideoService } from '../shared'
 import { VideoCreate } from '../../../../../shared'
+import { HttpEventType, HttpResponse } from '@angular/common/http'
+import { VIDEO_FILE } from '../../shared/forms/form-validators/video'
 
 @Component({
   selector: 'my-videos-add',
@@ -25,8 +25,10 @@ import { VideoCreate } from '../../../../../shared'
 })
 
 export class VideoAddComponent extends FormReactive implements OnInit {
+  @ViewChild('videofileInput') videofileInput
+
+  progressPercent = 0
   tags: string[] = []
-  uploader: FileUploader
   videoCategories = []
   videoLicences = []
   videoLanguages = []
@@ -34,29 +36,26 @@ export class VideoAddComponent extends FormReactive implements OnInit {
   tagValidators = VIDEO_TAGS.VALIDATORS
   tagValidatorsMessages = VIDEO_TAGS.MESSAGES
 
-  error: string = null
+  error: string
   form: FormGroup
   formErrors = {
     name: '',
     category: '',
     licence: '',
     language: '',
-    description: ''
+    description: '',
+    videofile: ''
   }
   validationMessages = {
     name: VIDEO_NAME.MESSAGES,
     category: VIDEO_CATEGORY.MESSAGES,
     licence: VIDEO_LICENCE.MESSAGES,
     language: VIDEO_LANGUAGE.MESSAGES,
-    description: VIDEO_DESCRIPTION.MESSAGES
+    description: VIDEO_DESCRIPTION.MESSAGES,
+    videofile: VIDEO_FILE.MESSAGES
   }
 
-  // Special error messages
-  fileError = ''
-
   constructor (
-    private authService: AuthService,
-    private elementRef: ElementRef,
     private formBuilder: FormBuilder,
     private router: Router,
     private notificationsService: NotificationsService,
@@ -66,11 +65,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
   }
 
   get filename () {
-    if (this.uploader.queue.length === 0) {
-      return null
-    }
-
-    return this.uploader.queue[0].file.name
+    return this.form.value['videofile']
   }
 
   buildForm () {
@@ -81,7 +76,8 @@ export class VideoAddComponent extends FormReactive implements OnInit {
       licence: [ '', VIDEO_LICENCE.VALIDATORS ],
       language: [ '', VIDEO_LANGUAGE.VALIDATORS ],
       description: [ '', VIDEO_DESCRIPTION.VALIDATORS ],
-      tags: [ '']
+      videofile: [ '', VIDEO_FILE.VALIDATORS ],
+      tags: [ '' ]
     })
 
     this.form.valueChanges.subscribe(data => this.onValueChanged(data))
@@ -92,60 +88,24 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     this.videoLicences = this.videoService.videoLicences
     this.videoLanguages = this.videoService.videoLanguages
 
-    this.uploader = new FileUploader({
-      authToken: this.authService.getRequestHeaderValue(),
-      queueLimit: 1,
-      url: API_URL + '/api/v1/videos/upload',
-      removeAfterUpload: true
-    })
-
-    this.uploader.onBuildItemForm = (item, form: FormData) => {
-      const formValue: VideoCreate = this.form.value
-
-      const name = formValue.name
-      const nsfw = formValue.nsfw
-      const category = formValue.category
-      const licence = formValue.licence
-      const language = formValue.language
-      const description = formValue.description
-      const tags = formValue.tags
-
-      form.append('name', name)
-      form.append('category', '' + category)
-      form.append('nsfw', '' + nsfw)
-      form.append('licence', '' + licence)
-
-      // Language is optional
-      if (language) {
-        form.append('language', '' + language)
-      }
-
-      form.append('description', description)
-
-      for (let i = 0; i < tags.length; i++) {
-        form.append(`tags[${i}]`, tags[i])
-      }
-    }
-
     this.buildForm()
   }
 
-  checkForm () {
-    this.forceCheck()
-
-    if (this.filename === null) {
-      this.fileError = 'You did not add a file.'
-    }
-
-    return this.form.valid === true && this.fileError === ''
+  // The goal is to keep reactive form validation (required field)
+  // https://stackoverflow.com/a/44238894
+  fileChange ($event) {
+    this.form.controls['videofile'].setValue($event.target.files[0].name)
   }
 
-  fileChanged () {
-    this.fileError = ''
+  removeFile () {
+    this.videofileInput.nativeElement.value = ''
+    this.form.controls['videofile'].setValue('')
   }
 
-  removeFile () {
-    this.uploader.clearQueue()
+  checkForm () {
+    this.forceCheck()
+
+    return this.form.valid
   }
 
   upload () {
@@ -153,39 +113,49 @@ export class VideoAddComponent extends FormReactive implements OnInit {
       return
     }
 
-    const item = this.uploader.queue[0]
-    // TODO: wait for https://github.com/valor-software/ng2-file-upload/pull/242
-    item.alias = 'videofile'
-
-    item.onSuccess = () => {
-      console.log('Video uploaded.')
-      this.notificationsService.success('Success', 'Video uploaded.')
-
-      // Print all the videos once it's finished
-      this.router.navigate(['/videos/list'])
+    const formValue: VideoCreate = this.form.value
+
+    const name = formValue.name
+    const nsfw = formValue.nsfw
+    const category = formValue.category
+    const licence = formValue.licence
+    const language = formValue.language
+    const description = formValue.description
+    const tags = formValue.tags
+    const videofile = this.videofileInput.nativeElement.files[0]
+
+    const formData = new FormData()
+    formData.append('name', name)
+    formData.append('category', '' + category)
+    formData.append('nsfw', '' + nsfw)
+    formData.append('licence', '' + licence)
+    formData.append('videofile', videofile)
+
+    // Language is optional
+    if (language) {
+      formData.append('language', '' + language)
     }
 
-    item.onError = (response: string, status: number) => {
-      // We need to handle manually these cases because we use the FileUpload component
-      if (status === 400) {
-        this.error = response
-      } else if (status === 401) {
-        this.error = 'Access token was expired, refreshing token...'
-        this.authService.refreshAccessToken().subscribe(
-          () => {
-            // Update the uploader request header
-            this.uploader.authToken = this.authService.getRequestHeaderValue()
-            this.error += ' access token refreshed. Please retry your request.'
-          }
-        )
-      } else if (status === 403) {
-        this.error = 'Your video quota is reached, you can\'t upload this video.'
-      } else {
-        this.error = 'Unknown error'
-        console.error(this.error)
-      }
+    formData.append('description', description)
+
+    for (let i = 0; i < tags.length; i++) {
+      formData.append(`tags[${i}]`, tags[i])
     }
 
-    this.uploader.uploadAll()
+    this.videoService.uploadVideo(formData).subscribe(
+      event => {
+        if (event.type === HttpEventType.UploadProgress) {
+          this.progressPercent = Math.round(100 * event.loaded / event.total)
+        } else if (event instanceof HttpResponse) {
+          console.log('Video uploaded.')
+          this.notificationsService.success('Success', 'Video uploaded.')
+
+          // Display all the videos once it's finished
+          this.router.navigate([ '/videos/list '])
+        }
+      },
+
+      err => this.error = err.message
+    )
   }
 }
index 6c57a23d8c8e5783cffaaf69e7f3c8394dc298f0..141ed3522a483ecdeb175abe4a91415989920213 100644 (file)
@@ -2,7 +2,6 @@ import { Component, ElementRef, OnInit } from '@angular/core'
 import { FormBuilder, FormGroup } from '@angular/forms'
 import { ActivatedRoute, Router } from '@angular/router'
 
-import { FileUploader } from 'ng2-file-upload/ng2-file-upload'
 import { NotificationsService } from 'angular2-notifications'
 
 import { AuthService } from '../../core'
index a5758060d7fd482fec62f900255c6ea3d2f0063e..d9c83a640bb45a154c37d9b48cd5294fe24fa398 100644 (file)
@@ -63,7 +63,7 @@ export class VideoReportComponent extends FormReactive implements OnInit {
                               this.hide()
                             },
 
-                            err => this.notificationsService.error('Error', err)
+                            err => this.notificationsService.error('Error', err.message)
                            )
   }
 }
index 9cedc9c761b448a855a509a62d455c3f6f8d0857..f5a47199d197030ab0a72390ae8be9453311a481 100644 (file)
@@ -158,7 +158,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
                         this.userRating = 'like'
                       },
 
-                      err => this.notificationsService.error('Error', err)
+                      err => this.notificationsService.error('Error', err.message)
                      )
   }
 
@@ -175,7 +175,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
                         this.userRating = 'dislike'
                       },
 
-                      err => this.notificationsService.error('Error', err)
+                      err => this.notificationsService.error('Error', err.message)
                      )
   }
 
@@ -275,7 +275,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
                          }
                        },
 
-                       err => this.notificationsService.error('Error', err)
+                       err => this.notificationsService.error('Error', err.message)
                       )
   }
 
index 3552dbf990659aac9e53b7346aef109c3a4c7379..b61da863660b00001bd73ba404580e775428a697 100644 (file)
@@ -4436,10 +4436,6 @@ ng-router-loader@^2.0.0:
     loader-utils "^0.2.16"
     recast "^0.11.20"
 
-ng2-file-upload@^1.1.4-2:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/ng2-file-upload/-/ng2-file-upload-1.2.1.tgz#5563c5dfd6f43fbfbe815c206e343464a0a6a197"
-
 ng2-material-dropdown@0.7.10:
   version "0.7.10"
   resolved "https://registry.yarnpkg.com/ng2-material-dropdown/-/ng2-material-dropdown-0.7.10.tgz#093471f2a9cadd726cbcb120b0ad7818a54fa5ed"
index 4d0e054b088eeb8575b483e2b33918860a74befc..3a0f56f6a7d783a253775874b436d96138799f61 100644 (file)
@@ -11,7 +11,11 @@ import { isTestInstance } from '../../helpers'
 function makeFriendsValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   // Force https if the administrator wants to make friends
   if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') {
-    return res.status(400).send('Cannot make friends with a non HTTPS web server.')
+    return res.status(400)
+              .json({
+                error: 'Cannot make friends with a non HTTPS web server.'
+              })
+              .end()
   }
 
   req.checkBody('hosts', 'Should have an array of unique hosts').isEachUniqueHostValid()
index aec6324bf0be21acf1d83f97f56dd46282ebf527..15c07c6936f01903d5d6d8dfd2542b7a70c89fe2 100644 (file)
@@ -45,9 +45,13 @@ function usersRemoveValidator (req: express.Request, res: express.Response, next
         return res.sendStatus(500)
       }
 
-      if (user.username === 'root') return res.status(400).send('Cannot remove the root user')
+      if (user.username === 'root') {
+        return res.status(400)
+                  .send({ error: 'Cannot remove the root user' })
+                  .end()
+      }
 
-      next()
+      return next()
     })
   })
 }
@@ -99,9 +103,13 @@ function usersVideoRatingValidator (req: express.Request, res: express.Response,
 
     videoPromise
       .then(video => {
-        if (!video) return res.status(404).send('Video not found')
+        if (!video) {
+          return res.status(404)
+                    .json({ error: 'Video not found' })
+                    .end()
+        }
 
-        next()
+        return next()
       })
       .catch(err => {
         logger.error('Error in user request validator.', err)
@@ -113,7 +121,9 @@ function usersVideoRatingValidator (req: express.Request, res: express.Response,
 function ensureUserRegistrationAllowed (req: express.Request, res: express.Response, next: express.NextFunction) {
   isSignupAllowed().then(allowed => {
     if (allowed === false) {
-      return res.status(403).send('User registration is not enabled or user limit is reached.')
+      return res.status(403)
+                .send({ error: 'User registration is not enabled or user limit is reached.' })
+                .end()
     }
 
     return next()
@@ -138,10 +148,14 @@ export {
 function checkUserExists (id: number, res: express.Response, callback: (err: Error, user: UserInstance) => void) {
   db.User.loadById(id)
     .then(user => {
-      if (!user) return res.status(404).send('User not found')
+      if (!user) {
+        return res.status(404)
+                  .send({ error: 'User not found' })
+                  .end()
+      }
 
       res.locals.user = user
-      callback(null, user)
+      return callback(null, user)
     })
     .catch(err => {
       logger.error('Error in user request validator.', err)
@@ -152,9 +166,13 @@ function checkUserExists (id: number, res: express.Response, callback: (err: Err
 function checkUserDoesNotAlreadyExist (username: string, email: string, res: express.Response, callback: () => void) {
   db.User.loadByUsernameOrEmail(username, email)
       .then(user => {
-        if (user) return res.status(409).send('User already exists.')
+        if (user) {
+          return res.status(409)
+                    .send({ error: 'User already exists.' })
+                    .end()
+        }
 
-        callback()
+        return callback()
       })
       .catch(err => {
         logger.error('Error in usersAdd request validator.', err)
index 519e3d46c630854ccdfbccc91dd69a5c3249a21d..213b4c46b93f9159c9bc10f8db5e863c4cecc60a 100644 (file)
@@ -30,7 +30,9 @@ function videosAddValidator (req: express.Request, res: express.Response, next:
     user.isAbleToUploadVideo(videoFile)
       .then(isAble => {
         if (isAble === false) {
-          res.status(403).send('The user video quota is exceeded with this video.')
+          res.status(403)
+             .json({ error: 'The user video quota is exceeded with this video.' })
+             .end()
 
           return undefined
         }
@@ -38,17 +40,23 @@ function videosAddValidator (req: express.Request, res: express.Response, next:
         return db.Video.getDurationFromFile(videoFile.path)
           .catch(err => {
             logger.error('Invalid input file in videosAddValidator.', err)
-            res.status(400).send('Invalid input file.')
+            res.status(400)
+               .json({ error: 'Invalid input file.' })
+               .end()
 
             return undefined
           })
       })
       .then(duration => {
         // Previous test failed, abort
-        if (duration === undefined) return undefined
+        if (duration === undefined) return
 
         if (!isVideoDurationValid('' + duration)) {
-          return res.status(400).send('Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).')
+          return res.status(400)
+                    .json({
+                      error: 'Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).'
+                    })
+                    .end()
         }
 
         videoFile['duration'] = duration
@@ -80,11 +88,15 @@ function videosUpdateValidator (req: express.Request, res: express.Response, nex
     checkVideoExists(req.params.id, res, () => {
       // We need to make additional checks
       if (res.locals.video.isOwned() === false) {
-        return res.status(403).send('Cannot update video of another pod')
+        return res.status(403)
+                  .json({ error: 'Cannot update video of another pod' })
+                  .end()
       }
 
       if (res.locals.video.Author.userId !== res.locals.oauth.token.User.id) {
-        return res.status(403).send('Cannot update video of another user')
+        return res.status(403)
+                  .json({ error: 'Cannot update video of another user' })
+                  .end()
       }
 
       next()
@@ -188,7 +200,11 @@ function checkVideoExists (id: string, res: express.Response, callback: () => vo
   }
 
   promise.then(video => {
-    if (!video) return res.status(404).send('Video not found')
+    if (!video) {
+      return res.status(404)
+                .json({ error: 'Video not found' })
+                .end()
+    }
 
     res.locals.video = video
     callback()
@@ -204,14 +220,18 @@ function checkUserCanDeleteVideo (userId: number, res: express.Response, callbac
   db.User.loadById(userId)
     .then(user => {
       if (res.locals.video.isOwned() === false) {
-        return res.status(403).send('Cannot remove video of another pod, blacklist it')
+        return res.status(403)
+                  .json({ error: 'Cannot remove video of another pod, blacklist it' })
+                  .end()
       }
 
       // Check if the user can delete the video
       // The user can delete it if s/he is an admin
       // Or if s/he is the video's author
       if (user.isAdmin() === false && res.locals.video.Author.userId !== res.locals.oauth.token.User.id) {
-        return res.status(403).send('Cannot remove video of another user')
+        return res.status(403)
+                  .json({ error: 'Cannot remove video of another user' })
+                  .end()
       }
 
       // If we reach this comment, we can delete the video
@@ -225,7 +245,9 @@ function checkUserCanDeleteVideo (userId: number, res: express.Response, callbac
 
 function checkVideoIsBlacklistable (req: express.Request, res: express.Response, callback: () => void) {
   if (res.locals.video.isOwned() === true) {
-    return res.status(403).send('Cannot blacklist a local video')
+    return res.status(403)
+              .json({ error: 'Cannot blacklist a local video' })
+              .end()
   }
 
   callback()