]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/models/account/account.ts
Fix error when creating a fresh database
[github/Chocobozzz/PeerTube.git] / server / models / account / account.ts
index daf8f47035c009a581496577bbe9a48183bcaf32..464105261a463bba2e58b03dae10cce89fc5ab29 100644 (file)
@@ -22,21 +22,18 @@ import {
 
   AccountMethods
 } from './account-interface'
-import LoadApplication = AccountMethods.LoadApplication
 import { sendDeleteAccount } from '../../lib/activitypub/send-request'
+import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants'
 
 let Account: Sequelize.Model<AccountInstance, AccountAttributes>
-let loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID
+let loadAccountByServerAndUUID: AccountMethods.LoadAccountByServerAndUUID
 let load: AccountMethods.Load
 let loadApplication: AccountMethods.LoadApplication
 let loadByUUID: AccountMethods.LoadByUUID
 let loadByUrl: AccountMethods.LoadByUrl
-let loadLocalAccountByNameAndPod: AccountMethods.LoadLocalAccountByNameAndPod
+let loadLocalByName: AccountMethods.LoadLocalByName
+let loadByNameAndHost: AccountMethods.LoadByNameAndHost
 let listOwned: AccountMethods.ListOwned
-let listFollowerUrlsForApi: AccountMethods.ListFollowerUrlsForApi
-let listFollowingUrlsForApi: AccountMethods.ListFollowingUrlsForApi
-let listFollowingForApi: AccountMethods.ListFollowingForApi
-let listFollowersForApi: AccountMethods.ListFollowersForApi
 let isOwned: AccountMethods.IsOwned
 let toActivityPubObject: AccountMethods.ToActivityPubObject
 let toFormattedJSON: AccountMethods.ToFormattedJSON
