]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/models/activitypub/actor.ts
Upgrade sequelize
[github/Chocobozzz/PeerTube.git] / server / models / activitypub / actor.ts
index 119d0c1da1bba13c2a09c5afc2643975f78b5ab9..4a466441cd98a73c034ace260279a884d38aeb34 100644 (file)
@@ -30,13 +30,14 @@ import {
   isActorPublicKeyValid
 } from '../../helpers/custom-validators/activitypub/actor'
 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
-import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONFIG, CONSTRAINTS_FIELDS } from '../../initializers'
+import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants'
 import { AccountModel } from '../account/account'
 import { AvatarModel } from '../avatar/avatar'
 import { ServerModel } from '../server/server'
-import { throwIfNotValid } from '../utils'
+import { isOutdated, throwIfNotValid } from '../utils'
 import { VideoChannelModel } from '../video/video-channel'
 import { ActorFollowModel } from './actor-follow'
+import { VideoModel } from '../video/video'
 
 enum ScopeNames {
   FULL = 'FULL'
@@ -55,40 +56,46 @@ export const unusedActorAttributesForAPI = [
   'updatedAt'
 ]
 
-@DefaultScope({
+@DefaultScope(() => ({
   include: [
     {
-      model: () => ServerModel,
+      model: ServerModel,
       required: false
     },
     {
-      model: () => AvatarModel,
+      model: AvatarModel,
       required: false
     }
   ]
-})
-@Scopes({
+}))
+@Scopes(() => ({
   [ScopeNames.FULL]: {
     include: [
       {
-        model: () => AccountModel.unscoped(),
+        model: AccountModel.unscoped(),
         required: false
       },
       {
-        model: () => VideoChannelModel.unscoped(),
-        required: false
+        model: VideoChannelModel.unscoped(),
+        required: false,
+        include: [
+          {
+            model: AccountModel,
+            required: true
+          }
+        ]
       },
       {
-        model: () => ServerModel,
+        model: ServerModel,
         required: false
       },
       {
-        model: () => AvatarModel,
+        model: AvatarModel,
         required: false
       }
     ]
   }
-})
+}))
 @Table({
   tableName: 'actor',
   indexes: [
@@ -124,7 +131,7 @@ export const unusedActorAttributesForAPI = [
 export class ActorModel extends Model<ActorModel> {
 
   @AllowNull(false)
-  @Column(DataType.ENUM(values(ACTIVITY_PUB_ACTOR_TYPES)))
+  @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES)))
   type: ActivityPubActorType
 
   @AllowNull(false)
@@ -144,12 +151,12 @@ export class ActorModel extends Model<ActorModel> {
   url: string
 
   @AllowNull(true)
-  @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPublicKeyValid, 'public key'))
+  @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPublicKeyValid, 'public key', true))
   @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.PUBLIC_KEY.max))
   publicKey: string
 
   @AllowNull(true)
-  @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPrivateKeyValid, 'private key'))
+  @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPrivateKeyValid, 'private key', true))
   @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY.max))
   privateKey: string
 
@@ -212,6 +219,7 @@ export class ActorModel extends Model<ActorModel> {
       name: 'actorId',
       allowNull: false
     },
+    as: 'ActorFollowings',
     onDelete: 'cascade'
   })
   ActorFollowing: ActorFollowModel[]
@@ -257,7 +265,51 @@ export class ActorModel extends Model<ActorModel> {
   VideoChannel: VideoChannelModel
 
   static load (id: number) {
-    return ActorModel.unscoped().findById(id)
+    return ActorModel.unscoped().findByPk(id)
+  }
+
+  static loadAccountActorByVideoId (videoId: number, transaction: Sequelize.Transaction) {
+    const query = {
+      include: [
+        {
+          attributes: [ 'id' ],
+          model: AccountModel.unscoped(),
+          required: true,
+          include: [
+            {
+              attributes: [ 'id' ],
+              model: VideoChannelModel.unscoped(),
+              required: true,
+              include: [
+                {
+                  attributes: [ 'id' ],
+                  model: VideoModel.unscoped(),
+                  required: true,
+                  where: {
+                    id: videoId
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      ],
+      transaction
+    }
+
+    return ActorModel.unscoped().findOne(query)
+  }
+
+  static isActorUrlExist (url: string) {
+    const query = {
+      raw: true,
+      where: {
+        url
+      }
+    }
+
+    return ActorModel.unscoped().findOne(query)
+      .then(a => !!a)
   }
 
   static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction) {
@@ -305,6 +357,29 @@ export class ActorModel extends Model<ActorModel> {
   }
 
   static loadByUrl (url: string, transaction?: Sequelize.Transaction) {
+    const query = {
+      where: {
+        url
+      },
+      transaction,
+      include: [
+        {
+          attributes: [ 'id' ],
+          model: AccountModel.unscoped(),
+          required: false
+        },
+        {
+          attributes: [ 'id' ],
+          model: VideoChannelModel.unscoped(),
+          required: false
+        }
+      ]
+    }
+
+    return ActorModel.unscoped().findOne(query)
+  }
+
+  static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Sequelize.Transaction) {
     const query = {
       where: {
         url
@@ -316,8 +391,7 @@ export class ActorModel extends Model<ActorModel> {
   }
 
   static incrementFollows (id: number, column: 'followersCount' | 'followingCount', by: number) {
-    // FIXME: typings
-    return (ActorModel as any).increment(column, {
+    return ActorModel.increment(column, {
       by,
       where: {
         id
@@ -337,6 +411,7 @@ export class ActorModel extends Model<ActorModel> {
       uuid: this.uuid,
       name: this.preferredUsername,
       host: this.getHost(),
+      hostRedundancyAllowed: this.getRedundancyAllowed(),
       followingCount: this.followingCount,
       followersCount: this.followersCount,
       avatar,
@@ -370,6 +445,7 @@ export class ActorModel extends Model<ActorModel> {
       id: this.url,
       following: this.getFollowingUrl(),
       followers: this.getFollowersUrl(),
+      playlists: this.getPlaylistsUrl(),
       inbox: this.inboxUrl,
       outbox: this.outboxUrl,
       preferredUsername: this.preferredUsername,
@@ -420,6 +496,10 @@ export class ActorModel extends Model<ActorModel> {
     return this.url + '/followers'
   }
 
+  getPlaylistsUrl () {
+    return this.url + '/playlists'
+  }
+
   getPublicKeyUrl () {
     return this.url + '#main-key'
   }
@@ -437,23 +517,22 @@ export class ActorModel extends Model<ActorModel> {
   }
 
   getHost () {
-    return this.Server ? this.Server.host : CONFIG.WEBSERVER.HOST
+    return this.Server ? this.Server.host : WEBSERVER.HOST
+  }
+
+  getRedundancyAllowed () {
+    return this.Server ? this.Server.redundancyAllowed : false
   }
 
   getAvatarUrl () {
     if (!this.avatarId) return undefined
 
-    return CONFIG.WEBSERVER.URL + this.Avatar.getWebserverPath()
+    return WEBSERVER.URL + this.Avatar.getWebserverPath()
   }
 
   isOutdated () {
     if (this.isOwned()) return false
 
-    const now = Date.now()
-    const createdAtTime = this.createdAt.getTime()
-    const updatedAtTime = this.updatedAt.getTime()
-
-    return (now - createdAtTime) > ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL &&
-      (now - updatedAtTime) > ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL
+    return isOutdated(this, ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL)
   }
 }