})
export class FriendAddComponent implements OnInit {
form: FormGroup
- hosts = [ ]
+ hosts: string[] = [ ]
error: string = null
constructor (
import 'rxjs/add/operator/map'
import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared'
+import { UserCreate } from '../../../../../../shared'
@Injectable()
export class UserService {
private restExtractor: RestExtractor
) {}
- addUser (username: string, password: string, email: string) {
- const body = {
- username,
- email,
- password
- }
-
- return this.authHttp.post(UserService.BASE_USERS_URL, body)
+ addUser (userCreate: UserCreate) {
+ return this.authHttp.post(UserService.BASE_USERS_URL, userCreate)
.map(this.restExtractor.extractDataBool)
.catch(this.restExtractor.handleError)
}
USER_EMAIL,
USER_PASSWORD
} from '../../../shared'
+import { UserCreate } from '../../../../../../shared'
@Component({
selector: 'my-user-add',
addUser () {
this.error = null
- const { username, password, email } = this.form.value
+ const userCreate: UserCreate = this.form.value
- this.userService.addUser(username, password, email).subscribe(
+ this.userService.addUser(userCreate).subscribe(
() => {
- this.notificationsService.success('Success', `User ${username} created.`)
+ this.notificationsService.success('Success', `User ${userCreate.username} created.`)
this.router.navigate([ '/admin/users/list' ])
},
UserService,
USER_PASSWORD
} from '../../shared'
+import { UserUpdate } from '../../../../../shared'
@Component({
selector: 'my-account-details',
updateDetails () {
const displayNSFW = this.form.value['displayNSFW']
- const details = {
+ const details: UserUpdate = {
displayNSFW
}
// Do not use the barrel (dependency loop)
-import { UserRole } from '../../../../../shared/models/user.model'
+import { UserRole } from '../../../../../shared/models/users/user-role.type'
import { User } from '../../shared/users/user.model'
export type TokenOptions = {
import { AuthService } from '../../core'
import { AuthHttp } from '../auth'
import { RestExtractor } from '../rest'
+import { UserCreate, UserUpdate } from '../../../../../shared'
@Injectable()
export class UserService {
changePassword (newPassword: string) {
const url = UserService.BASE_USERS_URL + this.authService.getUser().id
- const body = {
+ const body: UserUpdate = {
password: newPassword
}
.catch((res) => this.restExtractor.handleError(res))
}
- updateDetails (details: { displayNSFW: boolean }) {
+ updateDetails (details: UserUpdate) {
const url = UserService.BASE_USERS_URL + this.authService.getUser().id
return this.authHttp.put(url, details)
.catch((res) => this.restExtractor.handleError(res))
}
- signup (username: string, password: string, email: string) {
- const body = {
- username,
- email,
- password
- }
-
- return this.http.post(UserService.BASE_USERS_URL + 'register', body)
+ signup (userCreate: UserCreate) {
+ return this.http.post(UserService.BASE_USERS_URL + 'register', userCreate)
.map(this.restExtractor.extractDataBool)
.catch(this.restExtractor.handleError)
}
USER_EMAIL,
USER_PASSWORD
} from '../shared'
+import { UserCreate } from '../../../../shared'
@Component({
selector: 'my-signup',
signup () {
this.error = null
- const { username, password, email } = this.form.value
+ const userCreate: UserCreate = this.form.value
- this.userService.signup(username, password, email).subscribe(
+ this.userService.signup(userCreate).subscribe(
() => {
- this.notificationsService.success('Success', `Registration for ${username} complete.`)
+ this.notificationsService.success('Success', `Registration for ${userCreate.username} complete.`)
this.router.navigate([ '/videos/list' ])
},
UserService
} from '../../shared'
import { Video } from './video.model'
-import { UserVideoRate, VideoRateType } from '../../../../../shared'
+import {
+ UserVideoRate,
+ VideoRateType,
+ VideoUpdate,
+ VideoAbuseCreate,
+ UserVideoRateUpdate
+} from '../../../../../shared'
@Injectable()
export class VideoService {
) {}
loadVideoCategories () {
- return this.http.get(VideoService.BASE_VIDEO_URL + 'categories')
- .map(this.restExtractor.extractDataGet)
- .subscribe(data => {
- Object.keys(data).forEach(categoryKey => {
- this.videoCategories.push({
- id: parseInt(categoryKey, 10),
- label: data[categoryKey]
- })
- })
- })
+ return this.loadVideoAttributeEnum('categories', this.videoCategories)
}
loadVideoLicences () {
- return this.http.get(VideoService.BASE_VIDEO_URL + 'licences')
- .map(this.restExtractor.extractDataGet)
- .subscribe(data => {
- Object.keys(data).forEach(licenceKey => {
- this.videoLicences.push({
- id: parseInt(licenceKey, 10),
- label: data[licenceKey]
- })
- })
- })
+ return this.loadVideoAttributeEnum('licences', this.videoLicences)
}
loadVideoLanguages () {
- return this.http.get(VideoService.BASE_VIDEO_URL + 'languages')
- .map(this.restExtractor.extractDataGet)
- .subscribe(data => {
- Object.keys(data).forEach(languageKey => {
- this.videoLanguages.push({
- id: parseInt(languageKey, 10),
- label: data[languageKey]
- })
- })
- })
+ return this.loadVideoAttributeEnum('languages', this.videoLanguages)
}
getVideo (id: string): Observable<Video> {
updateVideo (video: Video) {
const language = video.language ? video.language : null
- const body = {
+ const body: VideoUpdate = {
name: video.name,
category: video.category,
licence: video.licence,
language,
description: video.description,
- tags: video.tags
+ tags: video.tags,
+ nsfw: video.nsfw
}
const headers = new Headers({ 'Content-Type': 'application/json' })
reportVideo (id: string, reason: string) {
const url = VideoService.BASE_VIDEO_URL + id + '/abuse'
- const body = {
+ const body: VideoAbuseCreate = {
reason
}
private setVideoRate (id: string, rateType: VideoRateType) {
const url = VideoService.BASE_VIDEO_URL + id + '/rate'
- const body = {
+ const body: UserVideoRateUpdate = {
rating: rateType
}
return { videos, totalVideos }
}
+
+ private loadVideoAttributeEnum (attributeName: 'categories' | 'licences' | 'languages', hashToPopulate: { id: number, label: string }[]) {
+ return this.http.get(VideoService.BASE_VIDEO_URL + attributeName)
+ .map(this.restExtractor.extractDataGet)
+ .subscribe(data => {
+ Object.keys(data).forEach(dataKey => {
+ hashToPopulate.push({
+ id: parseInt(dataKey, 10),
+ label: data[dataKey]
+ })
+ })
+ })
+ }
}
VIDEO_TAGS
} from '../../shared'
import { VideoService } from '../shared'
+import { VideoCreate } from '../../../../../shared'
@Component({
selector: 'my-videos-add',
removeAfterUpload: true
})
- this.uploader.onBuildItemForm = (item, form) => {
- const name = this.form.value['name']
- const nsfw = this.form.value['nsfw']
- const category = this.form.value['category']
- const licence = this.form.value['licence']
- const language = this.form.value['language']
- const description = this.form.value['description']
- const tags = this.form.value['tags']
+ 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)
+ form.append('category', '' + category)
+ form.append('nsfw', '' + nsfw)
+ form.append('licence', '' + licence)
// Language is optional
if (language) {
- form.append('language', language)
+ form.append('language', '' + language)
}
form.append('description', description)
cd client || exit -1
-npm run webpack-dev-server -- --config config/webpack.dev.js --progress --profile --colors --watch --content-base src/ --inline --hot
+npm run webpack-dev-server -- --config config/webpack.dev.js --progress --profile --colors --watch --content-base src/ --inline --hot --open
#!/usr/bin/env sh
-NODE_ENV=test concurrently \
+NODE_ENV=test concurrently -k \
"npm run tsc -- --sourceMap && npm run nodemon -- --delay 2 --watch ./dist dist/server" \
"npm run tsc -- --sourceMap -w"
import { database as db } from '../../../initializers/database'
import { checkSignature, signatureValidator } from '../../../middlewares'
+import { PodSignature } from '../../../../shared'
const remotePodsRouter = express.Router()
// ---------------------------------------------------------------------------
function removePods (req: express.Request, res: express.Response, next: express.NextFunction) {
- const host = req.body.signature.host
+ const signature: PodSignature = req.body.signature
+ const host = signature.host
db.Pod.loadByHost(host)
- .then(pod => {
- return pod.destroy()
- })
+ .then(pod => pod.destroy())
.then(() => res.type('json').status(204).end())
.catch(err => next(err))
}
import { logger, retryTransactionWrapper } from '../../../helpers'
import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib'
import { PodInstance, VideoInstance } from '../../../models'
+import {
+ RemoteVideoRequest,
+ RemoteVideoCreateData,
+ RemoteVideoUpdateData,
+ RemoteVideoRemoveData,
+ RemoteVideoReportAbuseData,
+ RemoteQaduVideoRequest,
+ RemoteQaduVideoData,
+ RemoteVideoEventRequest,
+ RemoteVideoEventData
+} from '../../../../shared'
const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
// ---------------------------------------------------------------------------
function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
- const requests = req.body.data
+ const requests: RemoteVideoRequest[] = req.body.data
const fromPod = res.locals.secure.pod
// We need to process in the same order to keep consistency
- Promise.each(requests, (request: any) => {
+ Promise.each(requests, request => {
const data = request.data
// Get the function we need to call in order to process the request
}
function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) {
- const requests = req.body.data
+ const requests: RemoteQaduVideoRequest[] = req.body.data
const fromPod = res.locals.secure.pod
- Promise.each(requests, (request: any) => {
+ Promise.each(requests, request => {
const videoData = request.data
return quickAndDirtyUpdateVideoRetryWrapper(videoData, fromPod)
}
function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) {
- const requests = req.body.data
+ const requests: RemoteVideoEventRequest[] = req.body.data
const fromPod = res.locals.secure.pod
- Promise.each(requests, (request: any) => {
+ Promise.each(requests, request => {
const eventData = request.data
return processVideosEventsRetryWrapper(eventData, fromPod)
return res.type('json').status(204).end()
}
-function processVideosEventsRetryWrapper (eventData: any, fromPod: PodInstance) {
+function processVideosEventsRetryWrapper (eventData: RemoteVideoEventData, fromPod: PodInstance) {
const options = {
arguments: [ eventData, fromPod ],
errorMessage: 'Cannot process videos events with many retries.'
return retryTransactionWrapper(processVideosEvents, options)
}
-function processVideosEvents (eventData: any, fromPod: PodInstance) {
+function processVideosEvents (eventData: RemoteVideoEventData, fromPod: PodInstance) {
return db.sequelize.transaction(t => {
return fetchOwnedVideo(eventData.remoteId)
})
}
-function quickAndDirtyUpdateVideoRetryWrapper (videoData: any, fromPod: PodInstance) {
+function quickAndDirtyUpdateVideoRetryWrapper (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
const options = {
arguments: [ videoData, fromPod ],
errorMessage: 'Cannot update quick and dirty the remote video with many retries.'
return retryTransactionWrapper(quickAndDirtyUpdateVideo, options)
}
-function quickAndDirtyUpdateVideo (videoData: any, fromPod: PodInstance) {
+function quickAndDirtyUpdateVideo (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
let videoName
return db.sequelize.transaction(t => {
}
// Handle retries on fail
-function addRemoteVideoRetryWrapper (videoToCreateData: any, fromPod: PodInstance) {
+function addRemoteVideoRetryWrapper (videoToCreateData: RemoteVideoCreateData, fromPod: PodInstance) {
const options = {
arguments: [ videoToCreateData, fromPod ],
errorMessage: 'Cannot insert the remote video with many retries.'
return retryTransactionWrapper(addRemoteVideo, options)
}
-function addRemoteVideo (videoToCreateData: any, fromPod: PodInstance) {
+function addRemoteVideo (videoToCreateData: RemoteVideoCreateData, fromPod: PodInstance) {
logger.debug('Adding remote video "%s".', videoToCreateData.remoteId)
return db.sequelize.transaction(t => {
}
// Handle retries on fail
-function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: any, fromPod: PodInstance) {
+function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: RemoteVideoUpdateData, fromPod: PodInstance) {
const options = {
arguments: [ videoAttributesToUpdate, fromPod ],
errorMessage: 'Cannot update the remote video with many retries'
return retryTransactionWrapper(updateRemoteVideo, options)
}
-function updateRemoteVideo (videoAttributesToUpdate: any, fromPod: PodInstance) {
+function updateRemoteVideo (videoAttributesToUpdate: RemoteVideoUpdateData, fromPod: PodInstance) {
logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId)
return db.sequelize.transaction(t => {
})
}
-function removeRemoteVideo (videoToRemoveData: any, fromPod: PodInstance) {
+function removeRemoteVideo (videoToRemoveData: RemoteVideoRemoveData, fromPod: PodInstance) {
// We need the instance because we have to remove some other stuffs (thumbnail etc)
return fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId)
.then(video => {
})
}
-function reportAbuseRemoteVideo (reportData: any, fromPod: PodInstance) {
+function reportAbuseRemoteVideo (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
return fetchOwnedVideo(reportData.videoRemoteId)
.then(video => {
logger.debug('Reporting remote abuse for video %s.', video.id)
setUsersSort,
token
} from '../../middlewares'
-import { UserVideoRate as FormatedUserVideoRate } from '../../../shared'
+import { UserVideoRate as FormatedUserVideoRate, UserCreate, UserUpdate } from '../../../shared'
const usersRouter = express.Router()
// ---------------------------------------------------------------------------
function createUser (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const body: UserCreate = req.body
+
const user = db.User.build({
- username: req.body.username,
- password: req.body.password,
- email: req.body.email,
+ username: body.username,
+ password: body.password,
+ email: body.email,
displayNSFW: false,
role: USER_ROLES.USER
})
}
function updateUser (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const body: UserUpdate = req.body
+
db.User.loadByUsername(res.locals.oauth.token.user.username)
.then(user => {
- if (req.body.password) user.password = req.body.password
- if (req.body.displayNSFW !== undefined) user.displayNSFW = req.body.displayNSFW
+ if (body.password) user.password = body.password
+ if (body.displayNSFW !== undefined) user.displayNSFW = body.displayNSFW
return user.save()
})
setPagination
} from '../../../middlewares'
import { VideoInstance } from '../../../models'
+import { VideoAbuseCreate } from '../../../../shared'
const abuseVideoRouter = express.Router()
function reportVideoAbuse (req: express.Request, res: express.Response) {
const videoInstance = res.locals.video
const reporterUsername = res.locals.oauth.token.User.username
+ const body: VideoAbuseCreate = req.body
const abuse = {
reporterUsername,
- reason: req.body.reason,
+ reason: body.reason,
videoId: videoInstance.id,
reporterPodId: null // This is our pod that reported this abuse
}
renamePromise
} from '../../../helpers'
import { TagInstance } from '../../../models'
+import { VideoCreate, VideoUpdate } from '../../../../shared'
import { abuseVideoRouter } from './abuse'
import { blacklistRouter } from './blacklist'
}
function addVideo (req: express.Request, res: express.Response, videoFile: Express.Multer.File) {
- const videoInfos = req.body
+ const videoInfos: VideoCreate = req.body
return db.sequelize.transaction(t => {
const user = res.locals.oauth.token.User
function updateVideo (req: express.Request, res: express.Response) {
const videoInstance = res.locals.video
const videoFieldsSave = videoInstance.toJSON()
- const videoInfosToUpdate = req.body
+ const videoInfosToUpdate: VideoUpdate = req.body
return db.sequelize.transaction(t => {
let tagsPromise: Promise<TagInstance[]>
import * as express from 'express'
+import * as Promise from 'bluebird'
import { database as db } from '../../../initializers/database'
import {
authenticate,
videoRateValidator
} from '../../../middlewares'
+import { UserVideoRateUpdate, VideoRateType } from '../../../../shared'
const rateVideoRouter = express.Router()
}
function rateVideo (req: express.Request, res: express.Response) {
- const rateType = req.body.rating
+ const body: UserVideoRateUpdate = req.body
+ const rateType = body.rating
const videoInstance = res.locals.video
const userInstance = res.locals.oauth.token.User
if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++
else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
+ let promise: Promise<any>
+
// There was a previous rate, update it
if (previousRate) {
// We will remove the previous rate, so we will need to remove it from the video attribute
if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement--
else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
- previousRate.type = rateType
+ if (rateType === 'none') { // Destroy previous rate
+ promise = previousRate.destroy()
+ } else { // Update previous rate
+ previousRate.type = rateType as VideoRateType
- return previousRate.save(options).then(() => ({ t, likesToIncrement, dislikesToIncrement }))
- } else { // There was not a previous rate, insert a new one
+ promise = previousRate.save()
+ }
+ } else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate
const query = {
userId: userInstance.id,
videoId: videoInstance.id,
type: rateType
}
- return db.UserVideoRate.create(query, options).then(() => ({ likesToIncrement, dislikesToIncrement }))
+ promise = db.UserVideoRate.create(query, options)
+ } else {
+ promise = Promise.resolve()
}
+
+ return promise.then(() => ({ likesToIncrement, dislikesToIncrement }))
})
.then(({ likesToIncrement, dislikesToIncrement }) => {
const options = { transaction: t }
CONFIG
} from '../initializers'
import { PodInstance } from '../models'
+import { PodSignature } from '../../shared'
import { sign } from './peertube-crypto'
type MakeRetryRequestParams = {
}
function makeSecureRequest (params: MakeSecureRequestParams) {
return new Promise<{ response: request.RequestResponse, body: any }>((res, rej) => {
- const requestParams = {
+ const requestParams: {
+ url: string,
+ json: {
+ signature: PodSignature,
+ data: any
+ }
+ } = {
url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path,
- json: {}
+ json: {
+ signature: null,
+ data: null
+ }
}
if (params.method !== 'POST') {
}
sign(dataToSign).then(signature => {
- requestParams.json['signature'] = {
+ requestParams.json.signature = {
host, // Which host we pretend to be
signature
}
// If there are data informations
if (params.data) {
- requestParams.json['data'] = params.data
+ requestParams.json.data = params.data
}
request.post(requestParams, (err, response, body) => err ? rej(err) : res({ response, body }))
import {
RequestEndpoint,
RequestVideoEventType,
- RequestVideoQaduType
+ RequestVideoQaduType,
+ RemoteVideoCreateData,
+ RemoteVideoUpdateData,
+ RemoteVideoRemoveData,
+ RemoteVideoReportAbuseData
} from '../../shared'
type QaduParam = { videoId: string, type: RequestVideoQaduType }
requestVideoEventScheduler.activate()
}
-function addVideoToFriends (videoData: Object, transaction: Sequelize.Transaction) {
+function addVideoToFriends (videoData: RemoteVideoCreateData, transaction: Sequelize.Transaction) {
const options = {
type: ENDPOINT_ACTIONS.ADD,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
return createRequest(options)
}
-function updateVideoToFriends (videoData: Object, transaction: Sequelize.Transaction) {
+function updateVideoToFriends (videoData: RemoteVideoUpdateData, transaction: Sequelize.Transaction) {
const options = {
type: ENDPOINT_ACTIONS.UPDATE,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
return createRequest(options)
}
-function removeVideoToFriends (videoParams: Object) {
+function removeVideoToFriends (videoParams: RemoteVideoRemoveData) {
const options = {
type: ENDPOINT_ACTIONS.REMOVE,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
return createRequest(options)
}
-function reportAbuseVideoToFriend (reportData: Object, video: VideoInstance, transaction: Sequelize.Transaction) {
+function reportAbuseVideoToFriend (reportData: RemoteVideoReportAbuseData, video: VideoInstance, transaction: Sequelize.Transaction) {
const options = {
type: ENDPOINT_ACTIONS.REPORT_ABUSE,
endpoint: REQUEST_ENDPOINTS.VIDEOS,
REQUESTS_INTERVAL
} from '../../initializers'
+interface RequestsObjects<U> {
+ [ id: string ]: {
+ toPod: PodInstance
+ endpoint: string
+ ids: number[] // ids
+ datas: U[]
+ }
+}
+
abstract class AbstractRequestScheduler <T> {
requestInterval: number
limitPods: number
abstract getRequestModel (): AbstractRequestClass<T>
abstract getRequestToPodModel (): AbstractRequestToPodClass
- abstract buildRequestObjects (requestsGrouped: T): {}
+ abstract buildRequestsObjects (requestsGrouped: T): RequestsObjects<any>
activate () {
logger.info('Requests scheduler activated.')
// ---------------------------------------------------------------------------
// Make a requests to friends of a certain type
- protected makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: Object) {
+ protected makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: any) {
const params = {
toPod: toPod,
method: 'POST' as 'POST',
return this.getRequestModel().listWithLimitAndRandom(this.limitPods, this.limitPerPod)
.then((requestsGrouped: T) => {
// We want to group requests by destinations pod and endpoint
- const requestsToMake = this.buildRequestObjects(requestsGrouped)
+ const requestsToMake = this.buildRequestsObjects(requestsGrouped)
// If there are no requests, abort
if (isEmpty(requestsToMake) === true) {
logger.info('Making "%s" to friends.', this.description)
- const goodPods = []
- const badPods = []
+ const goodPods: number[] = []
+ const badPods: number[] = []
return Promise.map(Object.keys(requestsToMake), hashKey => {
const requestToMake = requestsToMake[hashKey]
// ---------------------------------------------------------------------------
export {
- AbstractRequestScheduler
+ AbstractRequestScheduler,
+ RequestsObjects
}
import * as Sequelize from 'sequelize'
import { database as db } from '../../initializers/database'
-import { AbstractRequestScheduler } from './abstract-request-scheduler'
+import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
import { logger } from '../../helpers'
import { REQUESTS_LIMIT_PODS, REQUESTS_LIMIT_PER_POD } from '../../initializers'
import { RequestsGrouped } from '../../models'
-import { RequestEndpoint } from '../../../shared'
+import { RequestEndpoint, RemoteVideoRequest } from '../../../shared'
export type RequestSchedulerOptions = {
type: string
return db.RequestToPod
}
- buildRequestObjects (requestsGrouped: RequestsGrouped) {
- const requestsToMakeGrouped = {}
+ buildRequestsObjects (requestsGrouped: RequestsGrouped) {
+ const requestsToMakeGrouped: RequestsObjects<RemoteVideoRequest> = {}
Object.keys(requestsGrouped).forEach(toPodId => {
requestsGrouped[toPodId].forEach(data => {
import * as Sequelize from 'sequelize'
import { database as db } from '../../initializers/database'
-import { AbstractRequestScheduler } from './abstract-request-scheduler'
+import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
import {
REQUESTS_VIDEO_EVENT_LIMIT_PODS,
REQUESTS_VIDEO_EVENT_LIMIT_PER_POD,
REQUEST_VIDEO_EVENT_ENDPOINT
} from '../../initializers'
import { RequestsVideoEventGrouped } from '../../models'
-import { RequestVideoEventType } from '../../../shared'
+import { RequestVideoEventType, RemoteVideoEventRequest, RemoteVideoEventType } from '../../../shared'
export type RequestVideoEventSchedulerOptions = {
type: RequestVideoEventType
return db.RequestVideoEvent
}
- buildRequestObjects (eventRequests: RequestsVideoEventGrouped) {
- const requestsToMakeGrouped = {}
+ buildRequestsObjects (eventRequests: RequestsVideoEventGrouped) {
+ const requestsToMakeGrouped: RequestsObjects<RemoteVideoEventRequest> = {}
/* Example:
{
}
}
*/
- const eventsPerVideoPerPod = {}
+ const eventsPerVideoPerPod: {
+ [ podId: string ]: {
+ [ videoRemoteId: string ]: {
+ views?: number
+ likes?: number
+ dislikes?: number
+ }
+ }
+ } = {}
// We group video events per video and per pod
// We add the counts of the same event types
requestsToMakeGrouped[toPodId].datas.push({
data: {
remoteId,
- eventType,
- count: eventsForVideo[eventType]
+ eventType: eventType as RemoteVideoEventType,
+ count: +eventsForVideo[eventType]
}
})
})
import * as Sequelize from 'sequelize'
import { database as db } from '../../initializers/database'
-import { AbstractRequestScheduler } from './abstract-request-scheduler'
+import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler'
import { logger } from '../../helpers'
import {
REQUESTS_VIDEO_QADU_LIMIT_PODS,
REQUEST_VIDEO_QADU_ENDPOINT,
REQUEST_VIDEO_QADU_TYPES
} from '../../initializers'
-import { RequestsVideoQaduGrouped } from '../../models'
-import { RequestVideoQaduType } from '../../../shared'
+import { RequestsVideoQaduGrouped, PodInstance } from '../../models'
+import { RemoteQaduVideoRequest, RequestVideoQaduType } from '../../../shared'
+
+// We create a custom interface because we need "videos" attribute for our computations
+interface RequestsObjectsCustom<U> extends RequestsObjects<U> {
+ [ id: string ]: {
+ toPod: PodInstance
+ endpoint: string
+ ids: number[] // ids
+ datas: U[]
+
+ videos: {
+ [ id: string ]: {
+ remoteId: string
+ likes?: number
+ dislikes?: number
+ views?: number
+ }
+ }
+ }
+}
export type RequestVideoQaduSchedulerOptions = {
type: RequestVideoQaduType
return db.RequestVideoQadu
}
- buildRequestObjects (requests: RequestsVideoQaduGrouped) {
- const requestsToMakeGrouped = {}
+ buildRequestsObjects (requests: RequestsVideoQaduGrouped) {
+ const requestsToMakeGrouped: RequestsObjectsCustom<RemoteQaduVideoRequest> = {}
Object.keys(requests).forEach(toPodId => {
requests[toPodId].forEach(data => {
// Maybe another attribute was filled for this video
let videoData = requestsToMakeGrouped[hashKey].videos[video.id]
- if (!videoData) videoData = {}
+ if (!videoData) videoData = { remoteId: null }
switch (request.type) {
case REQUEST_VIDEO_QADU_TYPES.LIKES:
logger,
checkSignature as peertubeCryptoCheckSignature
} from '../helpers'
+import { PodSignature } from '../../shared'
function checkSignature (req: express.Request, res: express.Response, next: express.NextFunction) {
- const host = req.body.signature.host
+ const signatureObject: PodSignature = req.body.signature
+ const host = signatureObject.host
+
db.Pod.loadByHost(host)
.then(pod => {
if (pod === null) {
signatureShouldBe = host
}
- const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature)
+ const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, signatureObject.signature)
if (signatureOk === true) {
res.locals.secure = {
return next()
}
- logger.error('Signature is not okay in body for %s.', req.body.signature.host)
+ logger.error('Signature is not okay in body for %s.', signatureObject.host)
return res.sendStatus(403)
})
.catch(err => {
- logger.error('Cannot get signed host in body.', { error: err.stack, signature: req.body.signature.signature })
+ logger.error('Cannot get signed host in body.', { error: err.stack, signature: signatureObject.signature })
return res.sendStatus(500)
})
}
import * as Promise from 'bluebird'
// Don't use barrel, import just what we need
-import { Pod as FormatedPod } from '../../../shared/models/pod.model'
+import { Pod as FormatedPod } from '../../../shared/models/pods/pod.model'
export namespace PodMethods {
export type ToFormatedJSON = (this: PodInstance) => FormatedPod
import * as Promise from 'bluebird'
// Don't use barrel, import just what we need
-import { UserRole, User as FormatedUser } from '../../../shared/models/user.model'
+import { User as FormatedUser } from '../../../shared/models/users/user.model'
+import { UserRole } from '../../../shared/models/users/user-role.type'
import { ResultList } from '../../../shared/models/result-list.model'
export namespace UserMethods {
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
-import { VideoRateType } from '../../../shared/models/user-video-rate.model'
+import { VideoRateType } from '../../../shared/models/videos/video-rate.type'
export namespace UserVideoRateMethods {
export type Load = (userId: number, videoId: string, transaction: Sequelize.Transaction) => Promise<UserVideoRateInstance>
import { ResultList } from '../../../shared'
// Don't use barrel, import just what we need
-import { VideoAbuse as FormatedVideoAbuse } from '../../../shared/models/video-abuse.model'
+import { VideoAbuse as FormatedVideoAbuse } from '../../../shared/models/videos/video-abuse.model'
export namespace VideoAbuseMethods {
export type ToFormatedJSON = (this: VideoAbuseInstance) => FormatedVideoAbuse
import { ResultList } from '../../../shared'
// Don't use barrel, import just what we need
-import { BlacklistedVideo as FormatedBlacklistedVideo } from '../../../shared/models/video-blacklist.model'
+import { BlacklistedVideo as FormatedBlacklistedVideo } from '../../../shared/models/videos/video-blacklist.model'
export namespace BlacklistedVideoMethods {
export type ToFormatedJSON = (this: BlacklistedVideoInstance) => FormatedBlacklistedVideo
import { TagAttributes, TagInstance } from './tag-interface'
// Don't use barrel, import just what we need
-import { Video as FormatedVideo } from '../../../shared/models/video.model'
+import { Video as FormatedVideo } from '../../../shared/models/videos/video.model'
import { ResultList } from '../../../shared/models/result-list.model'
export type FormatedAddRemoteVideo = {
+export * from './pods'
+export * from './users'
+export * from './videos'
export * from './job.model'
export * from './oauth-client-local.model'
-export * from './pod.model'
export * from './result-list.model'
export * from './request-scheduler.model'
-export * from './user-video-rate.model'
-export * from './user.model'
-export * from './video-abuse.model'
-export * from './video-blacklist.model'
-export * from './video.model'
export * from './server-config.model'
+++ /dev/null
-export interface Pod {
- id: number,
- host: string,
- email: string,
- score: number,
- createdAt: Date
-}
--- /dev/null
+export * from './pod-signature.model'
+export * from './pod.model'
+export * from './remote-video'
--- /dev/null
+export interface PodSignature {
+ host: string
+ signature: string
+}
--- /dev/null
+export interface Pod {
+ id: number,
+ host: string,
+ email: string,
+ score: number,
+ createdAt: Date
+}
--- /dev/null
+export * from './remote-qadu-video-request.model'
+export * from './remote-video-event-request.model'
+export * from './remote-video-request.model'
+export * from './remote-video-create-request.model'
+export * from './remote-video-update-request.model'
+export * from './remote-video-remove-request.model'
+export * from './remote-video-report-abuse-request.model'
--- /dev/null
+export interface RemoteQaduVideoData {
+ remoteId: string
+ views?: number
+ likes?: number
+ dislikes?: number
+}
+
+export interface RemoteQaduVideoRequest {
+ data: RemoteQaduVideoData
+}
--- /dev/null
+import { RemoteVideoRequest } from './remote-video-request.model'
+
+export interface RemoteVideoCreateData {
+ remoteId: string
+ author: string
+ tags: string[]
+ name: string
+ extname: string
+ infoHash: string
+ category: number
+ licence: number
+ language: number
+ nsfw: boolean
+ description: string
+ duration: number
+ createdAt: Date
+ updatedAt: Date
+ views: number
+ likes: number
+ dislikes: number
+ thumbnailData: string
+}
+
+export interface RemoteVideoCreateRequest extends RemoteVideoRequest {
+ type: 'add'
+ data: RemoteVideoCreateData
+}
--- /dev/null
+export type RemoteVideoEventType = 'views' | 'likes' | 'dislikes'
+
+export interface RemoteVideoEventData {
+ remoteId: string
+ eventType: RemoteVideoEventType
+ count: number
+}
+
+export interface RemoteVideoEventRequest {
+ data: RemoteVideoEventData
+}
--- /dev/null
+import { RemoteVideoRequest } from './remote-video-request.model'
+
+export interface RemoteVideoRemoveData {
+ remoteId: string
+}
+
+export interface RemoteVideoRemoveRequest extends RemoteVideoRequest {
+ type: 'remove'
+ data: RemoteVideoRemoveData
+}
--- /dev/null
+import { RemoteVideoRequest } from './remote-video-request.model'
+
+export interface RemoteVideoReportAbuseData {
+ videoRemoteId: string
+ reporterUsername: string
+ reportReason: string
+}
+
+export interface RemoteVideoReportAbuseRequest extends RemoteVideoRequest {
+ type: 'report-abuse'
+ data: RemoteVideoReportAbuseData
+}
--- /dev/null
+export interface RemoteVideoRequest {
+ type: 'add' | 'update' | 'remove' | 'report-abuse'
+ data: any
+}
--- /dev/null
+export interface RemoteVideoUpdateData {
+ remoteId: string
+ tags: string[]
+ name: string
+ extname: string
+ infoHash: string
+ category: number
+ licence: number
+ language: number
+ nsfw: boolean
+ description: string
+ duration: number
+ createdAt: Date
+ updatedAt: Date
+ views: number
+ likes: number
+ dislikes: number
+}
+
+export interface RemoteVideoUpdateRequest {
+ type: 'update'
+ data: RemoteVideoUpdateData
+}
+++ /dev/null
-export type VideoRateType = 'like' | 'dislike'
-export type UserVideoRateType = 'like' | 'dislike' | 'none'
-
-export interface UserVideoRate {
- videoId: string
- rating: UserVideoRateType
-}
+++ /dev/null
-export type UserRole = 'admin' | 'user'
-
-export interface User {
- id: number
- username: string
- email: string
- displayNSFW: boolean
- role: UserRole
- createdAt: Date
-}
--- /dev/null
+export * from './user.model'
+export * from './user-create.model'
+export * from './user-update.model'
+export * from './user-role.type'
--- /dev/null
+export interface UserCreate {
+ username: string
+ password: string
+ email: string
+}
--- /dev/null
+export type UserRole = 'admin' | 'user'
--- /dev/null
+export interface UserUpdate {
+ displayNSFW?: boolean
+ password?: string
+}
--- /dev/null
+import { UserRole } from './user-role.type'
+
+export interface User {
+ id: number
+ username: string
+ email: string
+ displayNSFW: boolean
+ role: UserRole
+ createdAt: Date
+}
+++ /dev/null
-export interface VideoAbuse {
- id: number
- reporterPodHost: string
- reason: string
- reporterUsername: string
- videoId: string
- createdAt: Date
-}
+++ /dev/null
-export interface BlacklistedVideo {
- id: number
- videoId: string
- createdAt: Date
-}
+++ /dev/null
-export interface Video {
- id: string
- author: string
- createdAt: Date
- categoryLabel: string
- category: number
- licenceLabel: string
- licence: number
- languageLabel: string
- language: number
- description: string
- duration: number
- isLocal: boolean
- magnetUri: string
- name: string
- podHost: string
- tags: string[]
- thumbnailPath: string
- views: number
- likes: number
- dislikes: number
- nsfw: boolean
-}
--- /dev/null
+export * from './user-video-rate-update.model'
+export * from './user-video-rate.model'
+export * from './user-video-rate.type'
+export * from './video-abuse-create.model'
+export * from './video-abuse.model'
+export * from './video-blacklist.model'
+export * from './video-create.model'
+export * from './video-rate.type'
+export * from './video-update.model'
+export * from './video.model'
--- /dev/null
+import { UserVideoRateType } from './user-video-rate.type'
+
+export interface UserVideoRateUpdate {
+ rating: UserVideoRateType
+}
--- /dev/null
+import { UserVideoRateType } from './user-video-rate.type'
+
+export interface UserVideoRate {
+ videoId: string
+ rating: UserVideoRateType
+}
--- /dev/null
+export type UserVideoRateType = 'like' | 'dislike' | 'none'
--- /dev/null
+export interface VideoAbuseCreate {
+ reason: string
+}
--- /dev/null
+export interface VideoAbuse {
+ id: number
+ reporterPodHost: string
+ reason: string
+ reporterUsername: string
+ videoId: string
+ createdAt: Date
+}
--- /dev/null
+export interface BlacklistedVideo {
+ id: number
+ videoId: string
+ createdAt: Date
+}
--- /dev/null
+export interface VideoCreate {
+ category: number
+ licence: number
+ language: number
+ description: string
+ nsfw: boolean
+ name: string
+ tags: string[]
+}
--- /dev/null
+export type VideoRateType = 'like' | 'dislike'
--- /dev/null
+export interface VideoUpdate {
+ name?: string
+ category?: number
+ licence?: number
+ language?: number
+ description?: string
+ tags?: string[]
+ nsfw?: boolean
+}
--- /dev/null
+export interface Video {
+ id: string
+ author: string
+ createdAt: Date
+ categoryLabel: string
+ category: number
+ licenceLabel: string
+ licence: number
+ languageLabel: string
+ language: number
+ description: string
+ duration: number
+ isLocal: boolean
+ magnetUri: string
+ name: string
+ podHost: string
+ tags: string[]
+ thumbnailPath: string
+ views: number
+ likes: number
+ dislikes: number
+ nsfw: boolean
+}