@@ -60,14 +57,14 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
         type: DataTypes.STRING,
         allowNull: false,
         validate: {
-          usernameValid: value => {
+          nameValid: value => {
             const res = isUserUsernameValid(value)
-            if (res === false) throw new Error('Username is not valid.')
+            if (res === false) throw new Error('Name is not valid.')
           }
         }
       },
       url: {
-        type: DataTypes.STRING,
+        type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max),
         allowNull: false,
         validate: {
           urlValid: value => {
@@ -77,7 +74,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
         }
       },
       publicKey: {
-        type: DataTypes.STRING,
+        type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.PUBLIC_KEY.max),
         allowNull: false,
         validate: {
           publicKeyValid: value => {
@@ -87,8 +84,8 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
         }
       },
       privateKey: {
-        type: DataTypes.STRING,
-        allowNull: false,
+        type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.PRIVATE_KEY.max),
+        allowNull: true,
         validate: {
           privateKeyValid: value => {
             const res = isAccountPrivateKeyValid(value)
@@ -110,14 +107,14 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
         type: DataTypes.INTEGER,
         allowNull: false,
         validate: {
-          followersCountValid: value => {
+          followingCountValid: value => {
             const res = isAccountFollowingCountValid(value)
             if (res === false) throw new Error('Following count is not valid.')
           }
         }
       },
       inboxUrl: {
-        type: DataTypes.STRING,
+        type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max),
         allowNull: false,
         validate: {
           inboxUrlValid: value => {
@@ -127,7 +124,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
         }
       },
       outboxUrl: {
-        type: DataTypes.STRING,
+        type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max),
         allowNull: false,
         validate: {
           outboxUrlValid: value => {
@@ -137,7 +134,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
         }
       },
       sharedInboxUrl: {
-        type: DataTypes.STRING,
+        type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max),
         allowNull: false,
         validate: {
           sharedInboxUrlValid: value => {
@@ -147,7 +144,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
         }
       },
       followersUrl: {
-        type: DataTypes.STRING,
+        type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max),
         allowNull: false,
         validate: {
           followersUrlValid: value => {
@@ -157,7 +154,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
         }
       },
       followingUrl: {
-        type: DataTypes.STRING,
+        type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max),
         allowNull: false,
         validate: {
           followingUrlValid: value => {
@@ -173,7 +170,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
           fields: [ 'name' ]
         },
         {
-          fields: [ 'podId' ]
+          fields: [ 'serverId' ]
         },
         {
           fields: [ 'userId' ],
@@ -184,7 +181,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
           unique: true
         },
         {
-          fields: [ 'name', 'podId' ],
+          fields: [ 'name', 'serverId', 'applicationId' ],
           unique: true
         }
       ],
@@ -194,16 +191,14 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
 
   const classMethods = [
     associate,
-    loadAccountByPodAndUUID,
+    loadAccountByServerAndUUID,
     loadApplication,
     load,
     loadByUUID,
-    loadLocalAccountByNameAndPod,
-    listOwned,
-    listFollowerUrlsForApi,
-    listFollowingUrlsForApi,
-    listFollowingForApi,
-    listFollowersForApi
+    loadByUrl,
+    loadLocalByName,
+    loadByNameAndHost,
+    listOwned
   ]
   const instanceMethods = [
     isOwned,
@@ -222,9 +217,9 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
 // ---------------------------------------------------------------------------
 
 function associate (models) {
-  Account.belongsTo(models.Pod, {
+  Account.belongsTo(models.Server, {
     foreignKey: {
-      name: 'podId',
+      name: 'serverId',
       allowNull: true
     },
     onDelete: 'cascade'
@@ -240,7 +235,7 @@ function associate (models) {
 
   Account.belongsTo(models.Application, {
     foreignKey: {
-      name: 'userId',
+      name: 'applicationId',
       allowNull: true
     },
     onDelete: 'cascade'
@@ -255,21 +250,19 @@ function associate (models) {
     hooks: true
   })
 
-  Account.hasMany(models.AccountFollower, {
+  Account.hasMany(models.AccountFollow, {
     foreignKey: {
       name: 'accountId',
       allowNull: false
     },
-    as: 'following',
     onDelete: 'cascade'
   })
 
-  Account.hasMany(models.AccountFollower, {
+  Account.hasMany(models.AccountFollow, {
     foreignKey: {
       name: 'targetAccountId',
       allowNull: false
     },
-    as: 'followers',
     onDelete: 'cascade'
   })
 }
@@ -283,17 +276,28 @@ function afterDestroy (account: AccountInstance) {
 }
 
 toFormattedJSON = function (this: AccountInstance) {
+  let host = CONFIG.WEBSERVER.HOST
+  let score: number
+
+  if (this.Server) {
+    host = this.Server.host
+    score = this.Server.score as number
+  }
+
   const json = {
     id: this.id,
-    host: this.Pod.host,
-    name: this.name
+    host,
+    score,
+    name: this.name,
+    createdAt: this.createdAt,
+    updatedAt: this.updatedAt
   }
 
   return json
 }
 
 toActivityPubObject = function (this: AccountInstance) {
-  const type = this.podId ? 'Application' as 'Application' : 'Person' as 'Person'
+  const type = this.serverId ? 'Application' as 'Application' : 'Person' as 'Person'
 
   const json = {
     type,
@@ -320,7 +324,7 @@ toActivityPubObject = function (this: AccountInstance) {
 }
 
 isOwned = function (this: AccountInstance) {
-  return this.podId === null
+  return this.serverId === null
 }
 
 getFollowerSharedInboxUrls = function (this: AccountInstance) {
@@ -328,7 +332,9 @@ getFollowerSharedInboxUrls = function (this: AccountInstance) {
     attributes: [ 'sharedInboxUrl' ],
     include: [
       {
-        model: Account['sequelize'].models.AccountFollower,
+        model: Account['sequelize'].models.AccountFollow,
+        required: true,
+        as: 'followers',
         where: {
           targetAccountId: this.id
         }
@@ -341,7 +347,7 @@ getFollowerSharedInboxUrls = function (this: AccountInstance) {
 }
 
 getFollowingUrl = function (this: AccountInstance) {
-  return this.url + '/followers'
+  return this.url + '/following'
 }
 
 getFollowersUrl = function (this: AccountInstance) {
@@ -357,88 +363,18 @@ getPublicKeyUrl = function (this: AccountInstance) {
 listOwned = function () {
   const query: Sequelize.FindOptions<AccountAttributes> = {
     where: {
-      podId: null
+      serverId: null
     }
   }
 
   return Account.findAll(query)
 }
 
-listFollowerUrlsForApi = function (id: number, start: number, count?: number) {
-  return createListFollowForApiQuery('followers', id, start, count)
-}
-
-listFollowingUrlsForApi = function (id: number, start: number, count?: number) {
-  return createListFollowForApiQuery('following', id, start, count)
-}
-
-listFollowingForApi = function (id: number, start: number, count: number, sort: string) {
-  const query = {
-    distinct: true,
-    offset: start,
-    limit: count,
-    order: [ getSort(sort) ],
-    include: [
-      {
-        model: Account['sequelize'].models.AccountFollow,
-        required: true,
-        as: 'following',
-        include: [
-          {
-            model: Account['sequelize'].models.Account,
-            as: 'following',
-            required: true,
-            include: [ Account['sequelize'].models.Pod ]
-          }
-        ]
-      }
-    ]
-  }
-
-  return Account.findAndCountAll(query).then(({ rows, count }) => {
-    return {
-      data: rows,
-      total: count
-    }
-  })
-}
-
-listFollowersForApi = function (id: number, start: number, count: number, sort: string) {
-  const query = {
-    distinct: true,
-    offset: start,
-    limit: count,
-    order: [ getSort(sort) ],
-    include: [
-      {
-        model: Account['sequelize'].models.AccountFollow,
-        required: true,
-        as: 'followers',
-        include: [
-          {
-            model: Account['sequelize'].models.Account,
-            as: 'followers',
-            required: true,
-            include: [ Account['sequelize'].models.Pod ]
-          }
-        ]
-      }
-    ]
-  }
-
-  return Account.findAndCountAll(query).then(({ rows, count }) => {
-    return {
-      data: rows,
-      total: count
-    }
-  })
-}
-
 loadApplication = function () {
   return Account.findOne({
     include: [
       {
-        model: Account['sequelize'].model.Application,
+        model: Account['sequelize'].models.Application,
         required: true
       }
     ]
@@ -459,17 +395,37 @@ loadByUUID = function (uuid: string) {
   return Account.findOne(query)
 }
 
-loadLocalAccountByNameAndPod = function (name: string, host: string) {
+loadLocalByName = function (name: string) {
   const query: Sequelize.FindOptions<AccountAttributes> = {
     where: {
       name,
-      userId: {
-        [Sequelize.Op.ne]: null
-      }
+      [Sequelize.Op.or]: [
+        {
+          userId: {
+            [Sequelize.Op.ne]: null
+          }
+        },
+        {
+          applicationId: {
+            [Sequelize.Op.ne]: null
+          }
+        }
+      ]
+    }
+  }
+
+  return Account.findOne(query)
+}
+
+loadByNameAndHost = function (name: string, host: string) {
+  const query: Sequelize.FindOptions<AccountAttributes> = {
+    where: {
+      name
     },
     include: [
       {
-        model: Account['sequelize'].models.Pod,
+        model: Account['sequelize'].models.Server,
+        required: true,
         where: {
           host
         }
@@ -480,20 +436,21 @@ loadLocalAccountByNameAndPod = function (name: string, host: string) {
   return Account.findOne(query)
 }
 
-loadByUrl = function (url: string) {
+loadByUrl = function (url: string, transaction?: Sequelize.Transaction) {
   const query: Sequelize.FindOptions<AccountAttributes> = {
     where: {
       url
-    }
+    },
+    transaction
   }
 
   return Account.findOne(query)
 }
 
-loadAccountByPodAndUUID = function (uuid: string, podId: number, transaction: Sequelize.Transaction) {
+loadAccountByServerAndUUID = function (uuid: string, serverId: number, transaction: Sequelize.Transaction) {
   const query: Sequelize.FindOptions<AccountAttributes> = {
     where: {
-      podId,
+      serverId,
       uuid
     },
     transaction
@@ -501,45 +458,3 @@ loadAccountByPodAndUUID = function (uuid: string, podId: number, transaction: Se
 
   return Account.find(query)
 }
-
-// ------------------------------ UTILS ------------------------------
-
-async function createListFollowForApiQuery (type: 'followers' | 'following', id: number, start: number, count?: number) {
-  let firstJoin: string
-  let secondJoin: string
-
-  if (type === 'followers') {
-    firstJoin = 'targetAccountId'
-    secondJoin = 'accountId'
-  } else {
-    firstJoin = 'accountId'
-    secondJoin = 'targetAccountId'
-  }
-
-  const selections = [ '"Followers"."url" AS "url"', 'COUNT(*) AS "total"' ]
-  const tasks: Promise<any>[] = []
-
-  for (const selection of selections) {
-    let query = 'SELECT ' + selection + ' FROM "Account" ' +
-      'INNER JOIN "AccountFollower" ON "AccountFollower"."' + firstJoin + '" = "Account"."id" ' +
-      'INNER JOIN "Account" AS "Follows" ON "Followers"."id" = "Follows"."' + secondJoin + '" ' +
-      'WHERE "Account"."id" = $id ' +
-      'LIMIT ' + start
-
-    if (count !== undefined) query += ', ' + count
-
-    const options = {
-      bind: { id },
-      type: Sequelize.QueryTypes.SELECT
-    }
-    tasks.push(Account['sequelize'].query(query, options))
-  }
-
-  const [ followers, [ { total } ]] = await Promise.all(tasks)
-  const urls: string[] = followers.map(f => f.url)
-
-  return {
-    data: urls,
-    total: parseInt(total, 10)
-  }
-}