Put Person first in AP attributedTo
[oweals/peertube.git] / server / models / video / video-share.ts
1 import * as Sequelize from 'sequelize'
2 import * as Bluebird from 'bluebird'
3 import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
4 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
5 import { CONSTRAINTS_FIELDS } from '../../initializers'
6 import { AccountModel } from '../account/account'
7 import { ActorModel } from '../activitypub/actor'
8 import { throwIfNotValid } from '../utils'
9 import { VideoModel } from './video'
10 import { VideoChannelModel } from './video-channel'
11
12 enum ScopeNames {
13   FULL = 'FULL',
14   WITH_ACTOR = 'WITH_ACTOR'
15 }
16
17 @Scopes({
18   [ScopeNames.FULL]: {
19     include: [
20       {
21         model: () => ActorModel,
22         required: true
23       },
24       {
25         model: () => VideoModel,
26         required: true
27       }
28     ]
29   },
30   [ScopeNames.WITH_ACTOR]: {
31     include: [
32       {
33         model: () => ActorModel,
34         required: true
35       }
36     ]
37   }
38 })
39 @Table({
40   tableName: 'videoShare',
41   indexes: [
42     {
43       fields: [ 'actorId' ]
44     },
45     {
46       fields: [ 'videoId' ]
47     },
48     {
49       fields: [ 'url' ],
50       unique: true
51     }
52   ]
53 })
54 export class VideoShareModel extends Model<VideoShareModel> {
55
56   @AllowNull(false)
57   @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))
58   @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_SHARE.URL.max))
59   url: string
60
61   @CreatedAt
62   createdAt: Date
63
64   @UpdatedAt
65   updatedAt: Date
66
67   @ForeignKey(() => ActorModel)
68   @Column
69   actorId: number
70
71   @BelongsTo(() => ActorModel, {
72     foreignKey: {
73       allowNull: false
74     },
75     onDelete: 'cascade'
76   })
77   Actor: ActorModel
78
79   @ForeignKey(() => VideoModel)
80   @Column
81   videoId: number
82
83   @BelongsTo(() => VideoModel, {
84     foreignKey: {
85       allowNull: false
86     },
87     onDelete: 'cascade'
88   })
89   Video: VideoModel
90
91   static load (actorId: number, videoId: number, t: Sequelize.Transaction) {
92     return VideoShareModel.scope(ScopeNames.WITH_ACTOR).findOne({
93       where: {
94         actorId,
95         videoId
96       },
97       transaction: t
98     })
99   }
100
101   static loadActorsByShare (videoId: number, t: Sequelize.Transaction) {
102     const query = {
103       where: {
104         videoId
105       },
106       include: [
107         {
108           model: ActorModel,
109           required: true
110         }
111       ],
112       transaction: t
113     }
114
115     return VideoShareModel.scope(ScopeNames.FULL).findAll(query)
116       .then(res => res.map(r => r.Actor))
117   }
118
119   static loadActorsByVideoOwner (actorOwnerId: number, t: Sequelize.Transaction): Bluebird<ActorModel[]> {
120     const query = {
121       attributes: [],
122       include: [
123         {
124           model: ActorModel,
125           required: true
126         },
127         {
128           attributes: [],
129           model: VideoModel,
130           required: true,
131           include: [
132             {
133               attributes: [],
134               model: VideoChannelModel.unscoped(),
135               required: true,
136               include: [
137                 {
138                   attributes: [],
139                   model: AccountModel.unscoped(),
140                   required: true,
141                   where: {
142                     actorId: actorOwnerId
143                   }
144                 }
145               ]
146             }
147           ]
148         }
149       ],
150       transaction: t
151     }
152
153     return VideoShareModel.scope(ScopeNames.FULL).findAll(query)
154       .then(res => res.map(r => r.Actor))
155   }
156
157   static loadActorsByVideoChannel (videoChannelId: number, t: Sequelize.Transaction): Bluebird<ActorModel[]> {
158     const query = {
159       attributes: [],
160       include: [
161         {
162           model: ActorModel,
163           required: true
164         },
165         {
166           attributes: [],
167           model: VideoModel,
168           required: true,
169           where: {
170             channelId: videoChannelId
171           }
172         }
173       ],
174       transaction: t
175     }
176
177     return VideoShareModel.scope(ScopeNames.FULL)
178       .findAll(query)
179       .then(res => res.map(r => r.Actor))
180   }
181 }