aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/activitypub/inbox.ts4
-rw-r--r--server/helpers/custom-validators/activitypub/activity.ts8
-rw-r--r--server/helpers/custom-validators/activitypub/videos.ts24
-rw-r--r--server/initializers/database.ts4
-rw-r--r--server/lib/activitypub/index.ts5
-rw-r--r--server/lib/activitypub/process-add.ts7
-rw-r--r--server/lib/activitypub/process-announce.ts52
-rw-r--r--server/lib/activitypub/process-create.ts9
-rw-r--r--server/models/video/index.ts2
-rw-r--r--server/models/video/video-channel-share-interface.ts27
-rw-r--r--server/models/video/video-channel-share.ts49
-rw-r--r--server/models/video/video-share-interface.ts25
-rw-r--r--server/models/video/video-share.ts49
-rw-r--r--server/models/video/video.ts11
14 files changed, 255 insertions, 21 deletions
diff --git a/server/controllers/activitypub/inbox.ts b/server/controllers/activitypub/inbox.ts
index e62125d85..5f47648df 100644
--- a/server/controllers/activitypub/inbox.ts
+++ b/server/controllers/activitypub/inbox.ts
@@ -5,6 +5,7 @@ import { isActivityValid } from '../../helpers/custom-validators/activitypub/act
5import { processCreateActivity, processFlagActivity, processUpdateActivity } from '../../lib' 5import { processCreateActivity, processFlagActivity, processUpdateActivity } from '../../lib'
6import { processAcceptActivity } from '../../lib/activitypub/process-accept' 6import { processAcceptActivity } from '../../lib/activitypub/process-accept'
7import { processAddActivity } from '../../lib/activitypub/process-add' 7import { processAddActivity } from '../../lib/activitypub/process-add'
8import { processAnnounceActivity } from '../../lib/activitypub/process-announce'
8import { processDeleteActivity } from '../../lib/activitypub/process-delete' 9import { processDeleteActivity } from '../../lib/activitypub/process-delete'
9import { processFollowActivity } from '../../lib/activitypub/process-follow' 10import { processFollowActivity } from '../../lib/activitypub/process-follow'
10import { asyncMiddleware, checkSignature, localAccountValidator, signatureValidator } from '../../middlewares' 11import { asyncMiddleware, checkSignature, localAccountValidator, signatureValidator } from '../../middlewares'
@@ -18,7 +19,8 @@ const processActivity: { [ P in ActivityType ]: (activity: Activity, inboxAccoun
18 Flag: processFlagActivity, 19 Flag: processFlagActivity,
19 Delete: processDeleteActivity, 20 Delete: processDeleteActivity,
20 Follow: processFollowActivity, 21 Follow: processFollowActivity,
21 Accept: processAcceptActivity 22 Accept: processAcceptActivity,
23 Announce: processAnnounceActivity
22} 24}
23 25
24const inboxRouter = express.Router() 26const inboxRouter = express.Router()
diff --git a/server/helpers/custom-validators/activitypub/activity.ts b/server/helpers/custom-validators/activitypub/activity.ts
index b5ba0f7af..08e5ae0aa 100644
--- a/server/helpers/custom-validators/activitypub/activity.ts
+++ b/server/helpers/custom-validators/activitypub/activity.ts
@@ -2,9 +2,12 @@ import * as validator from 'validator'
2import { isAccountAcceptActivityValid, isAccountDeleteActivityValid, isAccountFollowActivityValid } from './account' 2import { isAccountAcceptActivityValid, isAccountDeleteActivityValid, isAccountFollowActivityValid } from './account'
3import { isActivityPubUrlValid } from './misc' 3import { isActivityPubUrlValid } from './misc'
4import { 4import {
5 isVideoAnnounceValid,
6 isVideoChannelAnnounceValid,
5 isVideoChannelCreateActivityValid, 7 isVideoChannelCreateActivityValid,
6 isVideoChannelDeleteActivityValid, 8 isVideoChannelDeleteActivityValid,
7 isVideoChannelUpdateActivityValid, 9 isVideoChannelUpdateActivityValid,
10 isVideoFlagValid,
8 isVideoTorrentAddActivityValid, 11 isVideoTorrentAddActivityValid,
9 isVideoTorrentDeleteActivityValid, 12 isVideoTorrentDeleteActivityValid,
10 isVideoTorrentUpdateActivityValid 13 isVideoTorrentUpdateActivityValid
@@ -32,7 +35,10 @@ function isActivityValid (activity: any) {
32 isVideoChannelDeleteActivityValid(activity) || 35 isVideoChannelDeleteActivityValid(activity) ||
33 isAccountDeleteActivityValid(activity) || 36 isAccountDeleteActivityValid(activity) ||
34 isAccountFollowActivityValid(activity) || 37 isAccountFollowActivityValid(activity) ||
35 isAccountAcceptActivityValid(activity) 38 isAccountAcceptActivityValid(activity) ||
39 isVideoFlagValid(activity) ||
40 isVideoAnnounceValid(activity) ||
41 isVideoChannelAnnounceValid(activity)
36} 42}
37 43
38// --------------------------------------------------------------------------- 44// ---------------------------------------------------------------------------
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts
index a46757397..9ddacd601 100644
--- a/server/helpers/custom-validators/activitypub/videos.ts
+++ b/server/helpers/custom-validators/activitypub/videos.ts
@@ -3,6 +3,7 @@ import { ACTIVITY_PUB } from '../../../initializers'
3import { exists, isDateValid, isUUIDValid } from '../misc' 3import { exists, isDateValid, isUUIDValid } from '../misc'
4import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' 4import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels'
5import { 5import {
6 isVideoAbuseReasonValid,
6 isVideoDurationValid, 7 isVideoDurationValid,
7 isVideoNameValid, 8 isVideoNameValid,
8 isVideoNSFWValid, 9 isVideoNSFWValid,
@@ -11,7 +12,7 @@ import {
11 isVideoUrlValid, 12 isVideoUrlValid,
12 isVideoViewsValid 13 isVideoViewsValid
13} from '../videos' 14} from '../videos'
14import { isBaseActivityValid } from './misc' 15import { isActivityPubUrlValid, isBaseActivityValid } from './misc'
15 16
16function isVideoTorrentAddActivityValid (activity: any) { 17function isVideoTorrentAddActivityValid (activity: any) {
17 return isBaseActivityValid(activity, 'Add') && 18 return isBaseActivityValid(activity, 'Add') &&
@@ -54,6 +55,22 @@ function isVideoTorrentObjectValid (video: any) {
54 setValidRemoteVideoUrls(video.url) 55 setValidRemoteVideoUrls(video.url)
55} 56}
56 57
58function isVideoFlagValid (activity: any) {
59 return isBaseActivityValid(activity, 'Flag') &&
60 isVideoAbuseReasonValid(activity.content) &&
61 isActivityPubUrlValid(activity.object)
62}
63
64function isVideoAnnounceValid (activity: any) {
65 return isBaseActivityValid(activity, 'Announce') &&
66 isVideoTorrentObjectValid(activity.object)
67}
68
69function isVideoChannelAnnounceValid (activity: any) {
70 return isBaseActivityValid(activity, 'Announce') &&
71 isVideoChannelObjectValid(activity.object)
72}
73
57function isVideoChannelCreateActivityValid (activity: any) { 74function isVideoChannelCreateActivityValid (activity: any) {
58 return isBaseActivityValid(activity, 'Create') && 75 return isBaseActivityValid(activity, 'Create') &&
59 isVideoChannelObjectValid(activity.object) 76 isVideoChannelObjectValid(activity.object)
@@ -83,7 +100,10 @@ export {
83 isVideoTorrentUpdateActivityValid, 100 isVideoTorrentUpdateActivityValid,
84 isVideoChannelUpdateActivityValid, 101 isVideoChannelUpdateActivityValid,
85 isVideoChannelDeleteActivityValid, 102 isVideoChannelDeleteActivityValid,
86 isVideoTorrentDeleteActivityValid 103 isVideoTorrentDeleteActivityValid,
104 isVideoFlagValid,
105 isVideoAnnounceValid,
106 isVideoChannelAnnounceValid
87} 107}
88 108
89// --------------------------------------------------------------------------- 109// ---------------------------------------------------------------------------
diff --git a/server/initializers/database.ts b/server/initializers/database.ts
index 0a716e4fb..5c757694e 100644
--- a/server/initializers/database.ts
+++ b/server/initializers/database.ts
@@ -24,6 +24,8 @@ import { OAuthClientModel } from './../models/oauth/oauth-client-interface'
24import { JobModel } from './../models/job/job-interface' 24import { JobModel } from './../models/job/job-interface'
25import { AccountModel } from './../models/account/account-interface' 25import { AccountModel } from './../models/account/account-interface'
26import { ApplicationModel } from './../models/application/application-interface' 26import { ApplicationModel } from './../models/application/application-interface'
27import { VideoChannelShareModel } from '../models/video/video-channel-share-interface'
28import { VideoShareModel } from '../models/video/video-share-interface'
27 29
28const dbname = CONFIG.DATABASE.DBNAME 30const dbname = CONFIG.DATABASE.DBNAME
29const username = CONFIG.DATABASE.USERNAME 31const username = CONFIG.DATABASE.USERNAME
@@ -45,6 +47,8 @@ const database: {
45 User?: UserModel, 47 User?: UserModel,
46 VideoAbuse?: VideoAbuseModel, 48 VideoAbuse?: VideoAbuseModel,
47 VideoChannel?: VideoChannelModel, 49 VideoChannel?: VideoChannelModel,
50 VideoChannelShare?: VideoChannelShareModel,
51 VideoShare?: VideoShareModel,
48 VideoFile?: VideoFileModel, 52 VideoFile?: VideoFileModel,
49 BlacklistedVideo?: BlacklistedVideoModel, 53 BlacklistedVideo?: BlacklistedVideoModel,
50 VideoTag?: VideoTagModel, 54 VideoTag?: VideoTagModel,
diff --git a/server/lib/activitypub/index.ts b/server/lib/activitypub/index.ts
index f8d56528a..dca446fd4 100644
--- a/server/lib/activitypub/index.ts
+++ b/server/lib/activitypub/index.ts
@@ -1,4 +1,9 @@
1export * from './process-accept'
2export * from './process-add'
3export * from './process-announce'
1export * from './process-create' 4export * from './process-create'
5export * from './process-delete'
2export * from './process-flag' 6export * from './process-flag'
7export * from './process-follow'
3export * from './process-update' 8export * from './process-update'
4export * from './send-request' 9export * from './send-request'
diff --git a/server/lib/activitypub/process-add.ts b/server/lib/activitypub/process-add.ts
index 06d23a2ea..98e414dbb 100644
--- a/server/lib/activitypub/process-add.ts
+++ b/server/lib/activitypub/process-add.ts
@@ -39,7 +39,7 @@ function processAddVideo (account: AccountInstance, videoChannelUrl: string, vid
39async function addRemoteVideo (account: AccountInstance, videoChannelUrl: string, videoToCreateData: VideoTorrentObject) { 39async function addRemoteVideo (account: AccountInstance, videoChannelUrl: string, videoToCreateData: VideoTorrentObject) {
40 logger.debug('Adding remote video %s.', videoToCreateData.url) 40 logger.debug('Adding remote video %s.', videoToCreateData.url)
41 41
42 await db.sequelize.transaction(async t => { 42 return db.sequelize.transaction(async t => {
43 const sequelizeOptions = { 43 const sequelizeOptions = {
44 transaction: t 44 transaction: t
45 } 45 }
@@ -66,7 +66,10 @@ async function addRemoteVideo (account: AccountInstance, videoChannelUrl: string
66 const tags = videoToCreateData.tag.map(t => t.name) 66 const tags = videoToCreateData.tag.map(t => t.name)
67 const tagInstances = await db.Tag.findOrCreateTags(tags, t) 67 const tagInstances = await db.Tag.findOrCreateTags(tags, t)
68 await videoCreated.setTags(tagInstances, sequelizeOptions) 68 await videoCreated.setTags(tagInstances, sequelizeOptions)
69
70 logger.info('Remote video with uuid %s inserted.', videoToCreateData.uuid)
71
72 return videoCreated
69 }) 73 })
70 74
71 logger.info('Remote video with uuid %s inserted.', videoToCreateData.uuid)
72} 75}
diff --git a/server/lib/activitypub/process-announce.ts b/server/lib/activitypub/process-announce.ts
new file mode 100644
index 000000000..d67958aec
--- /dev/null
+++ b/server/lib/activitypub/process-announce.ts
@@ -0,0 +1,52 @@
1import { ActivityAnnounce } from '../../../shared/models/activitypub/activity'
2import { VideoChannelObject } from '../../../shared/models/activitypub/objects/video-channel-object'
3import { VideoTorrentObject } from '../../../shared/models/activitypub/objects/video-torrent-object'
4import { logger } from '../../helpers/logger'
5import { processAddActivity } from './process-add'
6import { processCreateActivity } from './process-create'
7import { database as db } from '../../initializers/index'
8import { getOrCreateAccount } from '../../helpers/activitypub'
9import { VideoChannelInstance } from '../../models/video/video-channel-interface'
10import { VideoInstance } from '../../models/index'
11
12async function processAnnounceActivity (activity: ActivityAnnounce) {
13 const activityType = activity.object.type
14 const accountAnnouncer = await getOrCreateAccount(activity.actor)
15
16 if (activityType === 'VideoChannel') {
17 const activityCreate = Object.assign(activity, {
18 type: 'Create' as 'Create',
19 actor: activity.object.actor,
20 object: activity.object as VideoChannelObject
21 })
22
23 // Add share entry
24 const videoChannel: VideoChannelInstance = await processCreateActivity(activityCreate)
25 await db.VideoChannelShare.create({
26 accountId: accountAnnouncer.id,
27 videoChannelId: videoChannel.id
28 })
29 } else if (activityType === 'Video') {
30 const activityAdd = Object.assign(activity, {
31 type: 'Add' as 'Add',
32 actor: activity.object.actor,
33 object: activity.object as VideoTorrentObject
34 })
35
36 // Add share entry
37 const video: VideoInstance = await processAddActivity(activityAdd)
38 await db.VideoShare.create({
39 accountId: accountAnnouncer.id,
40 videoId: video.id
41 })
42 }
43
44 logger.warn('Unknown activity object type %s when announcing activity.', activityType, { activity: activity.id })
45 return Promise.resolve(undefined)
46}
47
48// ---------------------------------------------------------------------------
49
50export {
51 processAnnounceActivity
52}
diff --git a/server/lib/activitypub/process-create.ts b/server/lib/activitypub/process-create.ts
index 8d842b822..1b825ebbc 100644
--- a/server/lib/activitypub/process-create.ts
+++ b/server/lib/activitypub/process-create.ts
@@ -40,7 +40,7 @@ function processCreateVideoChannel (account: AccountInstance, videoChannelToCrea
40async function addRemoteVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) { 40async function addRemoteVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) {
41 logger.debug('Adding remote video channel "%s".', videoChannelToCreateData.uuid) 41 logger.debug('Adding remote video channel "%s".', videoChannelToCreateData.uuid)
42 42
43 await db.sequelize.transaction(async t => { 43 return db.sequelize.transaction(async t => {
44 let videoChannel = await db.VideoChannel.loadByUUIDOrUrl(videoChannelToCreateData.uuid, videoChannelToCreateData.id, t) 44 let videoChannel = await db.VideoChannel.loadByUUIDOrUrl(videoChannelToCreateData.uuid, videoChannelToCreateData.id, t)
45 if (videoChannel) throw new Error('Video channel with this URL/UUID already exists.') 45 if (videoChannel) throw new Error('Video channel with this URL/UUID already exists.')
46 46
@@ -57,10 +57,11 @@ async function addRemoteVideoChannel (account: AccountInstance, videoChannelToCr
57 videoChannel = db.VideoChannel.build(videoChannelData) 57 videoChannel = db.VideoChannel.build(videoChannelData)
58 videoChannel.url = getActivityPubUrl('videoChannel', videoChannel.uuid) 58 videoChannel.url = getActivityPubUrl('videoChannel', videoChannel.uuid)
59 59
60 await videoChannel.save({ transaction: t }) 60 videoChannel = await videoChannel.save({ transaction: t })
61 }) 61 logger.info('Remote video channel with uuid %s inserted.', videoChannelToCreateData.uuid)
62 62
63 logger.info('Remote video channel with uuid %s inserted.', videoChannelToCreateData.uuid) 63 return videoChannel
64 })
64} 65}
65 66
66function processCreateVideoAbuse (account: AccountInstance, videoAbuseToCreateData: VideoAbuseObject) { 67function processCreateVideoAbuse (account: AccountInstance, videoAbuseToCreateData: VideoAbuseObject) {
diff --git a/server/models/video/index.ts b/server/models/video/index.ts
index 20d97931f..e17bbfab4 100644
--- a/server/models/video/index.ts
+++ b/server/models/video/index.ts
@@ -5,3 +5,5 @@ export * from './video-channel-interface'
5export * from './video-tag-interface' 5export * from './video-tag-interface'
6export * from './video-file-interface' 6export * from './video-file-interface'
7export * from './video-interface' 7export * from './video-interface'
8export * from './video-share-interface'
9export * from './video-channel-share-interface'
diff --git a/server/models/video/video-channel-share-interface.ts b/server/models/video/video-channel-share-interface.ts
new file mode 100644
index 000000000..9ac6d7b23
--- /dev/null
+++ b/server/models/video/video-channel-share-interface.ts
@@ -0,0 +1,27 @@
1import * as Sequelize from 'sequelize'
2import { AccountInstance } from '../account/account-interface'
3import { VideoChannelInstance } from './video-channel-interface'
4
5export namespace VideoChannelShareMethods {
6}
7
8export interface VideoChannelShareClass {
9}
10
11export interface VideoChannelShareAttributes {
12 accountId: number
13 videoChannelId: number
14}
15
16export interface VideoChannelShareInstance
17 extends VideoChannelShareClass, VideoChannelShareAttributes, Sequelize.Instance<VideoChannelShareAttributes> {
18 id: number
19 createdAt: Date
20 updatedAt: Date
21
22 Account?: AccountInstance
23 VideoChannel?: VideoChannelInstance
24}
25
26export interface VideoChannelShareModel
27 extends VideoChannelShareClass, Sequelize.Model<VideoChannelShareInstance, VideoChannelShareAttributes> {}
diff --git a/server/models/video/video-channel-share.ts b/server/models/video/video-channel-share.ts
new file mode 100644
index 000000000..b6199279f
--- /dev/null
+++ b/server/models/video/video-channel-share.ts
@@ -0,0 +1,49 @@
1import * as Sequelize from 'sequelize'
2
3import { addMethodsToModel } from '../utils'
4import { VideoChannelShareAttributes, VideoChannelShareInstance } from './video-channel-share-interface'
5
6let VideoChannelShare: Sequelize.Model<VideoChannelShareInstance, VideoChannelShareAttributes>
7
8export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
9 VideoChannelShare = sequelize.define<VideoChannelShareInstance, VideoChannelShareAttributes>('VideoChannelShare',
10 { },
11 {
12 indexes: [
13 {
14 fields: [ 'accountId' ]
15 },
16 {
17 fields: [ 'videoChannelId' ]
18 }
19 ]
20 }
21 )
22
23 const classMethods = [
24 associate
25 ]
26 addMethodsToModel(VideoChannelShare, classMethods)
27
28 return VideoChannelShare
29}
30
31// ------------------------------ METHODS ------------------------------
32
33function associate (models) {
34 VideoChannelShare.belongsTo(models.Account, {
35 foreignKey: {
36 name: 'accountId',
37 allowNull: false
38 },
39 onDelete: 'cascade'
40 })
41
42 VideoChannelShare.belongsTo(models.VideoChannel, {
43 foreignKey: {
44 name: 'videoChannelId',
45 allowNull: true
46 },
47 onDelete: 'cascade'
48 })
49}
diff --git a/server/models/video/video-share-interface.ts b/server/models/video/video-share-interface.ts
new file mode 100644
index 000000000..7928b9a9c
--- /dev/null
+++ b/server/models/video/video-share-interface.ts
@@ -0,0 +1,25 @@
1import * as Sequelize from 'sequelize'
2import { AccountInstance } from '../account/account-interface'
3import { VideoInstance } from './video-interface'
4
5export namespace VideoShareMethods {
6}
7
8export interface VideoShareClass {
9}
10
11export interface VideoShareAttributes {
12 accountId: number
13 videoId: number
14}
15
16export interface VideoShareInstance extends VideoShareClass, VideoShareAttributes, Sequelize.Instance<VideoShareAttributes> {
17 id: number
18 createdAt: Date
19 updatedAt: Date
20
21 Account?: AccountInstance
22 Video?: VideoInstance
23}
24
25export interface VideoShareModel extends VideoShareClass, Sequelize.Model<VideoShareInstance, VideoShareAttributes> {}
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts
new file mode 100644
index 000000000..358491fd2
--- /dev/null
+++ b/server/models/video/video-share.ts
@@ -0,0 +1,49 @@
1import * as Sequelize from 'sequelize'
2
3import { addMethodsToModel } from '../utils'
4import { VideoShareAttributes, VideoShareInstance } from './video-share-interface'
5
6let VideoShare: Sequelize.Model<VideoShareInstance, VideoShareAttributes>
7
8export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
9 VideoShare = sequelize.define<VideoShareInstance, VideoShareAttributes>('VideoShare',
10 { },
11 {
12 indexes: [
13 {
14 fields: [ 'accountId' ]
15 },
16 {
17 fields: [ 'videoId' ]
18 }
19 ]
20 }
21 )
22
23 const classMethods = [
24 associate
25 ]
26 addMethodsToModel(VideoShare, classMethods)
27
28 return VideoShare
29}
30
31// ------------------------------ METHODS ------------------------------
32
33function associate (models) {
34 VideoShare.belongsTo(models.Account, {
35 foreignKey: {
36 name: 'accountId',
37 allowNull: false
38 },
39 onDelete: 'cascade'
40 })
41
42 VideoShare.belongsTo(models.Video, {
43 foreignKey: {
44 name: 'videoId',
45 allowNull: true
46 },
47 onDelete: 'cascade'
48 })
49}
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index b00081f25..480e54276 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -253,9 +253,6 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
253 }, 253 },
254 { 254 {
255 fields: [ 'channelId' ] 255 fields: [ 'channelId' ]
256 },
257 {
258 fields: [ 'parentId' ]
259 } 256 }
260 ], 257 ],
261 hooks: { 258 hooks: {
@@ -329,14 +326,6 @@ function associate (models) {
329 onDelete: 'cascade' 326 onDelete: 'cascade'
330 }) 327 })
331 328
332 Video.belongsTo(models.Video, {
333 foreignKey: {
334 name: 'parentId',
335 allowNull: true
336 },
337 onDelete: 'cascade'
338 })
339
340 Video.belongsToMany(models.Tag, { 329 Video.belongsToMany(models.Tag, {
341 foreignKey: 'videoId', 330 foreignKey: 'videoId',
342 through: models.VideoTag, 331 through: models.VideoTag,