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