+
diff --git a/frontend/src/app/routes/settings/users/settings-users-edit/settings-users-edit.component.ts b/frontend/src/app/routes/settings/users/settings-users-edit/settings-users-edit.component.ts
index 290d1a7..9a57aee 100644
--- a/frontend/src/app/routes/settings/users/settings-users-edit/settings-users-edit.component.ts
+++ b/frontend/src/app/routes/settings/users/settings-users-edit/settings-users-edit.component.ts
@@ -3,6 +3,7 @@ import { Component, OnInit } from '@angular/core';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatChipInputEvent } from '@angular/material/chips';
import { ActivatedRoute, Router } from '@angular/router';
+import { UIFriendlyPermissions } from 'picsur-shared/dist/dto/permissions';
import { HasFailed } from 'picsur-shared/dist/types';
import { UpdateUserControl } from 'src/app/models/forms/updateuser.control';
import { SnackBarType } from 'src/app/models/snack-bar-type';
@@ -77,6 +78,12 @@ export class SettingsUsersEditComponent implements OnInit {
this.model.putAllRoles(roles);
}
+ getEffectivePermissions() {
+ return this.model
+ .getEffectivePermissions()
+ .map((permission) => UIFriendlyPermissions[permission]);
+ }
+
removeRole(role: string) {
this.model.removeRole(role);
}
diff --git a/frontend/src/app/routes/settings/users/settings-users.component.html b/frontend/src/app/routes/settings/users/settings-users.component.html
index b19b086..5f6b7bc 100644
--- a/frontend/src/app/routes/settings/users/settings-users.component.html
+++ b/frontend/src/app/routes/settings/users/settings-users.component.html
@@ -1,22 +1,31 @@
Users
-
-
Username
{{ user.username }}
+
+ Roles
+
+
+
+ {{ role }}
+
+
+
+
+
Actions
+
diff --git a/frontend/src/app/routes/settings/users/settings-users.component.scss b/frontend/src/app/routes/settings/users/settings-users.component.scss
index e187b16..0a95fb8 100644
--- a/frontend/src/app/routes/settings/users/settings-users.component.scss
+++ b/frontend/src/app/routes/settings/users/settings-users.component.scss
@@ -6,3 +6,6 @@ mat-table {
justify-content: end;
}
+.icon-red {
+ color: #F44336;
+}
diff --git a/frontend/src/app/routes/settings/users/settings-users.component.ts b/frontend/src/app/routes/settings/users/settings-users.component.ts
index e3ee7a5..c3efc60 100644
--- a/frontend/src/app/routes/settings/users/settings-users.component.ts
+++ b/frontend/src/app/routes/settings/users/settings-users.component.ts
@@ -1,4 +1,5 @@
import { Component, OnInit, ViewChild } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { Router } from '@angular/router';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
@@ -8,13 +9,18 @@ import { BehaviorSubject, Subject, throttleTime } from 'rxjs';
import { SnackBarType } from 'src/app/models/snack-bar-type';
import { UserManageService } from 'src/app/services/api/usermanage.service';
import { UtilService } from 'src/app/util/util.service';
+import { DeleteConfirmDialogComponent } from './delete-confirm-dialog/delete-confirm-dialog.component';
@Component({
templateUrl: './settings-users.component.html',
styleUrls: ['./settings-users.component.scss'],
})
export class SettingsUsersComponent implements OnInit {
- public readonly displayedColumns: string[] = [/*'id',*/ 'username', 'actions'];
+ public readonly displayedColumns: string[] = [
+ 'username',
+ 'roles',
+ 'actions',
+ ];
public readonly pageSizeOptions: number[] = [5, 10, 25, 100];
public readonly startingPageSize = this.pageSizeOptions[2];
@@ -26,7 +32,8 @@ export class SettingsUsersComponent implements OnInit {
constructor(
private userManageService: UserManageService,
private utilService: UtilService,
- private router: Router
+ private router: Router,
+ private dialog: MatDialog
) {}
async ngOnInit() {
@@ -34,12 +41,28 @@ export class SettingsUsersComponent implements OnInit {
this.fetchUsers(this.startingPageSize, 0);
}
+ public addUser() {
+ this.router.navigate(['/settings/users/add']);
+ }
+
public editUser(user: EUser) {
this.router.navigate(['/settings/users/edit', user.username]);
}
- public addUser() {
- this.router.navigate(['/settings/users/add']);
+ public deleteUser(user: EUser) {
+ const dialogRef = this.dialog.open(DeleteConfirmDialogComponent, {
+ data: user,
+ });
+
+ dialogRef.afterClosed().subscribe(async () => {
+ const page = this.paginator.pageIndex;
+ const pageSize = this.paginator.pageSize;
+
+ const success = await this.fetchUsers(pageSize, page);
+ if (!success) {
+ this.paginator.firstPage();
+ }
+ });
}
@AutoUnsubscribe()
diff --git a/frontend/src/app/routes/settings/users/settings-users.module.ts b/frontend/src/app/routes/settings/users/settings-users.module.ts
index 63f2ad0..f90e95c 100644
--- a/frontend/src/app/routes/settings/users/settings-users.module.ts
+++ b/frontend/src/app/routes/settings/users/settings-users.module.ts
@@ -4,17 +4,23 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatChipsModule } from '@angular/material/chips';
+import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatTableModule } from '@angular/material/table';
+import { DeleteConfirmDialogComponent } from './delete-confirm-dialog/delete-confirm-dialog.component';
import { SettingsUsersEditComponent } from './settings-users-edit/settings-users-edit.component';
import { SettingsUsersComponent } from './settings-users.component';
import { SettingsUsersRoutingModule } from './settings-users.routing.module';
@NgModule({
- declarations: [SettingsUsersComponent, SettingsUsersEditComponent],
+ declarations: [
+ SettingsUsersComponent,
+ SettingsUsersEditComponent,
+ DeleteConfirmDialogComponent,
+ ],
imports: [
CommonModule,
SettingsUsersRoutingModule,
@@ -26,6 +32,7 @@ import { SettingsUsersRoutingModule } from './settings-users.routing.module';
MatInputModule,
MatChipsModule,
MatAutocompleteModule,
+ MatDialogModule,
FormsModule,
ReactiveFormsModule,
],
diff --git a/frontend/src/app/routes/user/login/login.component.html b/frontend/src/app/routes/user/login/login.component.html
index bbc3583..fa1eae2 100644
--- a/frontend/src/app/routes/user/login/login.component.html
+++ b/frontend/src/app/routes/user/login/login.component.html
@@ -19,9 +19,9 @@
name="username"
required
/>
- {{
- model.usernameError
- }}
+
+ {{ model.usernameError }}
+
@@ -34,9 +34,9 @@
name="password"
required
/>
- {{
- model.passwordError
- }}
+
+ {{ model.passwordError }}
+
diff --git a/frontend/src/app/routes/user/register/register.component.html b/frontend/src/app/routes/user/register/register.component.html
index eccda54..df13d6e 100644
--- a/frontend/src/app/routes/user/register/register.component.html
+++ b/frontend/src/app/routes/user/register/register.component.html
@@ -17,9 +17,9 @@
name="username"
required
/>
- {{
- model.usernameError
- }}
+
+ {{ model.usernameError }}
+
@@ -32,9 +32,9 @@
name="password"
required
/>
- {{
- model.passwordError
- }}
+
+ {{ model.passwordError }}
+
@@ -47,9 +47,9 @@
name="confirmpassword"
required
/>
- {{
- model.passwordConfirmError
- }}
+
+ {{ model.passwordConfirmError }}
+
diff --git a/frontend/src/app/services/api/usermanage.service.ts b/frontend/src/app/services/api/usermanage.service.ts
index 22fc10b..691570b 100644
--- a/frontend/src/app/services/api/usermanage.service.ts
+++ b/frontend/src/app/services/api/usermanage.service.ts
@@ -2,6 +2,8 @@ import { Injectable } from '@angular/core';
import {
UserCreateRequest,
UserCreateResponse,
+ UserDeleteRequest,
+ UserDeleteResponse,
UserInfoRequest,
UserInfoResponse,
UserListRequest,
@@ -76,4 +78,19 @@ export class UserManageService {
return result;
}
+
+ public async deleteUser(username: string): AsyncFailable {
+ const body = {
+ username,
+ };
+
+ const result = await this.apiService.post(
+ UserDeleteRequest,
+ UserDeleteResponse,
+ '/api/user/delete',
+ body
+ );
+
+ return result;
+ }
}
diff --git a/shared/src/dto/permissions.ts b/shared/src/dto/permissions.ts
index 0d78e73..12fa406 100644
--- a/shared/src/dto/permissions.ts
+++ b/shared/src/dto/permissions.ts
@@ -27,3 +27,20 @@ export const AdminDashboardPermissions: Permissions = [
Permission.RoleManage,
Permission.SysPrefManage,
];
+
+export const UIFriendlyPermissions: {
+ [key in Permission]: string;
+} = {
+ [Permission.ImageView]: 'View images',
+ [Permission.ImageUpload]: 'Upload images',
+
+ [Permission.UserLogin]: 'Login',
+ [Permission.UserMe]: 'View own user details',
+ [Permission.UserRegister]: 'Register',
+
+ [Permission.Settings]: 'View available settings',
+
+ [Permission.UserManage]: 'Manage users',
+ [Permission.RoleManage]: 'Manage roles',
+ [Permission.SysPrefManage]: 'Manage system preferences',
+};
diff --git a/yarn.lock b/yarn.lock
index 89ff422..d2c0b87 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5499,17 +5499,7 @@ minimatch@^3.0.4:
dependencies:
brace-expansion "^1.1.7"
-minimist@1.2.5:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
- integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-
-minimist@^1.2.0, minimist@^1.2.6:
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
- integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
-
-"minimist@npm:minimist-lite":
+minimist@1.2.5, minimist@^1.2.0, minimist@^1.2.6, "minimist@npm:minimist-lite":
version "2.2.1"
resolved "https://registry.yarnpkg.com/minimist-lite/-/minimist-lite-2.2.1.tgz#abb71db2c9b454d7cf4496868c03e9802de9934d"
integrity sha512-RSrWIRWGYoM2TDe102s7aIyeSipXMIXKb1fSHYx1tAbxAV0z4g2xR6ra3oPzkTqFb0EIUz1H3A/qvYYeDd+/qQ==