Split types and typings
[oweals/peertube.git] / server / models / account / account-blocklist.ts
1 import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
2 import { AccountModel } from './account'
3 import { getSort, searchAttribute } from '../utils'
4 import { AccountBlock } from '../../../shared/models/blocklist'
5 import { Op } from 'sequelize'
6 import * as Bluebird from 'bluebird'
7 import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models'
8 import { ActorModel } from '../activitypub/actor'
9 import { ServerModel } from '../server/server'
10
11 enum ScopeNames {
12   WITH_ACCOUNTS = 'WITH_ACCOUNTS'
13 }
14
15 @Scopes(() => ({
16   [ScopeNames.WITH_ACCOUNTS]: {
17     include: [
18       {
19         model: AccountModel,
20         required: true,
21         as: 'ByAccount'
22       },
23       {
24         model: AccountModel,
25         required: true,
26         as: 'BlockedAccount'
27       }
28     ]
29   }
30 }))
31
32 @Table({
33   tableName: 'accountBlocklist',
34   indexes: [
35     {
36       fields: [ 'accountId', 'targetAccountId' ],
37       unique: true
38     },
39     {
40       fields: [ 'targetAccountId' ]
41     }
42   ]
43 })
44 export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
45
46   @CreatedAt
47   createdAt: Date
48
49   @UpdatedAt
50   updatedAt: Date
51
52   @ForeignKey(() => AccountModel)
53   @Column
54   accountId: number
55
56   @BelongsTo(() => AccountModel, {
57     foreignKey: {
58       name: 'accountId',
59       allowNull: false
60     },
61     as: 'ByAccount',
62     onDelete: 'CASCADE'
63   })
64   ByAccount: AccountModel
65
66   @ForeignKey(() => AccountModel)
67   @Column
68   targetAccountId: number
69
70   @BelongsTo(() => AccountModel, {
71     foreignKey: {
72       name: 'targetAccountId',
73       allowNull: false
74     },
75     as: 'BlockedAccount',
76     onDelete: 'CASCADE'
77   })
78   BlockedAccount: AccountModel
79
80   static isAccountMutedByMulti (accountIds: number[], targetAccountId: number) {
81     const query = {
82       attributes: [ 'accountId', 'id' ],
83       where: {
84         accountId: {
85           [Op.in]: accountIds
86         },
87         targetAccountId
88       },
89       raw: true
90     }
91
92     return AccountBlocklistModel.unscoped()
93                                 .findAll(query)
94                                 .then(rows => {
95                                   const result: { [accountId: number]: boolean } = {}
96
97                                   for (const accountId of accountIds) {
98                                     result[accountId] = !!rows.find(r => r.accountId === accountId)
99                                   }
100
101                                   return result
102                                 })
103   }
104
105   static loadByAccountAndTarget (accountId: number, targetAccountId: number): Bluebird<MAccountBlocklist> {
106     const query = {
107       where: {
108         accountId,
109         targetAccountId
110       }
111     }
112
113     return AccountBlocklistModel.findOne(query)
114   }
115
116   static listForApi (parameters: {
117     start: number
118     count: number
119     sort: string
120     search?: string
121     accountId: number
122   }) {
123     const { start, count, sort, search, accountId } = parameters
124
125     const query = {
126       offset: start,
127       limit: count,
128       order: getSort(sort)
129     }
130
131     const where = {
132       accountId
133     }
134
135     if (search) {
136       Object.assign(where, {
137         [Op.or]: [
138           searchAttribute(search, '$BlockedAccount.name$'),
139           searchAttribute(search, '$BlockedAccount.Actor.url$')
140         ]
141       })
142     }
143
144     Object.assign(query, { where })
145
146     return AccountBlocklistModel
147       .scope([ ScopeNames.WITH_ACCOUNTS ])
148       .findAndCountAll<MAccountBlocklistAccounts>(query)
149       .then(({ rows, count }) => {
150         return { total: count, data: rows }
151       })
152   }
153
154   static listHandlesBlockedBy (accountIds: number[]): Bluebird<string[]> {
155     const query = {
156       attributes: [],
157       where: {
158         accountId: {
159           [Op.in]: accountIds
160         }
161       },
162       include: [
163         {
164           attributes: [ 'id' ],
165           model: AccountModel.unscoped(),
166           required: true,
167           as: 'BlockedAccount',
168           include: [
169             {
170               attributes: [ 'preferredUsername' ],
171               model: ActorModel.unscoped(),
172               required: true,
173               include: [
174                 {
175                   attributes: [ 'host' ],
176                   model: ServerModel.unscoped(),
177                   required: true
178                 }
179               ]
180             }
181           ]
182         }
183       ]
184     }
185
186     return AccountBlocklistModel.findAll(query)
187       .then(entries => entries.map(e => `${e.BlockedAccount.Actor.preferredUsername}@${e.BlockedAccount.Actor.Server.host}`))
188   }
189
190   toFormattedJSON (this: MAccountBlocklistFormattable): AccountBlock {
191     return {
192       byAccount: this.ByAccount.toFormattedJSON(),
193       blockedAccount: this.BlockedAccount.toFormattedJSON(),
194       createdAt: this.createdAt
195     }
196   }
197 }