aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+admin/friends/friend-add/friend-add.component.ts2
-rw-r--r--client/src/app/+admin/users/shared/user.service.ts11
-rw-r--r--client/src/app/+admin/users/user-add/user-add.component.ts7
-rw-r--r--client/src/app/account/account-details/account-details.component.ts3
-rw-r--r--client/src/app/core/auth/auth-user.model.ts2
-rw-r--r--client/src/app/shared/users/user.service.ts15
-rw-r--r--client/src/app/signup/signup.component.ts7
-rw-r--r--client/src/app/videos/shared/video.service.ts63
-rw-r--r--client/src/app/videos/video-edit/video-add.component.ts27
-rwxr-xr-xscripts/watch/client.sh2
-rwxr-xr-xscripts/watch/server.sh2
-rw-r--r--server/controllers/api/remote/pods.ts8
-rw-r--r--server/controllers/api/remote/videos.ts43
-rw-r--r--server/controllers/api/users.ts16
-rw-r--r--server/controllers/api/videos/abuse.ts4
-rw-r--r--server/controllers/api/videos/index.ts5
-rw-r--r--server/controllers/api/videos/rate.ts23
-rw-r--r--server/helpers/requests.ts18
-rw-r--r--server/lib/friends.ts14
-rw-r--r--server/lib/request/abstract-request-scheduler.ts22
-rw-r--r--server/lib/request/request-scheduler.ts8
-rw-r--r--server/lib/request/request-video-event-scheduler.ts22
-rw-r--r--server/lib/request/request-video-qadu-scheduler.ts31
-rw-r--r--server/middlewares/secure.ts11
-rw-r--r--server/models/pod/pod-interface.ts2
-rw-r--r--server/models/user/user-interface.ts3
-rw-r--r--server/models/user/user-video-rate-interface.ts2
-rw-r--r--server/models/video/video-abuse-interface.ts2
-rw-r--r--server/models/video/video-blacklist-interface.ts2
-rw-r--r--server/models/video/video-interface.ts2
-rw-r--r--shared/models/index.ts9
-rw-r--r--shared/models/pods/index.ts3
-rw-r--r--shared/models/pods/pod-signature.model.ts4
-rw-r--r--shared/models/pods/pod.model.ts (renamed from shared/models/pod.model.ts)0
-rw-r--r--shared/models/pods/remote-video/index.ts7
-rw-r--r--shared/models/pods/remote-video/remote-qadu-video-request.model.ts10
-rw-r--r--shared/models/pods/remote-video/remote-video-create-request.model.ts27
-rw-r--r--shared/models/pods/remote-video/remote-video-event-request.model.ts11
-rw-r--r--shared/models/pods/remote-video/remote-video-remove-request.model.ts10
-rw-r--r--shared/models/pods/remote-video/remote-video-report-abuse-request.model.ts12
-rw-r--r--shared/models/pods/remote-video/remote-video-request.model.ts4
-rw-r--r--shared/models/pods/remote-video/remote-video-update-request.model.ts23
-rw-r--r--shared/models/user-video-rate.model.ts7
-rw-r--r--shared/models/users/index.ts4
-rw-r--r--shared/models/users/user-create.model.ts5
-rw-r--r--shared/models/users/user-role.type.ts1
-rw-r--r--shared/models/users/user-update.model.ts4
-rw-r--r--shared/models/users/user.model.ts (renamed from shared/models/user.model.ts)2
-rw-r--r--shared/models/videos/index.ts10
-rw-r--r--shared/models/videos/user-video-rate-update.model.ts5
-rw-r--r--shared/models/videos/user-video-rate.model.ts6
-rw-r--r--shared/models/videos/user-video-rate.type.ts1
-rw-r--r--shared/models/videos/video-abuse-create.model.ts3
-rw-r--r--shared/models/videos/video-abuse.model.ts (renamed from shared/models/video-abuse.model.ts)0
-rw-r--r--shared/models/videos/video-blacklist.model.ts (renamed from shared/models/video-blacklist.model.ts)0
-rw-r--r--shared/models/videos/video-create.model.ts9
-rw-r--r--shared/models/videos/video-rate.type.ts1
-rw-r--r--shared/models/videos/video-update.model.ts9
-rw-r--r--shared/models/videos/video.model.ts (renamed from shared/models/video.model.ts)0
59 files changed, 400 insertions, 166 deletions
diff --git a/client/src/app/+admin/friends/friend-add/friend-add.component.ts b/client/src/app/+admin/friends/friend-add/friend-add.component.ts
index 35cf4a1f7..0449d26a9 100644
--- a/client/src/app/+admin/friends/friend-add/friend-add.component.ts
+++ b/client/src/app/+admin/friends/friend-add/friend-add.component.ts
@@ -15,7 +15,7 @@ import { FriendService } from '../shared'
15}) 15})
16export class FriendAddComponent implements OnInit { 16export class FriendAddComponent implements OnInit {
17 form: FormGroup 17 form: FormGroup
18 hosts = [ ] 18 hosts: string[] = [ ]
19 error: string = null 19 error: string = null
20 20
21 constructor ( 21 constructor (
diff --git a/client/src/app/+admin/users/shared/user.service.ts b/client/src/app/+admin/users/shared/user.service.ts
index d52993a29..1c1cd575e 100644
--- a/client/src/app/+admin/users/shared/user.service.ts
+++ b/client/src/app/+admin/users/shared/user.service.ts
@@ -3,6 +3,7 @@ import 'rxjs/add/operator/catch'
3import 'rxjs/add/operator/map' 3import 'rxjs/add/operator/map'
4 4
5import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared' 5import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared'
6import { UserCreate } from '../../../../../../shared'
6 7
7@Injectable() 8@Injectable()
8export class UserService { 9export class UserService {
@@ -13,14 +14,8 @@ export class UserService {
13 private restExtractor: RestExtractor 14 private restExtractor: RestExtractor
14 ) {} 15 ) {}
15 16
16 addUser (username: string, password: string, email: string) { 17 addUser (userCreate: UserCreate) {
17 const body = { 18 return this.authHttp.post(UserService.BASE_USERS_URL, userCreate)
18 username,
19 email,
20 password
21 }
22
23 return this.authHttp.post(UserService.BASE_USERS_URL, body)
24 .map(this.restExtractor.extractDataBool) 19 .map(this.restExtractor.extractDataBool)
25 .catch(this.restExtractor.handleError) 20 .catch(this.restExtractor.handleError)
26 } 21 }
diff --git a/client/src/app/+admin/users/user-add/user-add.component.ts b/client/src/app/+admin/users/user-add/user-add.component.ts
index 2d25ab469..0dd99eccd 100644
--- a/client/src/app/+admin/users/user-add/user-add.component.ts
+++ b/client/src/app/+admin/users/user-add/user-add.component.ts
@@ -11,6 +11,7 @@ import {
11 USER_EMAIL, 11 USER_EMAIL,
12 USER_PASSWORD 12 USER_PASSWORD
13} from '../../../shared' 13} from '../../../shared'
14import { UserCreate } from '../../../../../../shared'
14 15
15@Component({ 16@Component({
16 selector: 'my-user-add', 17 selector: 'my-user-add',
@@ -57,11 +58,11 @@ export class UserAddComponent extends FormReactive implements OnInit {
57 addUser () { 58 addUser () {
58 this.error = null 59 this.error = null
59 60
60 const { username, password, email } = this.form.value 61 const userCreate: UserCreate = this.form.value
61 62
62 this.userService.addUser(username, password, email).subscribe( 63 this.userService.addUser(userCreate).subscribe(
63 () => { 64 () => {
64 this.notificationsService.success('Success', `User ${username} created.`) 65 this.notificationsService.success('Success', `User ${userCreate.username} created.`)
65 this.router.navigate([ '/admin/users/list' ]) 66 this.router.navigate([ '/admin/users/list' ])
66 }, 67 },
67 68
diff --git a/client/src/app/account/account-details/account-details.component.ts b/client/src/app/account/account-details/account-details.component.ts
index d7531cb55..547f045c4 100644
--- a/client/src/app/account/account-details/account-details.component.ts
+++ b/client/src/app/account/account-details/account-details.component.ts
@@ -11,6 +11,7 @@ import {
11 UserService, 11 UserService,
12 USER_PASSWORD 12 USER_PASSWORD
13} from '../../shared' 13} from '../../shared'
14import { UserUpdate } from '../../../../../shared'
14 15
15@Component({ 16@Component({
16 selector: 'my-account-details', 17 selector: 'my-account-details',
@@ -50,7 +51,7 @@ export class AccountDetailsComponent extends FormReactive implements OnInit {
50 51
51 updateDetails () { 52 updateDetails () {
52 const displayNSFW = this.form.value['displayNSFW'] 53 const displayNSFW = this.form.value['displayNSFW']
53 const details = { 54 const details: UserUpdate = {
54 displayNSFW 55 displayNSFW
55 } 56 }
56 57
diff --git a/client/src/app/core/auth/auth-user.model.ts b/client/src/app/core/auth/auth-user.model.ts
index 65c37bcfa..9cb201907 100644
--- a/client/src/app/core/auth/auth-user.model.ts
+++ b/client/src/app/core/auth/auth-user.model.ts
@@ -1,5 +1,5 @@
1// Do not use the barrel (dependency loop) 1// Do not use the barrel (dependency loop)
2import { UserRole } from '../../../../../shared/models/user.model' 2import { UserRole } from '../../../../../shared/models/users/user-role.type'
3import { User } from '../../shared/users/user.model' 3import { User } from '../../shared/users/user.model'
4 4
5export type TokenOptions = { 5export type TokenOptions = {
diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts
index e956df5b1..b479ac034 100644
--- a/client/src/app/shared/users/user.service.ts
+++ b/client/src/app/shared/users/user.service.ts
@@ -6,6 +6,7 @@ import 'rxjs/add/operator/map'
6import { AuthService } from '../../core' 6import { AuthService } from '../../core'
7import { AuthHttp } from '../auth' 7import { AuthHttp } from '../auth'
8import { RestExtractor } from '../rest' 8import { RestExtractor } from '../rest'
9import { UserCreate, UserUpdate } from '../../../../../shared'
9 10
10@Injectable() 11@Injectable()
11export class UserService { 12export class UserService {
@@ -27,7 +28,7 @@ export class UserService {
27 28
28 changePassword (newPassword: string) { 29 changePassword (newPassword: string) {
29 const url = UserService.BASE_USERS_URL + this.authService.getUser().id 30 const url = UserService.BASE_USERS_URL + this.authService.getUser().id
30 const body = { 31 const body: UserUpdate = {
31 password: newPassword 32 password: newPassword
32 } 33 }
33 34
@@ -36,7 +37,7 @@ export class UserService {
36 .catch((res) => this.restExtractor.handleError(res)) 37 .catch((res) => this.restExtractor.handleError(res))
37 } 38 }
38 39
39 updateDetails (details: { displayNSFW: boolean }) { 40 updateDetails (details: UserUpdate) {
40 const url = UserService.BASE_USERS_URL + this.authService.getUser().id 41 const url = UserService.BASE_USERS_URL + this.authService.getUser().id
41 42
42 return this.authHttp.put(url, details) 43 return this.authHttp.put(url, details)
@@ -44,14 +45,8 @@ export class UserService {
44 .catch((res) => this.restExtractor.handleError(res)) 45 .catch((res) => this.restExtractor.handleError(res))
45 } 46 }
46 47
47 signup (username: string, password: string, email: string) { 48 signup (userCreate: UserCreate) {
48 const body = { 49 return this.http.post(UserService.BASE_USERS_URL + 'register', userCreate)
49 username,
50 email,
51 password
52 }
53
54 return this.http.post(UserService.BASE_USERS_URL + 'register', body)
55 .map(this.restExtractor.extractDataBool) 50 .map(this.restExtractor.extractDataBool)
56 .catch(this.restExtractor.handleError) 51 .catch(this.restExtractor.handleError)
57 } 52 }
diff --git a/client/src/app/signup/signup.component.ts b/client/src/app/signup/signup.component.ts
index bcbc8ded3..981fe3c3b 100644
--- a/client/src/app/signup/signup.component.ts
+++ b/client/src/app/signup/signup.component.ts
@@ -12,6 +12,7 @@ import {
12 USER_EMAIL, 12 USER_EMAIL,
13 USER_PASSWORD 13 USER_PASSWORD
14} from '../shared' 14} from '../shared'
15import { UserCreate } from '../../../../shared'
15 16
16@Component({ 17@Component({
17 selector: 'my-signup', 18 selector: 'my-signup',
@@ -58,11 +59,11 @@ export class SignupComponent extends FormReactive implements OnInit {
58 signup () { 59 signup () {
59 this.error = null 60 this.error = null
60 61
61 const { username, password, email } = this.form.value 62 const userCreate: UserCreate = this.form.value
62 63
63 this.userService.signup(username, password, email).subscribe( 64 this.userService.signup(userCreate).subscribe(
64 () => { 65 () => {
65 this.notificationsService.success('Success', `Registration for ${username} complete.`) 66 this.notificationsService.success('Success', `Registration for ${userCreate.username} complete.`)
66 this.router.navigate([ '/videos/list' ]) 67 this.router.navigate([ '/videos/list' ])
67 }, 68 },
68 69
diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts
index 7658d8ff0..dc12c0637 100644
--- a/client/src/app/videos/shared/video.service.ts
+++ b/client/src/app/videos/shared/video.service.ts
@@ -16,7 +16,13 @@ import {
16 UserService 16 UserService
17} from '../../shared' 17} from '../../shared'
18import { Video } from './video.model' 18import { Video } from './video.model'
19import { UserVideoRate, VideoRateType } from '../../../../../shared' 19import {
20 UserVideoRate,
21 VideoRateType,
22 VideoUpdate,
23 VideoAbuseCreate,
24 UserVideoRateUpdate
25} from '../../../../../shared'
20 26
21@Injectable() 27@Injectable()
22export class VideoService { 28export class VideoService {
@@ -35,42 +41,15 @@ export class VideoService {
35 ) {} 41 ) {}
36 42
37 loadVideoCategories () { 43 loadVideoCategories () {
38 return this.http.get(VideoService.BASE_VIDEO_URL + 'categories') 44 return this.loadVideoAttributeEnum('categories', this.videoCategories)
39 .map(this.restExtractor.extractDataGet)
40 .subscribe(data => {
41 Object.keys(data).forEach(categoryKey => {
42 this.videoCategories.push({
43 id: parseInt(categoryKey, 10),
44 label: data[categoryKey]
45 })
46 })
47 })
48 } 45 }
49 46
50 loadVideoLicences () { 47 loadVideoLicences () {
51 return this.http.get(VideoService.BASE_VIDEO_URL + 'licences') 48 return this.loadVideoAttributeEnum('licences', this.videoLicences)
52 .map(this.restExtractor.extractDataGet)
53 .subscribe(data => {
54 Object.keys(data).forEach(licenceKey => {
55 this.videoLicences.push({
56 id: parseInt(licenceKey, 10),
57 label: data[licenceKey]
58 })
59 })
60 })
61 } 49 }
62 50
63 loadVideoLanguages () { 51 loadVideoLanguages () {
64 return this.http.get(VideoService.BASE_VIDEO_URL + 'languages') 52 return this.loadVideoAttributeEnum('languages', this.videoLanguages)
65 .map(this.restExtractor.extractDataGet)
66 .subscribe(data => {
67 Object.keys(data).forEach(languageKey => {
68 this.videoLanguages.push({
69 id: parseInt(languageKey, 10),
70 label: data[languageKey]
71 })
72 })
73 })
74 } 53 }
75 54
76 getVideo (id: string): Observable<Video> { 55 getVideo (id: string): Observable<Video> {
@@ -83,13 +62,14 @@ export class VideoService {
83 updateVideo (video: Video) { 62 updateVideo (video: Video) {
84 const language = video.language ? video.language : null 63 const language = video.language ? video.language : null
85 64
86 const body = { 65 const body: VideoUpdate = {
87 name: video.name, 66 name: video.name,
88 category: video.category, 67 category: video.category,
89 licence: video.licence, 68 licence: video.licence,
90 language, 69 language,
91 description: video.description, 70 description: video.description,
92 tags: video.tags 71 tags: video.tags,
72 nsfw: video.nsfw
93 } 73 }
94 74
95 const headers = new Headers({ 'Content-Type': 'application/json' }) 75 const headers = new Headers({ 'Content-Type': 'application/json' })
@@ -128,7 +108,7 @@ export class VideoService {
128 108
129 reportVideo (id: string, reason: string) { 109 reportVideo (id: string, reason: string) {
130 const url = VideoService.BASE_VIDEO_URL + id + '/abuse' 110 const url = VideoService.BASE_VIDEO_URL + id + '/abuse'
131 const body = { 111 const body: VideoAbuseCreate = {
132 reason 112 reason
133 } 113 }
134 114
@@ -161,7 +141,7 @@ export class VideoService {
161 141
162 private setVideoRate (id: string, rateType: VideoRateType) { 142 private setVideoRate (id: string, rateType: VideoRateType) {
163 const url = VideoService.BASE_VIDEO_URL + id + '/rate' 143 const url = VideoService.BASE_VIDEO_URL + id + '/rate'
164 const body = { 144 const body: UserVideoRateUpdate = {
165 rating: rateType 145 rating: rateType
166 } 146 }
167 147
@@ -180,4 +160,17 @@ export class VideoService {
180 160
181 return { videos, totalVideos } 161 return { videos, totalVideos }
182 } 162 }
163
164 private loadVideoAttributeEnum (attributeName: 'categories' | 'licences' | 'languages', hashToPopulate: { id: number, label: string }[]) {
165 return this.http.get(VideoService.BASE_VIDEO_URL + attributeName)
166 .map(this.restExtractor.extractDataGet)
167 .subscribe(data => {
168 Object.keys(data).forEach(dataKey => {
169 hashToPopulate.push({
170 id: parseInt(dataKey, 10),
171 label: data[dataKey]
172 })
173 })
174 })
175 }
183} 176}
diff --git a/client/src/app/videos/video-edit/video-add.component.ts b/client/src/app/videos/video-edit/video-add.component.ts
index 0653f5ac4..5d6c0e0c7 100644
--- a/client/src/app/videos/video-edit/video-add.component.ts
+++ b/client/src/app/videos/video-edit/video-add.component.ts
@@ -16,6 +16,7 @@ import {
16 VIDEO_TAGS 16 VIDEO_TAGS
17} from '../../shared' 17} from '../../shared'
18import { VideoService } from '../shared' 18import { VideoService } from '../shared'
19import { VideoCreate } from '../../../../../shared'
19 20
20@Component({ 21@Component({
21 selector: 'my-videos-add', 22 selector: 'my-videos-add',
@@ -98,23 +99,25 @@ export class VideoAddComponent extends FormReactive implements OnInit {
98 removeAfterUpload: true 99 removeAfterUpload: true
99 }) 100 })
100 101
101 this.uploader.onBuildItemForm = (item, form) => { 102 this.uploader.onBuildItemForm = (item, form: FormData) => {
102 const name = this.form.value['name'] 103 const formValue: VideoCreate = this.form.value
103 const nsfw = this.form.value['nsfw'] 104
104 const category = this.form.value['category'] 105 const name = formValue.name
105 const licence = this.form.value['licence'] 106 const nsfw = formValue.nsfw
106 const language = this.form.value['language'] 107 const category = formValue.category
107 const description = this.form.value['description'] 108 const licence = formValue.licence
108 const tags = this.form.value['tags'] 109 const language = formValue.language
110 const description = formValue.description
111 const tags = formValue.tags
109 112
110 form.append('name', name) 113 form.append('name', name)
111 form.append('category', category) 114 form.append('category', '' + category)
112 form.append('nsfw', nsfw) 115 form.append('nsfw', '' + nsfw)
113 form.append('licence', licence) 116 form.append('licence', '' + licence)
114 117
115 // Language is optional 118 // Language is optional
116 if (language) { 119 if (language) {
117 form.append('language', language) 120 form.append('language', '' + language)
118 } 121 }
119 122
120 form.append('description', description) 123 form.append('description', description)
diff --git a/scripts/watch/client.sh b/scripts/watch/client.sh
index c99ed14e6..313f66670 100755
--- a/scripts/watch/client.sh
+++ b/scripts/watch/client.sh
@@ -2,4 +2,4 @@
2 2
3cd client || exit -1 3cd client || exit -1
4 4
5npm run webpack-dev-server -- --config config/webpack.dev.js --progress --profile --colors --watch --content-base src/ --inline --hot 5npm run webpack-dev-server -- --config config/webpack.dev.js --progress --profile --colors --watch --content-base src/ --inline --hot --open
diff --git a/scripts/watch/server.sh b/scripts/watch/server.sh
index 55570138e..448f69552 100755
--- a/scripts/watch/server.sh
+++ b/scripts/watch/server.sh
@@ -1,5 +1,5 @@
1#!/usr/bin/env sh 1#!/usr/bin/env sh
2 2
3NODE_ENV=test concurrently \ 3NODE_ENV=test concurrently -k \
4 "npm run tsc -- --sourceMap && npm run nodemon -- --delay 2 --watch ./dist dist/server" \ 4 "npm run tsc -- --sourceMap && npm run nodemon -- --delay 2 --watch ./dist dist/server" \
5 "npm run tsc -- --sourceMap -w" 5 "npm run tsc -- --sourceMap -w"
diff --git a/server/controllers/api/remote/pods.ts b/server/controllers/api/remote/pods.ts
index 6319957d3..69bbd4378 100644
--- a/server/controllers/api/remote/pods.ts
+++ b/server/controllers/api/remote/pods.ts
@@ -2,6 +2,7 @@ import * as express from 'express'
2 2
3import { database as db } from '../../../initializers/database' 3import { database as db } from '../../../initializers/database'
4import { checkSignature, signatureValidator } from '../../../middlewares' 4import { checkSignature, signatureValidator } from '../../../middlewares'
5import { PodSignature } from '../../../../shared'
5 6
6const remotePodsRouter = express.Router() 7const remotePodsRouter = express.Router()
7 8
@@ -21,12 +22,11 @@ export {
21// --------------------------------------------------------------------------- 22// ---------------------------------------------------------------------------
22 23
23function removePods (req: express.Request, res: express.Response, next: express.NextFunction) { 24function removePods (req: express.Request, res: express.Response, next: express.NextFunction) {
24 const host = req.body.signature.host 25 const signature: PodSignature = req.body.signature
26 const host = signature.host
25 27
26 db.Pod.loadByHost(host) 28 db.Pod.loadByHost(host)
27 .then(pod => { 29 .then(pod => pod.destroy())
28 return pod.destroy()
29 })
30 .then(() => res.type('json').status(204).end()) 30 .then(() => res.type('json').status(204).end())
31 .catch(err => next(err)) 31 .catch(err => next(err))
32} 32}
diff --git a/server/controllers/api/remote/videos.ts b/server/controllers/api/remote/videos.ts
index fac85c3a8..96eab6d52 100644
--- a/server/controllers/api/remote/videos.ts
+++ b/server/controllers/api/remote/videos.ts
@@ -18,6 +18,17 @@ import {
18import { logger, retryTransactionWrapper } from '../../../helpers' 18import { logger, retryTransactionWrapper } from '../../../helpers'
19import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib' 19import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib'
20import { PodInstance, VideoInstance } from '../../../models' 20import { PodInstance, VideoInstance } from '../../../models'
21import {
22 RemoteVideoRequest,
23 RemoteVideoCreateData,
24 RemoteVideoUpdateData,
25 RemoteVideoRemoveData,
26 RemoteVideoReportAbuseData,
27 RemoteQaduVideoRequest,
28 RemoteQaduVideoData,
29 RemoteVideoEventRequest,
30 RemoteVideoEventData
31} from '../../../../shared'
21 32
22const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] 33const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
23 34
@@ -60,11 +71,11 @@ export {
60// --------------------------------------------------------------------------- 71// ---------------------------------------------------------------------------
61 72
62function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) { 73function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
63 const requests = req.body.data 74 const requests: RemoteVideoRequest[] = req.body.data
64 const fromPod = res.locals.secure.pod 75 const fromPod = res.locals.secure.pod
65 76
66 // We need to process in the same order to keep consistency 77 // We need to process in the same order to keep consistency
67 Promise.each(requests, (request: any) => { 78 Promise.each(requests, request => {
68 const data = request.data 79 const data = request.data
69 80
70 // Get the function we need to call in order to process the request 81 // Get the function we need to call in order to process the request
@@ -83,10 +94,10 @@ function remoteVideos (req: express.Request, res: express.Response, next: expres
83} 94}
84 95
85function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) { 96function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) {
86 const requests = req.body.data 97 const requests: RemoteQaduVideoRequest[] = req.body.data
87 const fromPod = res.locals.secure.pod 98 const fromPod = res.locals.secure.pod
88 99
89 Promise.each(requests, (request: any) => { 100 Promise.each(requests, request => {
90 const videoData = request.data 101 const videoData = request.data
91 102
92 return quickAndDirtyUpdateVideoRetryWrapper(videoData, fromPod) 103 return quickAndDirtyUpdateVideoRetryWrapper(videoData, fromPod)
@@ -97,10 +108,10 @@ function remoteVideosQadu (req: express.Request, res: express.Response, next: ex
97} 108}
98 109
99function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) { 110function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) {
100 const requests = req.body.data 111 const requests: RemoteVideoEventRequest[] = req.body.data
101 const fromPod = res.locals.secure.pod 112 const fromPod = res.locals.secure.pod
102 113
103 Promise.each(requests, (request: any) => { 114 Promise.each(requests, request => {
104 const eventData = request.data 115 const eventData = request.data
105 116
106 return processVideosEventsRetryWrapper(eventData, fromPod) 117 return processVideosEventsRetryWrapper(eventData, fromPod)
@@ -110,7 +121,7 @@ function remoteVideosEvents (req: express.Request, res: express.Response, next:
110 return res.type('json').status(204).end() 121 return res.type('json').status(204).end()
111} 122}
112 123
113function processVideosEventsRetryWrapper (eventData: any, fromPod: PodInstance) { 124function processVideosEventsRetryWrapper (eventData: RemoteVideoEventData, fromPod: PodInstance) {
114 const options = { 125 const options = {
115 arguments: [ eventData, fromPod ], 126 arguments: [ eventData, fromPod ],
116 errorMessage: 'Cannot process videos events with many retries.' 127 errorMessage: 'Cannot process videos events with many retries.'
@@ -119,7 +130,7 @@ function processVideosEventsRetryWrapper (eventData: any, fromPod: PodInstance)
119 return retryTransactionWrapper(processVideosEvents, options) 130 return retryTransactionWrapper(processVideosEvents, options)
120} 131}
121 132
122function processVideosEvents (eventData: any, fromPod: PodInstance) { 133function processVideosEvents (eventData: RemoteVideoEventData, fromPod: PodInstance) {
123 134
124 return db.sequelize.transaction(t => { 135 return db.sequelize.transaction(t => {
125 return fetchOwnedVideo(eventData.remoteId) 136 return fetchOwnedVideo(eventData.remoteId)
@@ -172,7 +183,7 @@ function processVideosEvents (eventData: any, fromPod: PodInstance) {
172 }) 183 })
173} 184}
174 185
175function quickAndDirtyUpdateVideoRetryWrapper (videoData: any, fromPod: PodInstance) { 186function quickAndDirtyUpdateVideoRetryWrapper (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
176 const options = { 187 const options = {
177 arguments: [ videoData, fromPod ], 188 arguments: [ videoData, fromPod ],
178 errorMessage: 'Cannot update quick and dirty the remote video with many retries.' 189 errorMessage: 'Cannot update quick and dirty the remote video with many retries.'
@@ -181,7 +192,7 @@ function quickAndDirtyUpdateVideoRetryWrapper (videoData: any, fromPod: PodInsta
181 return retryTransactionWrapper(quickAndDirtyUpdateVideo, options) 192 return retryTransactionWrapper(quickAndDirtyUpdateVideo, options)
182} 193}
183 194
184function quickAndDirtyUpdateVideo (videoData: any, fromPod: PodInstance) { 195function quickAndDirtyUpdateVideo (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
185 let videoName 196 let videoName
186 197
187 return db.sequelize.transaction(t => { 198 return db.sequelize.transaction(t => {
@@ -211,7 +222,7 @@ function quickAndDirtyUpdateVideo (videoData: any, fromPod: PodInstance) {
211} 222}
212 223
213// Handle retries on fail 224// Handle retries on fail
214function addRemoteVideoRetryWrapper (videoToCreateData: any, fromPod: PodInstance) { 225function addRemoteVideoRetryWrapper (videoToCreateData: RemoteVideoCreateData, fromPod: PodInstance) {
215 const options = { 226 const options = {
216 arguments: [ videoToCreateData, fromPod ], 227 arguments: [ videoToCreateData, fromPod ],
217 errorMessage: 'Cannot insert the remote video with many retries.' 228 errorMessage: 'Cannot insert the remote video with many retries.'
@@ -220,7 +231,7 @@ function addRemoteVideoRetryWrapper (videoToCreateData: any, fromPod: PodInstanc
220 return retryTransactionWrapper(addRemoteVideo, options) 231 return retryTransactionWrapper(addRemoteVideo, options)
221} 232}
222 233
223function addRemoteVideo (videoToCreateData: any, fromPod: PodInstance) { 234function addRemoteVideo (videoToCreateData: RemoteVideoCreateData, fromPod: PodInstance) {
224 logger.debug('Adding remote video "%s".', videoToCreateData.remoteId) 235 logger.debug('Adding remote video "%s".', videoToCreateData.remoteId)
225 236
226 return db.sequelize.transaction(t => { 237 return db.sequelize.transaction(t => {
@@ -293,7 +304,7 @@ function addRemoteVideo (videoToCreateData: any, fromPod: PodInstance) {
293} 304}
294 305
295// Handle retries on fail 306// Handle retries on fail
296function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: any, fromPod: PodInstance) { 307function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: RemoteVideoUpdateData, fromPod: PodInstance) {
297 const options = { 308 const options = {
298 arguments: [ videoAttributesToUpdate, fromPod ], 309 arguments: [ videoAttributesToUpdate, fromPod ],
299 errorMessage: 'Cannot update the remote video with many retries' 310 errorMessage: 'Cannot update the remote video with many retries'
@@ -302,7 +313,7 @@ function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: any, fromPod: P
302 return retryTransactionWrapper(updateRemoteVideo, options) 313 return retryTransactionWrapper(updateRemoteVideo, options)
303} 314}
304 315
305function updateRemoteVideo (videoAttributesToUpdate: any, fromPod: PodInstance) { 316function updateRemoteVideo (videoAttributesToUpdate: RemoteVideoUpdateData, fromPod: PodInstance) {
306 logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId) 317 logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId)
307 318
308 return db.sequelize.transaction(t => { 319 return db.sequelize.transaction(t => {
@@ -346,7 +357,7 @@ function updateRemoteVideo (videoAttributesToUpdate: any, fromPod: PodInstance)
346 }) 357 })
347} 358}
348 359
349function removeRemoteVideo (videoToRemoveData: any, fromPod: PodInstance) { 360function removeRemoteVideo (videoToRemoveData: RemoteVideoRemoveData, fromPod: PodInstance) {
350 // We need the instance because we have to remove some other stuffs (thumbnail etc) 361 // We need the instance because we have to remove some other stuffs (thumbnail etc)
351 return fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId) 362 return fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId)
352 .then(video => { 363 .then(video => {
@@ -358,7 +369,7 @@ function removeRemoteVideo (videoToRemoveData: any, fromPod: PodInstance) {
358 }) 369 })
359} 370}
360 371
361function reportAbuseRemoteVideo (reportData: any, fromPod: PodInstance) { 372function reportAbuseRemoteVideo (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
362 return fetchOwnedVideo(reportData.videoRemoteId) 373 return fetchOwnedVideo(reportData.videoRemoteId)
363 .then(video => { 374 .then(video => {
364 logger.debug('Reporting remote abuse for video %s.', video.id) 375 logger.debug('Reporting remote abuse for video %s.', video.id)
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index 845facd55..e79480521 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -17,7 +17,7 @@ import {
17 setUsersSort, 17 setUsersSort,
18 token 18 token
19} from '../../middlewares' 19} from '../../middlewares'
20import { UserVideoRate as FormatedUserVideoRate } from '../../../shared' 20import { UserVideoRate as FormatedUserVideoRate, UserCreate, UserUpdate } from '../../../shared'
21 21
22const usersRouter = express.Router() 22const usersRouter = express.Router()
23 23
@@ -78,10 +78,12 @@ export {
78// --------------------------------------------------------------------------- 78// ---------------------------------------------------------------------------
79 79
80function createUser (req: express.Request, res: express.Response, next: express.NextFunction) { 80function createUser (req: express.Request, res: express.Response, next: express.NextFunction) {
81 const body: UserCreate = req.body
82
81 const user = db.User.build({ 83 const user = db.User.build({
82 username: req.body.username, 84 username: body.username,
83 password: req.body.password, 85 password: body.password,
84 email: req.body.email, 86 email: body.email,
85 displayNSFW: false, 87 displayNSFW: false,
86 role: USER_ROLES.USER 88 role: USER_ROLES.USER
87 }) 89 })
@@ -132,10 +134,12 @@ function removeUser (req: express.Request, res: express.Response, next: express.
132} 134}
133 135
134function updateUser (req: express.Request, res: express.Response, next: express.NextFunction) { 136function updateUser (req: express.Request, res: express.Response, next: express.NextFunction) {
137 const body: UserUpdate = req.body
138
135 db.User.loadByUsername(res.locals.oauth.token.user.username) 139 db.User.loadByUsername(res.locals.oauth.token.user.username)
136 .then(user => { 140 .then(user => {
137 if (req.body.password) user.password = req.body.password 141 if (body.password) user.password = body.password
138 if (req.body.displayNSFW !== undefined) user.displayNSFW = req.body.displayNSFW 142 if (body.displayNSFW !== undefined) user.displayNSFW = body.displayNSFW
139 143
140 return user.save() 144 return user.save()
141 }) 145 })
diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts
index 3b1b7f58e..7d2e3bcfb 100644
--- a/server/controllers/api/videos/abuse.ts
+++ b/server/controllers/api/videos/abuse.ts
@@ -17,6 +17,7 @@ import {
17 setPagination 17 setPagination
18} from '../../../middlewares' 18} from '../../../middlewares'
19import { VideoInstance } from '../../../models' 19import { VideoInstance } from '../../../models'
20import { VideoAbuseCreate } from '../../../../shared'
20 21
21const abuseVideoRouter = express.Router() 22const abuseVideoRouter = express.Router()
22 23
@@ -63,10 +64,11 @@ function reportVideoAbuseRetryWrapper (req: express.Request, res: express.Respon
63function reportVideoAbuse (req: express.Request, res: express.Response) { 64function reportVideoAbuse (req: express.Request, res: express.Response) {
64 const videoInstance = res.locals.video 65 const videoInstance = res.locals.video
65 const reporterUsername = res.locals.oauth.token.User.username 66 const reporterUsername = res.locals.oauth.token.User.username
67 const body: VideoAbuseCreate = req.body
66 68
67 const abuse = { 69 const abuse = {
68 reporterUsername, 70 reporterUsername,
69 reason: req.body.reason, 71 reason: body.reason,
70 videoId: videoInstance.id, 72 videoId: videoInstance.id,
71 reporterPodId: null // This is our pod that reported this abuse 73 reporterPodId: null // This is our pod that reported this abuse
72 } 74 }
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 3532c753e..4ae7ea2ed 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -39,6 +39,7 @@ import {
39 renamePromise 39 renamePromise
40} from '../../../helpers' 40} from '../../../helpers'
41import { TagInstance } from '../../../models' 41import { TagInstance } from '../../../models'
42import { VideoCreate, VideoUpdate } from '../../../../shared'
42 43
43import { abuseVideoRouter } from './abuse' 44import { abuseVideoRouter } from './abuse'
44import { blacklistRouter } from './blacklist' 45import { blacklistRouter } from './blacklist'
@@ -155,7 +156,7 @@ function addVideoRetryWrapper (req: express.Request, res: express.Response, next
155} 156}
156 157
157function addVideo (req: express.Request, res: express.Response, videoFile: Express.Multer.File) { 158function addVideo (req: express.Request, res: express.Response, videoFile: Express.Multer.File) {
158 const videoInfos = req.body 159 const videoInfos: VideoCreate = req.body
159 160
160 return db.sequelize.transaction(t => { 161 return db.sequelize.transaction(t => {
161 const user = res.locals.oauth.token.User 162 const user = res.locals.oauth.token.User
@@ -257,7 +258,7 @@ function updateVideoRetryWrapper (req: express.Request, res: express.Response, n
257function updateVideo (req: express.Request, res: express.Response) { 258function updateVideo (req: express.Request, res: express.Response) {
258 const videoInstance = res.locals.video 259 const videoInstance = res.locals.video
259 const videoFieldsSave = videoInstance.toJSON() 260 const videoFieldsSave = videoInstance.toJSON()
260 const videoInfosToUpdate = req.body 261 const videoInfosToUpdate: VideoUpdate = req.body
261 262
262 return db.sequelize.transaction(t => { 263 return db.sequelize.transaction(t => {
263 let tagsPromise: Promise<TagInstance[]> 264 let tagsPromise: Promise<TagInstance[]>
diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts
index dfb5a450f..8456cbaf2 100644
--- a/server/controllers/api/videos/rate.ts
+++ b/server/controllers/api/videos/rate.ts
@@ -1,4 +1,5 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as Promise from 'bluebird'
2 3
3import { database as db } from '../../../initializers/database' 4import { database as db } from '../../../initializers/database'
4import { 5import {
@@ -18,6 +19,7 @@ import {
18 authenticate, 19 authenticate,
19 videoRateValidator 20 videoRateValidator
20} from '../../../middlewares' 21} from '../../../middlewares'
22import { UserVideoRateUpdate, VideoRateType } from '../../../../shared'
21 23
22const rateVideoRouter = express.Router() 24const rateVideoRouter = express.Router()
23 25
@@ -47,7 +49,8 @@ function rateVideoRetryWrapper (req: express.Request, res: express.Response, nex
47} 49}
48 50
49function rateVideo (req: express.Request, res: express.Response) { 51function rateVideo (req: express.Request, res: express.Response) {
50 const rateType = req.body.rating 52 const body: UserVideoRateUpdate = req.body
53 const rateType = body.rating
51 const videoInstance = res.locals.video 54 const videoInstance = res.locals.video
52 const userInstance = res.locals.oauth.token.User 55 const userInstance = res.locals.oauth.token.User
53 56
@@ -62,24 +65,34 @@ function rateVideo (req: express.Request, res: express.Response) {
62 if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++ 65 if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++
63 else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++ 66 else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
64 67
68 let promise: Promise<any>
69
65 // There was a previous rate, update it 70 // There was a previous rate, update it
66 if (previousRate) { 71 if (previousRate) {
67 // We will remove the previous rate, so we will need to remove it from the video attribute 72 // We will remove the previous rate, so we will need to remove it from the video attribute
68 if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement-- 73 if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement--
69 else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement-- 74 else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
70 75
71 previousRate.type = rateType 76 if (rateType === 'none') { // Destroy previous rate
77 promise = previousRate.destroy()
78 } else { // Update previous rate
79 previousRate.type = rateType as VideoRateType
72 80
73 return previousRate.save(options).then(() => ({ t, likesToIncrement, dislikesToIncrement })) 81 promise = previousRate.save()
74 } else { // There was not a previous rate, insert a new one 82 }
83 } else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate
75 const query = { 84 const query = {
76 userId: userInstance.id, 85 userId: userInstance.id,
77 videoId: videoInstance.id, 86 videoId: videoInstance.id,
78 type: rateType 87 type: rateType
79 } 88 }
80 89
81 return db.UserVideoRate.create(query, options).then(() => ({ likesToIncrement, dislikesToIncrement })) 90 promise = db.UserVideoRate.create(query, options)
91 } else {
92 promise = Promise.resolve()
82 } 93 }
94
95 return promise.then(() => ({ likesToIncrement, dislikesToIncrement }))
83 }) 96 })
84 .then(({ likesToIncrement, dislikesToIncrement }) => { 97 .then(({ likesToIncrement, dislikesToIncrement }) => {
85 const options = { transaction: t } 98 const options = { transaction: t }
diff --git a/server/helpers/requests.ts b/server/helpers/requests.ts
index 183f6df0d..d67d46044 100644
--- a/server/helpers/requests.ts
+++ b/server/helpers/requests.ts
@@ -8,6 +8,7 @@ import {
8 CONFIG 8 CONFIG
9} from '../initializers' 9} from '../initializers'
10import { PodInstance } from '../models' 10import { PodInstance } from '../models'
11import { PodSignature } from '../../shared'
11import { sign } from './peertube-crypto' 12import { sign } from './peertube-crypto'
12 13
13type MakeRetryRequestParams = { 14type MakeRetryRequestParams = {
@@ -37,9 +38,18 @@ type MakeSecureRequestParams = {
37} 38}
38function makeSecureRequest (params: MakeSecureRequestParams) { 39function makeSecureRequest (params: MakeSecureRequestParams) {
39 return new Promise<{ response: request.RequestResponse, body: any }>((res, rej) => { 40 return new Promise<{ response: request.RequestResponse, body: any }>((res, rej) => {
40 const requestParams = { 41 const requestParams: {
42 url: string,
43 json: {
44 signature: PodSignature,
45 data: any
46 }
47 } = {
41 url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path, 48 url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path,
42 json: {} 49 json: {
50 signature: null,
51 data: null
52 }
43 } 53 }
44 54
45 if (params.method !== 'POST') { 55 if (params.method !== 'POST') {
@@ -58,14 +68,14 @@ function makeSecureRequest (params: MakeSecureRequestParams) {
58 } 68 }
59 69
60 sign(dataToSign).then(signature => { 70 sign(dataToSign).then(signature => {
61 requestParams.json['signature'] = { 71 requestParams.json.signature = {
62 host, // Which host we pretend to be 72 host, // Which host we pretend to be
63 signature 73 signature
64 } 74 }
65 75
66 // If there are data informations 76 // If there are data informations
67 if (params.data) { 77 if (params.data) {
68 requestParams.json['data'] = params.data 78 requestParams.json.data = params.data
69 } 79 }
70 80
71 request.post(requestParams, (err, response, body) => err ? rej(err) : res({ response, body })) 81 request.post(requestParams, (err, response, body) => err ? rej(err) : res({ response, body }))
diff --git a/server/lib/friends.ts b/server/lib/friends.ts
index 3487addbe..4d56e9eb2 100644
--- a/server/lib/friends.ts
+++ b/server/lib/friends.ts
@@ -34,7 +34,11 @@ import {
34import { 34import {
35 RequestEndpoint, 35 RequestEndpoint,
36 RequestVideoEventType, 36 RequestVideoEventType,
37 RequestVideoQaduType 37 RequestVideoQaduType,
38 RemoteVideoCreateData,
39 RemoteVideoUpdateData,
40 RemoteVideoRemoveData,
41 RemoteVideoReportAbuseData
38} from '../../shared' 42} from '../../shared'
39 43
40type QaduParam = { videoId: string, type: RequestVideoQaduType } 44type QaduParam = { videoId: string, type: RequestVideoQaduType }
@@ -52,7 +56,7 @@ function activateSchedulers () {
52 requestVideoEventScheduler.activate() 56 requestVideoEventScheduler.activate()
53} 57}
54 58
55function addVideoToFriends (videoData: Object, transaction: Sequelize.Transaction) { 59function addVideoToFriends (videoData: RemoteVideoCreateData, transaction: Sequelize.Transaction) {
56 const options = { 60 const options = {
57 type: ENDPOINT_ACTIONS.ADD, 61 type: ENDPOINT_ACTIONS.ADD,
58 endpoint: REQUEST_ENDPOINTS.VIDEOS, 62 endpoint: REQUEST_ENDPOINTS.VIDEOS,
@@ -62,7 +66,7 @@ function addVideoToFriends (videoData: Object, transaction: Sequelize.Transactio
62 return createRequest(options) 66 return createRequest(options)
63} 67}
64 68
65function updateVideoToFriends (videoData: Object, transaction: Sequelize.Transaction) { 69function updateVideoToFriends (videoData: RemoteVideoUpdateData, transaction: Sequelize.Transaction) {
66 const options = { 70 const options = {
67 type: ENDPOINT_ACTIONS.UPDATE, 71 type: ENDPOINT_ACTIONS.UPDATE,
68 endpoint: REQUEST_ENDPOINTS.VIDEOS, 72 endpoint: REQUEST_ENDPOINTS.VIDEOS,
@@ -72,7 +76,7 @@ function updateVideoToFriends (videoData: Object, transaction: Sequelize.Transac
72 return createRequest(options) 76 return createRequest(options)
73} 77}
74 78
75function removeVideoToFriends (videoParams: Object) { 79function removeVideoToFriends (videoParams: RemoteVideoRemoveData) {
76 const options = { 80 const options = {
77 type: ENDPOINT_ACTIONS.REMOVE, 81 type: ENDPOINT_ACTIONS.REMOVE,
78 endpoint: REQUEST_ENDPOINTS.VIDEOS, 82 endpoint: REQUEST_ENDPOINTS.VIDEOS,
@@ -82,7 +86,7 @@ function removeVideoToFriends (videoParams: Object) {
82 return createRequest(options) 86 return createRequest(options)
83} 87}
84 88
85function reportAbuseVideoToFriend (reportData: Object, video: VideoInstance, transaction: Sequelize.Transaction) { 89function reportAbuseVideoToFriend (reportData: RemoteVideoReportAbuseData, video: VideoInstance, transaction: Sequelize.Transaction) {
86 const options = { 90 const options = {
87 type: ENDPOINT_ACTIONS.REPORT_ABUSE, 91 type: ENDPOINT_ACTIONS.REPORT_ABUSE,
88 endpoint: REQUEST_ENDPOINTS.VIDEOS, 92 endpoint: REQUEST_ENDPOINTS.VIDEOS,
diff --git a/server/lib/request/abstract-request-scheduler.ts b/server/lib/request/abstract-request-scheduler.ts
index 0a9ff65d5..ce4e2ffd2 100644
--- a/server/lib/request/abstract-request-scheduler.ts
+++ b/server/lib/request/abstract-request-scheduler.ts
@@ -10,6 +10,15 @@ import {
10 REQUESTS_INTERVAL 10 REQUESTS_INTERVAL
11} from '../../initializers' 11} from '../../initializers'
12 12
13interface RequestsObjects<U> {
14 [ id: string ]: {
15 toPod: PodInstance
16 endpoint: string
17 ids: number[] // ids
18 datas: U[]
19 }
20}
21
13abstract class AbstractRequestScheduler <T> { 22abstract class AbstractRequestScheduler <T> {
14 requestInterval: number 23 requestInterval: number
15 limitPods: number 24 limitPods: number
@@ -27,7 +36,7 @@ abstract class AbstractRequestScheduler <T> {
27 36
28 abstract getRequestModel (): AbstractRequestClass<T> 37 abstract getRequestModel (): AbstractRequestClass<T>
29 abstract getRequestToPodModel (): AbstractRequestToPodClass 38 abstract getRequestToPodModel (): AbstractRequestToPodClass
30 abstract buildRequestObjects (requestsGrouped: T): {} 39 abstract buildRequestsObjects (requestsGrouped: T): RequestsObjects<any>
31 40
32 activate () { 41 activate () {
33 logger.info('Requests scheduler activated.') 42 logger.info('Requests scheduler activated.')
@@ -67,7 +76,7 @@ abstract class AbstractRequestScheduler <T> {
67 // --------------------------------------------------------------------------- 76 // ---------------------------------------------------------------------------
68 77
69 // Make a requests to friends of a certain type 78 // Make a requests to friends of a certain type
70 protected makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: Object) { 79 protected makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: any) {
71 const params = { 80 const params = {
72 toPod: toPod, 81 toPod: toPod,
73 method: 'POST' as 'POST', 82 method: 'POST' as 'POST',
@@ -95,7 +104,7 @@ abstract class AbstractRequestScheduler <T> {
95 return this.getRequestModel().listWithLimitAndRandom(this.limitPods, this.limitPerPod) 104 return this.getRequestModel().listWithLimitAndRandom(this.limitPods, this.limitPerPod)
96 .then((requestsGrouped: T) => { 105 .then((requestsGrouped: T) => {
97 // We want to group requests by destinations pod and endpoint 106 // We want to group requests by destinations pod and endpoint
98 const requestsToMake = this.buildRequestObjects(requestsGrouped) 107 const requestsToMake = this.buildRequestsObjects(requestsGrouped)
99 108
100 // If there are no requests, abort 109 // If there are no requests, abort
101 if (isEmpty(requestsToMake) === true) { 110 if (isEmpty(requestsToMake) === true) {
@@ -105,8 +114,8 @@ abstract class AbstractRequestScheduler <T> {
105 114
106 logger.info('Making "%s" to friends.', this.description) 115 logger.info('Making "%s" to friends.', this.description)
107 116
108 const goodPods = [] 117 const goodPods: number[] = []
109 const badPods = [] 118 const badPods: number[] = []
110 119
111 return Promise.map(Object.keys(requestsToMake), hashKey => { 120 return Promise.map(Object.keys(requestsToMake), hashKey => {
112 const requestToMake = requestsToMake[hashKey] 121 const requestToMake = requestsToMake[hashKey]
@@ -149,5 +158,6 @@ abstract class AbstractRequestScheduler <T> {
149// --------------------------------------------------------------------------- 158// ---------------------------------------------------------------------------
150 159
151export { 160export {
152 AbstractRequestScheduler 161 AbstractRequestScheduler,
162 RequestsObjects
153} 163}
diff --git a/server/lib/request/request-scheduler.ts b/server/lib/request/request-scheduler.ts
index 3945ace20..696875dcf 100644
--- a/server/lib/request/request-scheduler.ts
+++ b/server/lib/request/request-scheduler.ts
@@ -1,11 +1,11 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3import { database as db } from '../../initializers/database' 3import { database as db } from '../../initializers/database'
4import { AbstractRequestScheduler } from './abstract-request-scheduler' 4import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
5import { logger } from '../../helpers' 5import { logger } from '../../helpers'
6import { REQUESTS_LIMIT_PODS, REQUESTS_LIMIT_PER_POD } from '../../initializers' 6import { REQUESTS_LIMIT_PODS, REQUESTS_LIMIT_PER_POD } from '../../initializers'
7import { RequestsGrouped } from '../../models' 7import { RequestsGrouped } from '../../models'
8import { RequestEndpoint } from '../../../shared' 8import { RequestEndpoint, RemoteVideoRequest } from '../../../shared'
9 9
10export type RequestSchedulerOptions = { 10export type RequestSchedulerOptions = {
11 type: string 11 type: string
@@ -34,8 +34,8 @@ class RequestScheduler extends AbstractRequestScheduler<RequestsGrouped> {
34 return db.RequestToPod 34 return db.RequestToPod
35 } 35 }
36 36
37 buildRequestObjects (requestsGrouped: RequestsGrouped) { 37 buildRequestsObjects (requestsGrouped: RequestsGrouped) {
38 const requestsToMakeGrouped = {} 38 const requestsToMakeGrouped: RequestsObjects<RemoteVideoRequest> = {}
39 39
40 Object.keys(requestsGrouped).forEach(toPodId => { 40 Object.keys(requestsGrouped).forEach(toPodId => {
41 requestsGrouped[toPodId].forEach(data => { 41 requestsGrouped[toPodId].forEach(data => {
diff --git a/server/lib/request/request-video-event-scheduler.ts b/server/lib/request/request-video-event-scheduler.ts
index d4d714c02..8a008c51b 100644
--- a/server/lib/request/request-video-event-scheduler.ts
+++ b/server/lib/request/request-video-event-scheduler.ts
@@ -1,14 +1,14 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3import { database as db } from '../../initializers/database' 3import { database as db } from '../../initializers/database'
4import { AbstractRequestScheduler } from './abstract-request-scheduler' 4import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
5import { 5import {
6 REQUESTS_VIDEO_EVENT_LIMIT_PODS, 6 REQUESTS_VIDEO_EVENT_LIMIT_PODS,
7 REQUESTS_VIDEO_EVENT_LIMIT_PER_POD, 7 REQUESTS_VIDEO_EVENT_LIMIT_PER_POD,
8 REQUEST_VIDEO_EVENT_ENDPOINT 8 REQUEST_VIDEO_EVENT_ENDPOINT
9} from '../../initializers' 9} from '../../initializers'
10import { RequestsVideoEventGrouped } from '../../models' 10import { RequestsVideoEventGrouped } from '../../models'
11import { RequestVideoEventType } from '../../../shared' 11import { RequestVideoEventType, RemoteVideoEventRequest, RemoteVideoEventType } from '../../../shared'
12 12
13export type RequestVideoEventSchedulerOptions = { 13export type RequestVideoEventSchedulerOptions = {
14 type: RequestVideoEventType 14 type: RequestVideoEventType
@@ -36,8 +36,8 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
36 return db.RequestVideoEvent 36 return db.RequestVideoEvent
37 } 37 }
38 38
39 buildRequestObjects (eventRequests: RequestsVideoEventGrouped) { 39 buildRequestsObjects (eventRequests: RequestsVideoEventGrouped) {
40 const requestsToMakeGrouped = {} 40 const requestsToMakeGrouped: RequestsObjects<RemoteVideoEventRequest> = {}
41 41
42 /* Example: 42 /* Example:
43 { 43 {
@@ -47,7 +47,15 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
47 } 47 }
48 } 48 }
49 */ 49 */
50 const eventsPerVideoPerPod = {} 50 const eventsPerVideoPerPod: {
51 [ podId: string ]: {
52 [ videoRemoteId: string ]: {
53 views?: number
54 likes?: number
55 dislikes?: number
56 }
57 }
58 } = {}
51 59
52 // We group video events per video and per pod 60 // We group video events per video and per pod
53 // We add the counts of the same event types 61 // We add the counts of the same event types
@@ -87,8 +95,8 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
87 requestsToMakeGrouped[toPodId].datas.push({ 95 requestsToMakeGrouped[toPodId].datas.push({
88 data: { 96 data: {
89 remoteId, 97 remoteId,
90 eventType, 98 eventType: eventType as RemoteVideoEventType,
91 count: eventsForVideo[eventType] 99 count: +eventsForVideo[eventType]
92 } 100 }
93 }) 101 })
94 }) 102 })
diff --git a/server/lib/request/request-video-qadu-scheduler.ts b/server/lib/request/request-video-qadu-scheduler.ts
index 5ec7de9c2..988165170 100644
--- a/server/lib/request/request-video-qadu-scheduler.ts
+++ b/server/lib/request/request-video-qadu-scheduler.ts
@@ -1,7 +1,7 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2 2
3import { database as db } from '../../initializers/database' 3import { database as db } from '../../initializers/database'
4import { AbstractRequestScheduler } from './abstract-request-scheduler' 4import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
5import { logger } from '../../helpers' 5import { logger } from '../../helpers'
6import { 6import {
7 REQUESTS_VIDEO_QADU_LIMIT_PODS, 7 REQUESTS_VIDEO_QADU_LIMIT_PODS,
@@ -9,8 +9,27 @@ import {
9 REQUEST_VIDEO_QADU_ENDPOINT, 9 REQUEST_VIDEO_QADU_ENDPOINT,
10 REQUEST_VIDEO_QADU_TYPES 10 REQUEST_VIDEO_QADU_TYPES
11} from '../../initializers' 11} from '../../initializers'
12import { RequestsVideoQaduGrouped } from '../../models' 12import { RequestsVideoQaduGrouped, PodInstance } from '../../models'
13import { RequestVideoQaduType } from '../../../shared' 13import { RemoteQaduVideoRequest, RequestVideoQaduType } from '../../../shared'
14
15// We create a custom interface because we need "videos" attribute for our computations
16interface RequestsObjectsCustom<U> extends RequestsObjects<U> {
17 [ id: string ]: {
18 toPod: PodInstance
19 endpoint: string
20 ids: number[] // ids
21 datas: U[]
22
23 videos: {
24 [ id: string ]: {
25 remoteId: string
26 likes?: number
27 dislikes?: number
28 views?: number
29 }
30 }
31 }
32}
14 33
15export type RequestVideoQaduSchedulerOptions = { 34export type RequestVideoQaduSchedulerOptions = {
16 type: RequestVideoQaduType 35 type: RequestVideoQaduType
@@ -37,8 +56,8 @@ class RequestVideoQaduScheduler extends AbstractRequestScheduler<RequestsVideoQa
37 return db.RequestVideoQadu 56 return db.RequestVideoQadu
38 } 57 }
39 58
40 buildRequestObjects (requests: RequestsVideoQaduGrouped) { 59 buildRequestsObjects (requests: RequestsVideoQaduGrouped) {
41 const requestsToMakeGrouped = {} 60 const requestsToMakeGrouped: RequestsObjectsCustom<RemoteQaduVideoRequest> = {}
42 61
43 Object.keys(requests).forEach(toPodId => { 62 Object.keys(requests).forEach(toPodId => {
44 requests[toPodId].forEach(data => { 63 requests[toPodId].forEach(data => {
@@ -59,7 +78,7 @@ class RequestVideoQaduScheduler extends AbstractRequestScheduler<RequestsVideoQa
59 78
60 // Maybe another attribute was filled for this video 79 // Maybe another attribute was filled for this video
61 let videoData = requestsToMakeGrouped[hashKey].videos[video.id] 80 let videoData = requestsToMakeGrouped[hashKey].videos[video.id]
62 if (!videoData) videoData = {} 81 if (!videoData) videoData = { remoteId: null }
63 82
64 switch (request.type) { 83 switch (request.type) {
65 case REQUEST_VIDEO_QADU_TYPES.LIKES: 84 case REQUEST_VIDEO_QADU_TYPES.LIKES:
diff --git a/server/middlewares/secure.ts b/server/middlewares/secure.ts
index f58bea734..f7424c9c3 100644
--- a/server/middlewares/secure.ts
+++ b/server/middlewares/secure.ts
@@ -6,9 +6,12 @@ import {
6 logger, 6 logger,
7 checkSignature as peertubeCryptoCheckSignature 7 checkSignature as peertubeCryptoCheckSignature
8} from '../helpers' 8} from '../helpers'
9import { PodSignature } from '../../shared'
9 10
10function checkSignature (req: express.Request, res: express.Response, next: express.NextFunction) { 11function checkSignature (req: express.Request, res: express.Response, next: express.NextFunction) {
11 const host = req.body.signature.host 12 const signatureObject: PodSignature = req.body.signature
13 const host = signatureObject.host
14
12 db.Pod.loadByHost(host) 15 db.Pod.loadByHost(host)
13 .then(pod => { 16 .then(pod => {
14 if (pod === null) { 17 if (pod === null) {
@@ -27,7 +30,7 @@ function checkSignature (req: express.Request, res: express.Response, next: expr
27 signatureShouldBe = host 30 signatureShouldBe = host
28 } 31 }
29 32
30 const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature) 33 const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, signatureObject.signature)
31 34
32 if (signatureOk === true) { 35 if (signatureOk === true) {
33 res.locals.secure = { 36 res.locals.secure = {
@@ -37,11 +40,11 @@ function checkSignature (req: express.Request, res: express.Response, next: expr
37 return next() 40 return next()
38 } 41 }
39 42
40 logger.error('Signature is not okay in body for %s.', req.body.signature.host) 43 logger.error('Signature is not okay in body for %s.', signatureObject.host)
41 return res.sendStatus(403) 44 return res.sendStatus(403)
42 }) 45 })
43 .catch(err => { 46 .catch(err => {
44 logger.error('Cannot get signed host in body.', { error: err.stack, signature: req.body.signature.signature }) 47 logger.error('Cannot get signed host in body.', { error: err.stack, signature: signatureObject.signature })
45 return res.sendStatus(500) 48 return res.sendStatus(500)
46 }) 49 })
47} 50}
diff --git a/server/models/pod/pod-interface.ts b/server/models/pod/pod-interface.ts
index f6963d47e..340d4f1a7 100644
--- a/server/models/pod/pod-interface.ts
+++ b/server/models/pod/pod-interface.ts
@@ -2,7 +2,7 @@ import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird' 2import * as Promise from 'bluebird'
3 3
4// Don't use barrel, import just what we need 4// Don't use barrel, import just what we need
5import { Pod as FormatedPod } from '../../../shared/models/pod.model' 5import { Pod as FormatedPod } from '../../../shared/models/pods/pod.model'
6 6
7export namespace PodMethods { 7export namespace PodMethods {
8 export type ToFormatedJSON = (this: PodInstance) => FormatedPod 8 export type ToFormatedJSON = (this: PodInstance) => FormatedPod
diff --git a/server/models/user/user-interface.ts b/server/models/user/user-interface.ts
index f743945f8..9bd3d2ebb 100644
--- a/server/models/user/user-interface.ts
+++ b/server/models/user/user-interface.ts
@@ -2,7 +2,8 @@ import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird' 2import * as Promise from 'bluebird'
3 3
4// Don't use barrel, import just what we need 4// Don't use barrel, import just what we need
5import { UserRole, User as FormatedUser } from '../../../shared/models/user.model' 5import { User as FormatedUser } from '../../../shared/models/users/user.model'
6import { UserRole } from '../../../shared/models/users/user-role.type'
6import { ResultList } from '../../../shared/models/result-list.model' 7import { ResultList } from '../../../shared/models/result-list.model'
7 8
8export namespace UserMethods { 9export namespace UserMethods {
diff --git a/server/models/user/user-video-rate-interface.ts b/server/models/user/user-video-rate-interface.ts
index e0b65a13d..f501f08b7 100644
--- a/server/models/user/user-video-rate-interface.ts
+++ b/server/models/user/user-video-rate-interface.ts
@@ -1,7 +1,7 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird' 2import * as Promise from 'bluebird'
3 3
4import { VideoRateType } from '../../../shared/models/user-video-rate.model' 4import { VideoRateType } from '../../../shared/models/videos/video-rate.type'
5 5
6export namespace UserVideoRateMethods { 6export namespace UserVideoRateMethods {
7 export type Load = (userId: number, videoId: string, transaction: Sequelize.Transaction) => Promise<UserVideoRateInstance> 7 export type Load = (userId: number, videoId: string, transaction: Sequelize.Transaction) => Promise<UserVideoRateInstance>
diff --git a/server/models/video/video-abuse-interface.ts b/server/models/video/video-abuse-interface.ts
index 75647fe0e..d6724d36f 100644
--- a/server/models/video/video-abuse-interface.ts
+++ b/server/models/video/video-abuse-interface.ts
@@ -5,7 +5,7 @@ import { PodInstance } from '../pod'
5import { ResultList } from '../../../shared' 5import { ResultList } from '../../../shared'
6 6
7// Don't use barrel, import just what we need 7// Don't use barrel, import just what we need
8import { VideoAbuse as FormatedVideoAbuse } from '../../../shared/models/video-abuse.model' 8import { VideoAbuse as FormatedVideoAbuse } from '../../../shared/models/videos/video-abuse.model'
9 9
10export namespace VideoAbuseMethods { 10export namespace VideoAbuseMethods {
11 export type ToFormatedJSON = (this: VideoAbuseInstance) => FormatedVideoAbuse 11 export type ToFormatedJSON = (this: VideoAbuseInstance) => FormatedVideoAbuse
diff --git a/server/models/video/video-blacklist-interface.ts b/server/models/video/video-blacklist-interface.ts
index 5ca423801..47a510231 100644
--- a/server/models/video/video-blacklist-interface.ts
+++ b/server/models/video/video-blacklist-interface.ts
@@ -4,7 +4,7 @@ import * as Promise from 'bluebird'
4import { ResultList } from '../../../shared' 4import { ResultList } from '../../../shared'
5 5
6// Don't use barrel, import just what we need 6// Don't use barrel, import just what we need
7import { BlacklistedVideo as FormatedBlacklistedVideo } from '../../../shared/models/video-blacklist.model' 7import { BlacklistedVideo as FormatedBlacklistedVideo } from '../../../shared/models/videos/video-blacklist.model'
8 8
9export namespace BlacklistedVideoMethods { 9export namespace BlacklistedVideoMethods {
10 export type ToFormatedJSON = (this: BlacklistedVideoInstance) => FormatedBlacklistedVideo 10 export type ToFormatedJSON = (this: BlacklistedVideoInstance) => FormatedBlacklistedVideo
diff --git a/server/models/video/video-interface.ts b/server/models/video/video-interface.ts
index c3e3365d5..b836d6da6 100644
--- a/server/models/video/video-interface.ts
+++ b/server/models/video/video-interface.ts
@@ -5,7 +5,7 @@ import { AuthorInstance } from './author-interface'
5import { TagAttributes, TagInstance } from './tag-interface' 5import { TagAttributes, TagInstance } from './tag-interface'
6 6
7// Don't use barrel, import just what we need 7// Don't use barrel, import just what we need
8import { Video as FormatedVideo } from '../../../shared/models/video.model' 8import { Video as FormatedVideo } from '../../../shared/models/videos/video.model'
9import { ResultList } from '../../../shared/models/result-list.model' 9import { ResultList } from '../../../shared/models/result-list.model'
10 10
11export type FormatedAddRemoteVideo = { 11export type FormatedAddRemoteVideo = {
diff --git a/shared/models/index.ts b/shared/models/index.ts
index cd885af89..02665a3e6 100644
--- a/shared/models/index.ts
+++ b/shared/models/index.ts
@@ -1,11 +1,8 @@
1export * from './pods'
2export * from './users'
3export * from './videos'
1export * from './job.model' 4export * from './job.model'
2export * from './oauth-client-local.model' 5export * from './oauth-client-local.model'
3export * from './pod.model'
4export * from './result-list.model' 6export * from './result-list.model'
5export * from './request-scheduler.model' 7export * from './request-scheduler.model'
6export * from './user-video-rate.model'
7export * from './user.model'
8export * from './video-abuse.model'
9export * from './video-blacklist.model'
10export * from './video.model'
11export * from './server-config.model' 8export * from './server-config.model'
diff --git a/shared/models/pods/index.ts b/shared/models/pods/index.ts
new file mode 100644
index 000000000..f59d01540
--- /dev/null
+++ b/shared/models/pods/index.ts
@@ -0,0 +1,3 @@
1export * from './pod-signature.model'
2export * from './pod.model'
3export * from './remote-video'
diff --git a/shared/models/pods/pod-signature.model.ts b/shared/models/pods/pod-signature.model.ts
new file mode 100644
index 000000000..b7988a40c
--- /dev/null
+++ b/shared/models/pods/pod-signature.model.ts
@@ -0,0 +1,4 @@
1export interface PodSignature {
2 host: string
3 signature: string
4}
diff --git a/shared/models/pod.model.ts b/shared/models/pods/pod.model.ts
index d25421936..d25421936 100644
--- a/shared/models/pod.model.ts
+++ b/shared/models/pods/pod.model.ts
diff --git a/shared/models/pods/remote-video/index.ts b/shared/models/pods/remote-video/index.ts
new file mode 100644
index 000000000..c88116849
--- /dev/null
+++ b/shared/models/pods/remote-video/index.ts
@@ -0,0 +1,7 @@
1export * from './remote-qadu-video-request.model'
2export * from './remote-video-event-request.model'
3export * from './remote-video-request.model'
4export * from './remote-video-create-request.model'
5export * from './remote-video-update-request.model'
6export * from './remote-video-remove-request.model'
7export * from './remote-video-report-abuse-request.model'
diff --git a/shared/models/pods/remote-video/remote-qadu-video-request.model.ts b/shared/models/pods/remote-video/remote-qadu-video-request.model.ts
new file mode 100644
index 000000000..0f84e3f13
--- /dev/null
+++ b/shared/models/pods/remote-video/remote-qadu-video-request.model.ts
@@ -0,0 +1,10 @@
1export interface RemoteQaduVideoData {
2 remoteId: string
3 views?: number
4 likes?: number
5 dislikes?: number
6}
7
8export interface RemoteQaduVideoRequest {
9 data: RemoteQaduVideoData
10}
diff --git a/shared/models/pods/remote-video/remote-video-create-request.model.ts b/shared/models/pods/remote-video/remote-video-create-request.model.ts
new file mode 100644
index 000000000..6babb0083
--- /dev/null
+++ b/shared/models/pods/remote-video/remote-video-create-request.model.ts
@@ -0,0 +1,27 @@
1import { RemoteVideoRequest } from './remote-video-request.model'
2
3export interface RemoteVideoCreateData {
4 remoteId: string
5 author: string
6 tags: string[]
7 name: string
8 extname: string
9 infoHash: string
10 category: number
11 licence: number
12 language: number
13 nsfw: boolean
14 description: string
15 duration: number
16 createdAt: Date
17 updatedAt: Date
18 views: number
19 likes: number
20 dislikes: number
21 thumbnailData: string
22}
23
24export interface RemoteVideoCreateRequest extends RemoteVideoRequest {
25 type: 'add'
26 data: RemoteVideoCreateData
27}
diff --git a/shared/models/pods/remote-video/remote-video-event-request.model.ts b/shared/models/pods/remote-video/remote-video-event-request.model.ts
new file mode 100644
index 000000000..84df1ca2f
--- /dev/null
+++ b/shared/models/pods/remote-video/remote-video-event-request.model.ts
@@ -0,0 +1,11 @@
1export type RemoteVideoEventType = 'views' | 'likes' | 'dislikes'
2
3export interface RemoteVideoEventData {
4 remoteId: string
5 eventType: RemoteVideoEventType
6 count: number
7}
8
9export interface RemoteVideoEventRequest {
10 data: RemoteVideoEventData
11}
diff --git a/shared/models/pods/remote-video/remote-video-remove-request.model.ts b/shared/models/pods/remote-video/remote-video-remove-request.model.ts
new file mode 100644
index 000000000..95ee38661
--- /dev/null
+++ b/shared/models/pods/remote-video/remote-video-remove-request.model.ts
@@ -0,0 +1,10 @@
1import { RemoteVideoRequest } from './remote-video-request.model'
2
3export interface RemoteVideoRemoveData {
4 remoteId: string
5}
6
7export interface RemoteVideoRemoveRequest extends RemoteVideoRequest {
8 type: 'remove'
9 data: RemoteVideoRemoveData
10}
diff --git a/shared/models/pods/remote-video/remote-video-report-abuse-request.model.ts b/shared/models/pods/remote-video/remote-video-report-abuse-request.model.ts
new file mode 100644
index 000000000..9059c92e0
--- /dev/null
+++ b/shared/models/pods/remote-video/remote-video-report-abuse-request.model.ts
@@ -0,0 +1,12 @@
1import { RemoteVideoRequest } from './remote-video-request.model'
2
3export interface RemoteVideoReportAbuseData {
4 videoRemoteId: string
5 reporterUsername: string
6 reportReason: string
7}
8
9export interface RemoteVideoReportAbuseRequest extends RemoteVideoRequest {
10 type: 'report-abuse'
11 data: RemoteVideoReportAbuseData
12}
diff --git a/shared/models/pods/remote-video/remote-video-request.model.ts b/shared/models/pods/remote-video/remote-video-request.model.ts
new file mode 100644
index 000000000..e5052a23d
--- /dev/null
+++ b/shared/models/pods/remote-video/remote-video-request.model.ts
@@ -0,0 +1,4 @@
1export interface RemoteVideoRequest {
2 type: 'add' | 'update' | 'remove' | 'report-abuse'
3 data: any
4}
diff --git a/shared/models/pods/remote-video/remote-video-update-request.model.ts b/shared/models/pods/remote-video/remote-video-update-request.model.ts
new file mode 100644
index 000000000..67ddbc1e4
--- /dev/null
+++ b/shared/models/pods/remote-video/remote-video-update-request.model.ts
@@ -0,0 +1,23 @@
1export interface RemoteVideoUpdateData {
2 remoteId: string
3 tags: string[]
4 name: string
5 extname: string
6 infoHash: string
7 category: number
8 licence: number
9 language: number
10 nsfw: boolean
11 description: string
12 duration: number
13 createdAt: Date
14 updatedAt: Date
15 views: number
16 likes: number
17 dislikes: number
18}
19
20export interface RemoteVideoUpdateRequest {
21 type: 'update'
22 data: RemoteVideoUpdateData
23}
diff --git a/shared/models/user-video-rate.model.ts b/shared/models/user-video-rate.model.ts
deleted file mode 100644
index b770f4073..000000000
--- a/shared/models/user-video-rate.model.ts
+++ /dev/null
@@ -1,7 +0,0 @@
1export type VideoRateType = 'like' | 'dislike'
2export type UserVideoRateType = 'like' | 'dislike' | 'none'
3
4export interface UserVideoRate {
5 videoId: string
6 rating: UserVideoRateType
7}
diff --git a/shared/models/users/index.ts b/shared/models/users/index.ts
new file mode 100644
index 000000000..414aaab08
--- /dev/null
+++ b/shared/models/users/index.ts
@@ -0,0 +1,4 @@
1export * from './user.model'
2export * from './user-create.model'
3export * from './user-update.model'
4export * from './user-role.type'
diff --git a/shared/models/users/user-create.model.ts b/shared/models/users/user-create.model.ts
new file mode 100644
index 000000000..2cddcdcb0
--- /dev/null
+++ b/shared/models/users/user-create.model.ts
@@ -0,0 +1,5 @@
1export interface UserCreate {
2 username: string
3 password: string
4 email: string
5}
diff --git a/shared/models/users/user-role.type.ts b/shared/models/users/user-role.type.ts
new file mode 100644
index 000000000..b38c4c8c3
--- /dev/null
+++ b/shared/models/users/user-role.type.ts
@@ -0,0 +1 @@
export type UserRole = 'admin' | 'user'
diff --git a/shared/models/users/user-update.model.ts b/shared/models/users/user-update.model.ts
new file mode 100644
index 000000000..8b9abfb15
--- /dev/null
+++ b/shared/models/users/user-update.model.ts
@@ -0,0 +1,4 @@
1export interface UserUpdate {
2 displayNSFW?: boolean
3 password?: string
4}
diff --git a/shared/models/user.model.ts b/shared/models/users/user.model.ts
index 92dc73ec2..5c48a17b2 100644
--- a/shared/models/user.model.ts
+++ b/shared/models/users/user.model.ts
@@ -1,4 +1,4 @@
1export type UserRole = 'admin' | 'user' 1import { UserRole } from './user-role.type'
2 2
3export interface User { 3export interface User {
4 id: number 4 id: number
diff --git a/shared/models/videos/index.ts b/shared/models/videos/index.ts
new file mode 100644
index 000000000..64d1676c5
--- /dev/null
+++ b/shared/models/videos/index.ts
@@ -0,0 +1,10 @@
1export * from './user-video-rate-update.model'
2export * from './user-video-rate.model'
3export * from './user-video-rate.type'
4export * from './video-abuse-create.model'
5export * from './video-abuse.model'
6export * from './video-blacklist.model'
7export * from './video-create.model'
8export * from './video-rate.type'
9export * from './video-update.model'
10export * from './video.model'
diff --git a/shared/models/videos/user-video-rate-update.model.ts b/shared/models/videos/user-video-rate-update.model.ts
new file mode 100644
index 000000000..85e89271a
--- /dev/null
+++ b/shared/models/videos/user-video-rate-update.model.ts
@@ -0,0 +1,5 @@
1import { UserVideoRateType } from './user-video-rate.type'
2
3export interface UserVideoRateUpdate {
4 rating: UserVideoRateType
5}
diff --git a/shared/models/videos/user-video-rate.model.ts b/shared/models/videos/user-video-rate.model.ts
new file mode 100644
index 000000000..4b9c574d8
--- /dev/null
+++ b/shared/models/videos/user-video-rate.model.ts
@@ -0,0 +1,6 @@
1import { UserVideoRateType } from './user-video-rate.type'
2
3export interface UserVideoRate {
4 videoId: string
5 rating: UserVideoRateType
6}
diff --git a/shared/models/videos/user-video-rate.type.ts b/shared/models/videos/user-video-rate.type.ts
new file mode 100644
index 000000000..a4d9c7e39
--- /dev/null
+++ b/shared/models/videos/user-video-rate.type.ts
@@ -0,0 +1 @@
export type UserVideoRateType = 'like' | 'dislike' | 'none'
diff --git a/shared/models/videos/video-abuse-create.model.ts b/shared/models/videos/video-abuse-create.model.ts
new file mode 100644
index 000000000..db6458275
--- /dev/null
+++ b/shared/models/videos/video-abuse-create.model.ts
@@ -0,0 +1,3 @@
1export interface VideoAbuseCreate {
2 reason: string
3}
diff --git a/shared/models/video-abuse.model.ts b/shared/models/videos/video-abuse.model.ts
index 72e32cbc7..72e32cbc7 100644
--- a/shared/models/video-abuse.model.ts
+++ b/shared/models/videos/video-abuse.model.ts
diff --git a/shared/models/video-blacklist.model.ts b/shared/models/videos/video-blacklist.model.ts
index f894bb065..f894bb065 100644
--- a/shared/models/video-blacklist.model.ts
+++ b/shared/models/videos/video-blacklist.model.ts
diff --git a/shared/models/videos/video-create.model.ts b/shared/models/videos/video-create.model.ts
new file mode 100644
index 000000000..5c0b498ce
--- /dev/null
+++ b/shared/models/videos/video-create.model.ts
@@ -0,0 +1,9 @@
1export interface VideoCreate {
2 category: number
3 licence: number
4 language: number
5 description: string
6 nsfw: boolean
7 name: string
8 tags: string[]
9}
diff --git a/shared/models/videos/video-rate.type.ts b/shared/models/videos/video-rate.type.ts
new file mode 100644
index 000000000..d48774a4b
--- /dev/null
+++ b/shared/models/videos/video-rate.type.ts
@@ -0,0 +1 @@
export type VideoRateType = 'like' | 'dislike'
diff --git a/shared/models/videos/video-update.model.ts b/shared/models/videos/video-update.model.ts
new file mode 100644
index 000000000..29a82621b
--- /dev/null
+++ b/shared/models/videos/video-update.model.ts
@@ -0,0 +1,9 @@
1export interface VideoUpdate {
2 name?: string
3 category?: number
4 licence?: number
5 language?: number
6 description?: string
7 tags?: string[]
8 nsfw?: boolean
9}
diff --git a/shared/models/video.model.ts b/shared/models/videos/video.model.ts
index 2e35f005c..2e35f005c 100644
--- a/shared/models/video.model.ts
+++ b/shared/models/videos/video.model.ts