]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/+admin/overview/users/user-list/user-list.component.ts
Add ability to mute user when banning them
[github/Chocobozzz/PeerTube.git] / client / src / app / +admin / overview / users / user-list / user-list.component.ts
CommitLineData
f77eb73b 1import { SortMeta } from 'primeng/api'
2e46eb97 2import { Component, OnInit, ViewChild } from '@angular/core'
1fd61899 3import { ActivatedRoute, Router } from '@angular/router'
d92d070c 4import { AuthService, ConfirmService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
1fd61899
C
5import { AdvancedInputFilter } from '@app/shared/shared-forms'
6import { DropdownAction } from '@app/shared/shared-main'
67ed6552 7import { UserBanModalComponent } from '@app/shared/shared-moderation'
d92d070c 8import { UserAdminService } from '@app/shared/shared-users'
2989628b 9import { User, UserRole } from '@shared/models'
7da18e44 10
4f5d0459
RK
11type UserForList = User & {
12 rawVideoQuota: number
13 rawVideoQuotaUsed: number
14 rawVideoQuotaDaily: number
15 rawVideoQuotaUsedDaily: number
16}
17
7da18e44
C
18@Component({
19 selector: 'my-user-list',
ec8d8440
C
20 templateUrl: './user-list.component.html',
21 styleUrls: [ './user-list.component.scss' ]
7da18e44 22})
2e46eb97 23export class UserListComponent extends RestTable implements OnInit {
f36da21e 24 @ViewChild('userBanModal', { static: true }) userBanModal: UserBanModalComponent
791645e6 25
d592e0a9 26 users: User[] = []
1fd61899 27
d592e0a9 28 totalRecords = 0
ab998f7b 29 sort: SortMeta = { field: 'createdAt', order: 1 }
d592e0a9 30 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
1fd61899 31
bc99dfe5 32 highlightBannedUsers = false
141b177d 33
791645e6 34 selectedUsers: User[] = []
9b82d49d 35 bulkUserActions: DropdownAction<User[]>[][] = []
52c4976f 36 columns: { id: string, label: string }[]
791645e6 37
1fd61899
C
38 inputFilters: AdvancedInputFilter[] = [
39 {
978c87e7
C
40 title: $localize`Advanced filters`,
41 children: [
42 {
dd6d2a7c 43 value: 'banned:true',
978c87e7
C
44 label: $localize`Banned users`
45 }
46 ]
1fd61899
C
47 }
48 ]
49
2989628b
C
50 requiresEmailVerification = false
51
52c4976f 52 private _selectedColumns: string[]
ba430d75 53
df98563e 54 constructor (
5ed46c1b
C
55 protected route: ActivatedRoute,
56 protected router: Router,
f8b2c1b4 57 private notifier: Notifier,
5769e1db 58 private confirmService: ConfirmService,
fc2ec87a 59 private serverService: ServerService,
a95a4cc8 60 private auth: AuthService,
d92d070c 61 private userAdminService: UserAdminService
5ed46c1b 62 ) {
d592e0a9 63 super()
7da18e44
C
64 }
65
a95a4cc8
C
66 get authUser () {
67 return this.auth.getUser()
68 }
69
bc99dfe5
RK
70 get selectedColumns () {
71 return this._selectedColumns
72 }
73
52c4976f 74 set selectedColumns (val: string[]) {
bc99dfe5
RK
75 this._selectedColumns = val
76 }
77
ab998f7b 78 ngOnInit () {
ba430d75 79 this.serverService.getConfig()
2989628b 80 .subscribe(config => this.requiresEmailVerification = config.signup.requiresEmailVerification)
ba430d75 81
24b9417c 82 this.initialize()
8491293b 83
791645e6 84 this.bulkUserActions = [
9b82d49d
RK
85 [
86 {
66357162
C
87 label: $localize`Delete`,
88 description: $localize`Videos will be deleted, comments will be tombstoned.`,
9b82d49d
RK
89 handler: users => this.removeUsers(users),
90 isDisplayed: users => users.every(u => this.authUser.canManage(u))
91 },
92 {
66357162
C
93 label: $localize`Ban`,
94 description: $localize`User won't be able to login anymore, but videos and comments will be kept as is.`,
9b82d49d
RK
95 handler: users => this.openBanUserModal(users),
96 isDisplayed: users => users.every(u => this.authUser.canManage(u) && u.blocked === false)
97 },
98 {
66357162 99 label: $localize`Unban`,
9b82d49d
RK
100 handler: users => this.unbanUsers(users),
101 isDisplayed: users => users.every(u => this.authUser.canManage(u) && u.blocked === true)
a95a4cc8 102 }
9b82d49d
RK
103 ],
104 [
105 {
66357162 106 label: $localize`Set Email as Verified`,
9b82d49d
RK
107 handler: users => this.setEmailsAsVerified(users),
108 isDisplayed: users => {
109 return this.requiresEmailVerification &&
110 users.every(u => this.authUser.canManage(u) && !u.blocked && u.emailVerified === false)
111 }
112 }
113 ]
791645e6 114 ]
bc99dfe5
RK
115
116 this.columns = [
c3185413
C
117 { id: 'username', label: $localize`Username` },
118 { id: 'email', label: $localize`Email` },
119 { id: 'quota', label: $localize`Video quota` },
120 { id: 'role', label: $localize`Role` },
121 { id: 'createdAt', label: $localize`Created` }
bc99dfe5 122 ]
52c4976f
C
123
124 this.selectedColumns = this.columns.map(c => c.id)
125
c3185413
C
126 this.columns.push({ id: 'quotaDaily', label: $localize`Daily quota` })
127 this.columns.push({ id: 'pluginAuth', label: $localize`Auth plugin` })
128 this.columns.push({ id: 'lastLoginDate', label: $localize`Last login` })
141b177d
C
129 }
130
8e11a1b3
C
131 getIdentifier () {
132 return 'UserListComponent'
133 }
134
bc99dfe5
RK
135 getRoleClass (role: UserRole) {
136 switch (role) {
137 case UserRole.ADMINISTRATOR:
138 return 'badge-purple'
139 case UserRole.MODERATOR:
140 return 'badge-blue'
141 default:
142 return 'badge-yellow'
143 }
144 }
145
52c4976f
C
146 isSelected (id: string) {
147 return this.selectedColumns.find(c => c === id)
148 }
149
150 getColumn (id: string) {
151 return this.columns.find(c => c.id === id)
bc99dfe5
RK
152 }
153
4f5d0459 154 getUserVideoQuotaPercentage (user: UserForList) {
bc99dfe5
RK
155 return user.rawVideoQuotaUsed * 100 / user.rawVideoQuota
156 }
157
4f5d0459 158 getUserVideoQuotaDailyPercentage (user: UserForList) {
bc99dfe5
RK
159 return user.rawVideoQuotaUsedDaily * 100 / user.rawVideoQuotaDaily
160 }
161
791645e6
C
162 openBanUserModal (users: User[]) {
163 for (const user of users) {
164 if (user.username === 'root') {
66357162 165 this.notifier.error($localize`You cannot ban root.`)
791645e6
C
166 return
167 }
168 }
169
170 this.userBanModal.openModal(users)
171 }
172
2fbe7f19 173 onUserChanged () {
2e46eb97 174 this.reloadData()
791645e6
C
175 }
176
177 async unbanUsers (users: User[]) {
66357162 178 const res = await this.confirmService.confirm($localize`Do you really want to unban ${users.length} users?`, $localize`Unban`)
791645e6
C
179 if (res === false) return
180
d92d070c 181 this.userAdminService.unbanUsers(users)
1378c0d3
C
182 .subscribe({
183 next: () => {
66357162 184 this.notifier.success($localize`${users.length} users unbanned.`)
2e46eb97 185 this.reloadData()
791645e6
C
186 },
187
1378c0d3
C
188 error: err => this.notifier.error(err.message)
189 })
791645e6
C
190 }
191
192 async removeUsers (users: User[]) {
193 for (const user of users) {
194 if (user.username === 'root') {
66357162 195 this.notifier.error($localize`You cannot delete root.`)
791645e6
C
196 return
197 }
198 }
199
66357162
C
200 const message = $localize`If you remove these users, you will not be able to create others with the same username!`
201 const res = await this.confirmService.confirm(message, $localize`Delete`)
791645e6
C
202 if (res === false) return
203
d92d070c 204 this.userAdminService.removeUser(users)
1378c0d3
C
205 .subscribe({
206 next: () => {
207 this.notifier.success($localize`${users.length} users deleted.`)
208 this.reloadData()
209 },
791645e6 210
1378c0d3
C
211 error: err => this.notifier.error(err.message)
212 })
791645e6
C
213 }
214
98ab5dc8 215 setEmailsAsVerified (users: User[]) {
d92d070c 216 this.userAdminService.updateUsers(users, { emailVerified: true })
1378c0d3
C
217 .subscribe({
218 next: () => {
219 this.notifier.success($localize`${users.length} users email set as verified.`)
220 this.reloadData()
221 },
fc2ec87a 222
1378c0d3
C
223 error: err => this.notifier.error(err.message)
224 })
fc2ec87a
JM
225 }
226
791645e6
C
227 isInSelectionMode () {
228 return this.selectedUsers.length !== 0
229 }
dffd5d12 230
2e46eb97 231 protected reloadData () {
dffd5d12
B
232 this.selectedUsers = []
233
d92d070c 234 this.userAdminService.getUsers({
8491293b
RK
235 pagination: this.pagination,
236 sort: this.sort,
237 search: this.search
1378c0d3
C
238 }).subscribe({
239 next: resultList => {
8491293b
RK
240 this.users = resultList.data
241 this.totalRecords = resultList.total
242 },
f8b2c1b4 243
1378c0d3
C
244 error: err => this.notifier.error(err.message)
245 })
dffd5d12 246 }
7da18e44 247}