]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-moderation/user-moderation-dropdown.component.ts
Merge branch 'release/3.1.0' into develop
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-moderation / user-moderation-dropdown.component.ts
1 import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild } from '@angular/core'
2 import { AuthService, ConfirmService, Notifier, ServerService, UserService } from '@app/core'
3 import { Account, DropdownAction } from '@app/shared/shared-main'
4 import { BulkRemoveCommentsOfBody, ServerConfig, User, UserRight } from '@shared/models'
5 import { BlocklistService } from './blocklist.service'
6 import { BulkService } from './bulk.service'
7 import { UserBanModalComponent } from './user-ban-modal.component'
8
9 @Component({
10 selector: 'my-user-moderation-dropdown',
11 templateUrl: './user-moderation-dropdown.component.html'
12 })
13 export class UserModerationDropdownComponent implements OnInit, OnChanges {
14 @ViewChild('userBanModal') userBanModal: UserBanModalComponent
15
16 @Input() user: User
17 @Input() account: Account
18 @Input() prependActions: DropdownAction<{ user: User, account: Account }>[]
19
20 @Input() buttonSize: 'normal' | 'small' = 'normal'
21 @Input() buttonStyled = true
22 @Input() placement = 'right-top right-bottom auto'
23 @Input() label: string
24 @Input() container: 'body' | undefined = undefined
25
26 @Output() userChanged = new EventEmitter()
27 @Output() userDeleted = new EventEmitter()
28
29 userActions: DropdownAction<{ user: User, account: Account }>[][] = []
30
31 private serverConfig: ServerConfig
32
33 constructor (
34 private authService: AuthService,
35 private notifier: Notifier,
36 private confirmService: ConfirmService,
37 private serverService: ServerService,
38 private userService: UserService,
39 private blocklistService: BlocklistService,
40 private bulkService: BulkService
41 ) { }
42
43 get requiresEmailVerification () {
44 return this.serverConfig.signup.requiresEmailVerification
45 }
46
47 ngOnInit (): void {
48 this.serverConfig = this.serverService.getTmpConfig()
49 this.serverService.getConfig()
50 .subscribe(config => this.serverConfig = config)
51 }
52
53 ngOnChanges () {
54 this.buildActions()
55 }
56
57 openBanUserModal (user: User) {
58 if (user.username === 'root') {
59 this.notifier.error($localize`You cannot ban root.`)
60 return
61 }
62
63 this.userBanModal.openModal(user)
64 }
65
66 onUserBanned () {
67 this.userChanged.emit()
68 }
69
70 async unbanUser (user: User) {
71 const res = await this.confirmService.confirm($localize`Do you really want to unban ${user.username}?`, $localize`Unban`)
72 if (res === false) return
73
74 this.userService.unbanUsers(user)
75 .subscribe(
76 () => {
77 this.notifier.success($localize`User ${user.username} unbanned.`)
78 this.userChanged.emit()
79 },
80
81 err => this.notifier.error(err.message)
82 )
83 }
84
85 async removeUser (user: User) {
86 if (user.username === 'root') {
87 this.notifier.error($localize`You cannot delete root.`)
88 return
89 }
90
91 const message = $localize`If you remove this user, you will not be able to create another with the same username!`
92 const res = await this.confirmService.confirm(message, $localize`Delete`)
93 if (res === false) return
94
95 this.userService.removeUser(user).subscribe(
96 () => {
97 this.notifier.success($localize`User ${user.username} deleted.`)
98 this.userDeleted.emit()
99 },
100
101 err => this.notifier.error(err.message)
102 )
103 }
104
105 setEmailAsVerified (user: User) {
106 this.userService.updateUser(user.id, { emailVerified: true }).subscribe(
107 () => {
108 this.notifier.success($localize`User ${user.username} email set as verified`)
109 this.userChanged.emit()
110 },
111
112 err => this.notifier.error(err.message)
113 )
114 }
115
116 blockAccountByUser (account: Account) {
117 this.blocklistService.blockAccountByUser(account)
118 .subscribe(
119 () => {
120 this.notifier.success($localize`Account ${account.nameWithHost} muted.`)
121
122 this.account.mutedByUser = true
123 this.userChanged.emit()
124 },
125
126 err => this.notifier.error(err.message)
127 )
128 }
129
130 unblockAccountByUser (account: Account) {
131 this.blocklistService.unblockAccountByUser(account)
132 .subscribe(
133 () => {
134 this.notifier.success($localize`Account ${account.nameWithHost} unmuted.`)
135
136 this.account.mutedByUser = false
137 this.userChanged.emit()
138 },
139
140 err => this.notifier.error(err.message)
141 )
142 }
143
144 blockServerByUser (host: string) {
145 this.blocklistService.blockServerByUser(host)
146 .subscribe(
147 () => {
148 this.notifier.success($localize`Instance ${host} muted.`)
149
150 this.account.mutedServerByUser = true
151 this.userChanged.emit()
152 },
153
154 err => this.notifier.error(err.message)
155 )
156 }
157
158 unblockServerByUser (host: string) {
159 this.blocklistService.unblockServerByUser(host)
160 .subscribe(
161 () => {
162 this.notifier.success($localize`Instance ${host} unmuted.`)
163
164 this.account.mutedServerByUser = false
165 this.userChanged.emit()
166 },
167
168 err => this.notifier.error(err.message)
169 )
170 }
171
172 blockAccountByInstance (account: Account) {
173 this.blocklistService.blockAccountByInstance(account)
174 .subscribe(
175 () => {
176 this.notifier.success($localize`Account ${account.nameWithHost} muted by the instance.`)
177
178 this.account.mutedByInstance = true
179 this.userChanged.emit()
180 },
181
182 err => this.notifier.error(err.message)
183 )
184 }
185
186 unblockAccountByInstance (account: Account) {
187 this.blocklistService.unblockAccountByInstance(account)
188 .subscribe(
189 () => {
190 this.notifier.success($localize`Account ${account.nameWithHost} unmuted by the instance.`)
191
192 this.account.mutedByInstance = false
193 this.userChanged.emit()
194 },
195
196 err => this.notifier.error(err.message)
197 )
198 }
199
200 blockServerByInstance (host: string) {
201 this.blocklistService.blockServerByInstance(host)
202 .subscribe(
203 () => {
204 this.notifier.success($localize`Instance ${host} muted by the instance.`)
205
206 this.account.mutedServerByInstance = true
207 this.userChanged.emit()
208 },
209
210 err => this.notifier.error(err.message)
211 )
212 }
213
214 unblockServerByInstance (host: string) {
215 this.blocklistService.unblockServerByInstance(host)
216 .subscribe(
217 () => {
218 this.notifier.success($localize`Instance ${host} unmuted by the instance.`)
219
220 this.account.mutedServerByInstance = false
221 this.userChanged.emit()
222 },
223
224 err => this.notifier.error(err.message)
225 )
226 }
227
228 async bulkRemoveCommentsOf (body: BulkRemoveCommentsOfBody) {
229 const message = $localize`Are you sure you want to remove all the comments of this account?`
230 const res = await this.confirmService.confirm(message, $localize`Delete account comments`)
231 if (res === false) return
232
233 this.bulkService.removeCommentsOf(body)
234 .subscribe(
235 () => {
236 this.notifier.success($localize`Will remove comments of this account (may take several minutes).`)
237 },
238
239 err => this.notifier.error(err.message)
240 )
241 }
242
243 getRouterUserEditLink (user: User) {
244 return [ '/admin', 'users', 'update', user.id ]
245 }
246
247 private buildActions () {
248 this.userActions = []
249
250 if (this.prependActions) {
251 this.userActions = [
252 this.prependActions
253 ]
254 }
255
256 if (this.authService.isLoggedIn()) {
257 const authUser = this.authService.getUser()
258
259 if (this.user && authUser.id === this.user.id) return
260
261 if (this.user && authUser.hasRight(UserRight.MANAGE_USERS) && authUser.canManage(this.user)) {
262 this.userActions.push([
263 {
264 label: $localize`Edit user`,
265 description: $localize`Change quota, role, and more.`,
266 linkBuilder: ({ user }) => this.getRouterUserEditLink(user)
267 },
268 {
269 label: $localize`Delete user`,
270 description: $localize`Videos will be deleted, comments will be tombstoned.`,
271 handler: ({ user }) => this.removeUser(user)
272 },
273 {
274 label: $localize`Ban`,
275 description: $localize`User won't be able to login anymore, but videos and comments will be kept as is.`,
276 handler: ({ user }) => this.openBanUserModal(user),
277 isDisplayed: ({ user }) => !user.blocked
278 },
279 {
280 label: $localize`Unban user`,
281 description: $localize`Allow the user to login and create videos/comments again`,
282 handler: ({ user }) => this.unbanUser(user),
283 isDisplayed: ({ user }) => user.blocked
284 },
285 {
286 label: $localize`Set Email as Verified`,
287 handler: ({ user }) => this.setEmailAsVerified(user),
288 isDisplayed: ({ user }) => this.requiresEmailVerification && !user.blocked && user.emailVerified === false
289 }
290 ])
291 }
292
293 // Actions on accounts/servers
294 if (this.account) {
295 // User actions
296 this.userActions.push([
297 {
298 label: $localize`Mute this account`,
299 description: $localize`Hide any content from that user from you.`,
300 isDisplayed: ({ account }) => account.mutedByUser === false,
301 handler: ({ account }) => this.blockAccountByUser(account)
302 },
303 {
304 label: $localize`Unmute this account`,
305 description: $localize`Show back content from that user for you.`,
306 isDisplayed: ({ account }) => account.mutedByUser === true,
307 handler: ({ account }) => this.unblockAccountByUser(account)
308 },
309 {
310 label: $localize`Mute the instance`,
311 description: $localize`Hide any content from that instance for you.`,
312 isDisplayed: ({ account }) => !account.userId && account.mutedServerByInstance === false,
313 handler: ({ account }) => this.blockServerByUser(account.host)
314 },
315 {
316 label: $localize`Unmute the instance`,
317 description: $localize`Show back content from that instance for you.`,
318 isDisplayed: ({ account }) => !account.userId && account.mutedServerByInstance === true,
319 handler: ({ account }) => this.unblockServerByUser(account.host)
320 },
321 {
322 label: $localize`Remove comments from your videos`,
323 description: $localize`Remove comments made by this account on your videos.`,
324 handler: ({ account }) => this.bulkRemoveCommentsOf({ accountName: account.nameWithHost, scope: 'my-videos' })
325 }
326 ])
327
328 let instanceActions: DropdownAction<{ user: User, account: Account }>[] = []
329
330 // Instance actions on account blocklists
331 if (authUser.hasRight(UserRight.MANAGE_ACCOUNTS_BLOCKLIST)) {
332 instanceActions = instanceActions.concat([
333 {
334 label: $localize`Mute this account by your instance`,
335 description: $localize`Hide any content from that user from you, your instance and its users.`,
336 isDisplayed: ({ account }) => account.mutedByInstance === false,
337 handler: ({ account }) => this.blockAccountByInstance(account)
338 },
339 {
340 label: $localize`Unmute this account by your instance`,
341 description: $localize`Show this user's content to the users of this instance again.`,
342 isDisplayed: ({ account }) => account.mutedByInstance === true,
343 handler: ({ account }) => this.unblockAccountByInstance(account)
344 }
345 ])
346 }
347
348 // Instance actions on server blocklists
349 if (authUser.hasRight(UserRight.MANAGE_SERVERS_BLOCKLIST)) {
350 instanceActions = instanceActions.concat([
351 {
352 label: $localize`Mute the instance by your instance`,
353 description: $localize`Hide any content from that instance from you, your instance and its users.`,
354 isDisplayed: ({ account }) => !account.userId && account.mutedServerByInstance === false,
355 handler: ({ account }) => this.blockServerByInstance(account.host)
356 },
357 {
358 label: $localize`Unmute the instance by your instance`,
359 description: $localize`Show back content from that instance for you, your instance and its users.`,
360 isDisplayed: ({ account }) => !account.userId && account.mutedServerByInstance === true,
361 handler: ({ account }) => this.unblockServerByInstance(account.host)
362 }
363 ])
364 }
365
366 if (authUser.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT)) {
367 instanceActions = instanceActions.concat([
368 {
369 label: $localize`Remove comments from your instance`,
370 description: $localize`Remove comments made by this account from your instance.`,
371 handler: ({ account }) => this.bulkRemoveCommentsOf({ accountName: account.nameWithHost, scope: 'instance' })
372 }
373 ])
374 }
375
376 if (instanceActions.length !== 0) {
377 this.userActions.push(instanceActions)
378 }
379 }
380 }
381 }
382 }