diff options
Diffstat (limited to 'server/models/account/account-blocklist.ts')
-rw-r--r-- | server/models/account/account-blocklist.ts | 236 |
1 files changed, 0 insertions, 236 deletions
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts deleted file mode 100644 index f6212ff6e..000000000 --- a/server/models/account/account-blocklist.ts +++ /dev/null | |||
@@ -1,236 +0,0 @@ | |||
1 | import { FindOptions, Op, QueryTypes } from 'sequelize' | ||
2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | ||
3 | import { handlesToNameAndHost } from '@server/helpers/actors' | ||
4 | import { MAccountBlocklist, MAccountBlocklistFormattable } from '@server/types/models' | ||
5 | import { AttributesOnly } from '@shared/typescript-utils' | ||
6 | import { AccountBlock } from '../../../shared/models' | ||
7 | import { ActorModel } from '../actor/actor' | ||
8 | import { ServerModel } from '../server/server' | ||
9 | import { createSafeIn, getSort, searchAttribute } from '../shared' | ||
10 | import { AccountModel } from './account' | ||
11 | |||
12 | @Table({ | ||
13 | tableName: 'accountBlocklist', | ||
14 | indexes: [ | ||
15 | { | ||
16 | fields: [ 'accountId', 'targetAccountId' ], | ||
17 | unique: true | ||
18 | }, | ||
19 | { | ||
20 | fields: [ 'targetAccountId' ] | ||
21 | } | ||
22 | ] | ||
23 | }) | ||
24 | export class AccountBlocklistModel extends Model<Partial<AttributesOnly<AccountBlocklistModel>>> { | ||
25 | |||
26 | @CreatedAt | ||
27 | createdAt: Date | ||
28 | |||
29 | @UpdatedAt | ||
30 | updatedAt: Date | ||
31 | |||
32 | @ForeignKey(() => AccountModel) | ||
33 | @Column | ||
34 | accountId: number | ||
35 | |||
36 | @BelongsTo(() => AccountModel, { | ||
37 | foreignKey: { | ||
38 | name: 'accountId', | ||
39 | allowNull: false | ||
40 | }, | ||
41 | as: 'ByAccount', | ||
42 | onDelete: 'CASCADE' | ||
43 | }) | ||
44 | ByAccount: AccountModel | ||
45 | |||
46 | @ForeignKey(() => AccountModel) | ||
47 | @Column | ||
48 | targetAccountId: number | ||
49 | |||
50 | @BelongsTo(() => AccountModel, { | ||
51 | foreignKey: { | ||
52 | name: 'targetAccountId', | ||
53 | allowNull: false | ||
54 | }, | ||
55 | as: 'BlockedAccount', | ||
56 | onDelete: 'CASCADE' | ||
57 | }) | ||
58 | BlockedAccount: AccountModel | ||
59 | |||
60 | static isAccountMutedByAccounts (accountIds: number[], targetAccountId: number) { | ||
61 | const query = { | ||
62 | attributes: [ 'accountId', 'id' ], | ||
63 | where: { | ||
64 | accountId: { | ||
65 | [Op.in]: accountIds | ||
66 | }, | ||
67 | targetAccountId | ||
68 | }, | ||
69 | raw: true | ||
70 | } | ||
71 | |||
72 | return AccountBlocklistModel.unscoped() | ||
73 | .findAll(query) | ||
74 | .then(rows => { | ||
75 | const result: { [accountId: number]: boolean } = {} | ||
76 | |||
77 | for (const accountId of accountIds) { | ||
78 | result[accountId] = !!rows.find(r => r.accountId === accountId) | ||
79 | } | ||
80 | |||
81 | return result | ||
82 | }) | ||
83 | } | ||
84 | |||
85 | static loadByAccountAndTarget (accountId: number, targetAccountId: number): Promise<MAccountBlocklist> { | ||
86 | const query = { | ||
87 | where: { | ||
88 | accountId, | ||
89 | targetAccountId | ||
90 | } | ||
91 | } | ||
92 | |||
93 | return AccountBlocklistModel.findOne(query) | ||
94 | } | ||
95 | |||
96 | static listForApi (parameters: { | ||
97 | start: number | ||
98 | count: number | ||
99 | sort: string | ||
100 | search?: string | ||
101 | accountId: number | ||
102 | }) { | ||
103 | const { start, count, sort, search, accountId } = parameters | ||
104 | |||
105 | const getQuery = (forCount: boolean) => { | ||
106 | const query: FindOptions = { | ||
107 | offset: start, | ||
108 | limit: count, | ||
109 | order: getSort(sort), | ||
110 | where: { accountId } | ||
111 | } | ||
112 | |||
113 | if (search) { | ||
114 | Object.assign(query.where, { | ||
115 | [Op.or]: [ | ||
116 | searchAttribute(search, '$BlockedAccount.name$'), | ||
117 | searchAttribute(search, '$BlockedAccount.Actor.url$') | ||
118 | ] | ||
119 | }) | ||
120 | } | ||
121 | |||
122 | if (forCount !== true) { | ||
123 | query.include = [ | ||
124 | { | ||
125 | model: AccountModel, | ||
126 | required: true, | ||
127 | as: 'ByAccount' | ||
128 | }, | ||
129 | { | ||
130 | model: AccountModel, | ||
131 | required: true, | ||
132 | as: 'BlockedAccount' | ||
133 | } | ||
134 | ] | ||
135 | } else if (search) { // We need some joins when counting with search | ||
136 | query.include = [ | ||
137 | { | ||
138 | model: AccountModel.unscoped(), | ||
139 | required: true, | ||
140 | as: 'BlockedAccount', | ||
141 | include: [ | ||
142 | { | ||
143 | model: ActorModel.unscoped(), | ||
144 | required: true | ||
145 | } | ||
146 | ] | ||
147 | } | ||
148 | ] | ||
149 | } | ||
150 | |||
151 | return query | ||
152 | } | ||
153 | |||
154 | return Promise.all([ | ||
155 | AccountBlocklistModel.count(getQuery(true)), | ||
156 | AccountBlocklistModel.findAll(getQuery(false)) | ||
157 | ]).then(([ total, data ]) => ({ total, data })) | ||
158 | } | ||
159 | |||
160 | static listHandlesBlockedBy (accountIds: number[]): Promise<string[]> { | ||
161 | const query = { | ||
162 | attributes: [ 'id' ], | ||
163 | where: { | ||
164 | accountId: { | ||
165 | [Op.in]: accountIds | ||
166 | } | ||
167 | }, | ||
168 | include: [ | ||
169 | { | ||
170 | attributes: [ 'id' ], | ||
171 | model: AccountModel.unscoped(), | ||
172 | required: true, | ||
173 | as: 'BlockedAccount', | ||
174 | include: [ | ||
175 | { | ||
176 | attributes: [ 'preferredUsername' ], | ||
177 | model: ActorModel.unscoped(), | ||
178 | required: true, | ||
179 | include: [ | ||
180 | { | ||
181 | attributes: [ 'host' ], | ||
182 | model: ServerModel.unscoped(), | ||
183 | required: true | ||
184 | } | ||
185 | ] | ||
186 | } | ||
187 | ] | ||
188 | } | ||
189 | ] | ||
190 | } | ||
191 | |||
192 | return AccountBlocklistModel.findAll(query) | ||
193 | .then(entries => entries.map(e => `${e.BlockedAccount.Actor.preferredUsername}@${e.BlockedAccount.Actor.Server.host}`)) | ||
194 | } | ||
195 | |||
196 | static getBlockStatus (byAccountIds: number[], handles: string[]): Promise<{ name: string, host: string, accountId: number }[]> { | ||
197 | const sanitizedHandles = handlesToNameAndHost(handles) | ||
198 | |||
199 | const localHandles = sanitizedHandles.filter(h => !h.host) | ||
200 | .map(h => h.name) | ||
201 | |||
202 | const remoteHandles = sanitizedHandles.filter(h => !!h.host) | ||
203 | .map(h => ([ h.name, h.host ])) | ||
204 | |||
205 | const handlesWhere: string[] = [] | ||
206 | |||
207 | if (localHandles.length !== 0) { | ||
208 | handlesWhere.push(`("actor"."preferredUsername" IN (:localHandles) AND "server"."id" IS NULL)`) | ||
209 | } | ||
210 | |||
211 | if (remoteHandles.length !== 0) { | ||
212 | handlesWhere.push(`(("actor"."preferredUsername", "server"."host") IN (:remoteHandles))`) | ||
213 | } | ||
214 | |||
215 | const rawQuery = `SELECT "accountBlocklist"."accountId", "actor"."preferredUsername" AS "name", "server"."host" ` + | ||
216 | `FROM "accountBlocklist" ` + | ||
217 | `INNER JOIN "account" ON "account"."id" = "accountBlocklist"."targetAccountId" ` + | ||
218 | `INNER JOIN "actor" ON "actor"."id" = "account"."actorId" ` + | ||
219 | `LEFT JOIN "server" ON "server"."id" = "actor"."serverId" ` + | ||
220 | `WHERE "accountBlocklist"."accountId" IN (${createSafeIn(AccountBlocklistModel.sequelize, byAccountIds)}) ` + | ||
221 | `AND (${handlesWhere.join(' OR ')})` | ||
222 | |||
223 | return AccountBlocklistModel.sequelize.query(rawQuery, { | ||
224 | type: QueryTypes.SELECT as QueryTypes.SELECT, | ||
225 | replacements: { byAccountIds, localHandles, remoteHandles } | ||
226 | }) | ||
227 | } | ||
228 | |||
229 | toFormattedJSON (this: MAccountBlocklistFormattable): AccountBlock { | ||
230 | return { | ||
231 | byAccount: this.ByAccount.toFormattedJSON(), | ||
232 | blockedAccount: this.BlockedAccount.toFormattedJSON(), | ||
233 | createdAt: this.createdAt | ||
234 | } | ||
235 | } | ||
236 | } | ||