Admin.deleteUser
This commit is contained in:
parent
f7af71d52b
commit
f47d30a4c8
@ -7,6 +7,7 @@ export class UserPrivate extends UserPublic {
|
|||||||
readonly privateUuid: string,
|
readonly privateUuid: string,
|
||||||
publicUuid: string,
|
publicUuid: string,
|
||||||
readonly created: Date,
|
readonly created: Date,
|
||||||
|
readonly lastAccess: Date,
|
||||||
name: string,
|
name: string,
|
||||||
readonly password: boolean,
|
readonly password: boolean,
|
||||||
readonly email: string,
|
readonly email: string,
|
||||||
@ -21,6 +22,7 @@ export class UserPrivate extends UserPublic {
|
|||||||
validateString(json['privateUuid']),
|
validateString(json['privateUuid']),
|
||||||
validateString(json['publicUuid']),
|
validateString(json['publicUuid']),
|
||||||
validateDate(json['created']),
|
validateDate(json['created']),
|
||||||
|
validateDate(json['lastAccess']),
|
||||||
validateString(json['name']),
|
validateString(json['name']),
|
||||||
validateBoolean(json['password']),
|
validateBoolean(json['password']),
|
||||||
validateString(json['email']),
|
validateString(json['email']),
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import {GroupLeftEvent} from "../group/events/GroupLeftEvent";
|
|||||||
import {UserLogoutEvent} from "./events/UserLogoutEvent";
|
import {UserLogoutEvent} from "./events/UserLogoutEvent";
|
||||||
import {validateBoolean} from "../common/validators";
|
import {validateBoolean} from "../common/validators";
|
||||||
import {UserLoginRequest} from "./requests/UserLoginRequest";
|
import {UserLoginRequest} from "./requests/UserLoginRequest";
|
||||||
|
import {Page} from "../common/Page";
|
||||||
|
|
||||||
function userPushMessageFromJson(json: any): object {
|
function userPushMessageFromJson(json: any): object {
|
||||||
const type = json['_type_'];
|
const type = json['_type_'];
|
||||||
@ -143,4 +144,14 @@ export class UserService {
|
|||||||
this.router.navigate(['Profile']);
|
this.router.navigate(['Profile']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adminPage(pageIndex: number, pageSize: number, next: Next<Page<UserPrivate>>) {
|
||||||
|
this.api.postPage(['User', 'Admin', 'page'], {pageIndex: pageIndex, pageSize: pageSize, orders: [{property: 'lastAccess', direction: 'ASC'}]}, UserPrivate.fromJson, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
adminDelete(user: UserPrivate, next?: Next<void>) {
|
||||||
|
if (confirm("Benutzer \"" + user.name + "\" wirklich löschen?")) {
|
||||||
|
this.api.postNone(['User', 'Admin', 'delete'], user.privateUuid, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import {GroupComponent} from "./pages/group/group/group.component";
|
|||||||
import {NumbersComponent} from "./pages/tools/numbers/numbers.component";
|
import {NumbersComponent} from "./pages/tools/numbers/numbers.component";
|
||||||
import {EmailConfirmationComponent} from "./pages/email-confirmation/email-confirmation.component";
|
import {EmailConfirmationComponent} from "./pages/email-confirmation/email-confirmation.component";
|
||||||
import {LoginComponent} from "./pages/login/login.component";
|
import {LoginComponent} from "./pages/login/login.component";
|
||||||
|
import {AdminComponent} from "./pages/admin/admin.component";
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{path: 'SolarSystemPrintout', component: SolarSystemPrintoutComponent},
|
{path: 'SolarSystemPrintout', component: SolarSystemPrintoutComponent},
|
||||||
@ -27,6 +28,8 @@ export const routes: Routes = [
|
|||||||
{path: 'Profile', component: ProfileComponent},
|
{path: 'Profile', component: ProfileComponent},
|
||||||
{path: 'emailConfirmation/:emailConfirmation', component: EmailConfirmationComponent},
|
{path: 'emailConfirmation/:emailConfirmation', component: EmailConfirmationComponent},
|
||||||
|
|
||||||
|
{path: 'Admin', component: AdminComponent},
|
||||||
|
|
||||||
// fallback
|
// fallback
|
||||||
{path: '**', redirectTo: '/SolarSystem'},
|
{path: '**', redirectTo: '/SolarSystem'},
|
||||||
];
|
];
|
||||||
|
|||||||
27
src/main/angular/src/app/pages/admin/admin.component.html
Normal file
27
src/main/angular/src/app/pages/admin/admin.component.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<div class="tileContainer">
|
||||||
|
<div class="tile">
|
||||||
|
<div class="tileInner">
|
||||||
|
<div class="tileTitle">
|
||||||
|
Benutzer
|
||||||
|
</div>
|
||||||
|
<div class="tileContent">
|
||||||
|
<app-pagination [page]="page" (goto)="goto($event)"></app-pagination>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Benutzername</th>
|
||||||
|
<th>Zuletzt</th>
|
||||||
|
<th>Aktion</th>
|
||||||
|
</tr>
|
||||||
|
<tr *ngFor="let user of page.content">
|
||||||
|
<td>{{ user.name }}</td>
|
||||||
|
<td>{{ user.lastAccess | relative:now }}</td>
|
||||||
|
<td class="buttons">
|
||||||
|
<div class="button buttonDelete" (click)="userService.adminDelete(user)">Löschen</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<app-pagination [page]="page" (goto)="goto($event)"></app-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
42
src/main/angular/src/app/pages/admin/admin.component.ts
Normal file
42
src/main/angular/src/app/pages/admin/admin.component.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {NgForOf} from "@angular/common";
|
||||||
|
import {Page} from "../../api/common/Page";
|
||||||
|
import {PaginationComponent} from "../../shared/pagination/pagination.component";
|
||||||
|
import {UserService} from "../../api/User/user.service";
|
||||||
|
import {UserPrivate} from "../../api/User/UserPrivate";
|
||||||
|
import {RelativePipe} from "../../shared/relative.pipe";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-admin',
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
NgForOf,
|
||||||
|
PaginationComponent,
|
||||||
|
RelativePipe
|
||||||
|
],
|
||||||
|
templateUrl: './admin.component.html',
|
||||||
|
styleUrl: './admin.component.less'
|
||||||
|
})
|
||||||
|
export class AdminComponent implements OnInit {
|
||||||
|
|
||||||
|
private readonly PER_PAGE: number = 20;
|
||||||
|
|
||||||
|
protected page: Page<UserPrivate> = Page.EMPTY;
|
||||||
|
|
||||||
|
protected now: Date = new Date();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected readonly userService: UserService,
|
||||||
|
) {
|
||||||
|
// -
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.goto(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto(pageIndex: number) {
|
||||||
|
this.userService.adminPage(pageIndex, this.PER_PAGE, page => this.page = page);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<div class="pagination">
|
||||||
|
<div class="number" *ngFor="let number of numbers" (click)="goto.emit(number)" [class.currentPage]="number === page.number">
|
||||||
|
{{ number + 1 }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
@import "../../../styles/config";
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
|
||||||
|
.number {
|
||||||
|
float: left;
|
||||||
|
padding: @halfSpace;
|
||||||
|
margin: @halfSpace;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.currentPage {
|
||||||
|
color: dodgerblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import {Component, EventEmitter, Input, Output} from '@angular/core';
|
||||||
|
import {Page} from '../../api/common/Page';
|
||||||
|
import {NgForOf, NgIf} from "@angular/common";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-pagination',
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
NgForOf,
|
||||||
|
NgIf
|
||||||
|
],
|
||||||
|
templateUrl: './pagination.component.html',
|
||||||
|
styleUrl: './pagination.component.less'
|
||||||
|
})
|
||||||
|
export class PaginationComponent {
|
||||||
|
|
||||||
|
_page: Page<any> = Page.EMPTY;
|
||||||
|
|
||||||
|
protected numbers: number[] = [];
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
readonly goto: EventEmitter<number> = new EventEmitter<number>();
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set page(page: Page<any>) {
|
||||||
|
this._page = page;
|
||||||
|
this.numbers = [...Array(this.page.totalPages).keys()];
|
||||||
|
}
|
||||||
|
|
||||||
|
get page(): Page<any> {
|
||||||
|
return this._page;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.tools.email;
|
package de.ph87.tools.email;
|
||||||
|
|
||||||
|
import de.ph87.tools.user.User;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@ -8,6 +9,7 @@ import org.springframework.data.repository.ListCrudRepository;
|
|||||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface EmailRepository extends ListCrudRepository<Email, String>, PagingAndSortingRepository<Email, String> {
|
public interface EmailRepository extends ListCrudRepository<Email, String>, PagingAndSortingRepository<Email, String> {
|
||||||
|
|
||||||
@ -15,4 +17,7 @@ public interface EmailRepository extends ListCrudRepository<Email, String>, Pagi
|
|||||||
@Query("select e from Email e where e.sent is null and (e.tried is null or e.tried <= :earliest) and e.tries < 5")
|
@Query("select e from Email e where e.sent is null and (e.tried is null or e.tried <= :earliest) and e.tries < 5")
|
||||||
Page<Email> findNextToSend(@NonNull final ZonedDateTime earliest, @NonNull Pageable pageable);
|
Page<Email> findNextToSend(@NonNull final ZonedDateTime earliest, @NonNull Pageable pageable);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
List<Email> findAllByUser(@NonNull User user);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,4 +80,11 @@ public class EmailService {
|
|||||||
.replaceAll("%EMAIL_CONFIRMATION%", user.getEmailConfirmation());
|
.replaceAll("%EMAIL_CONFIRMATION%", user.getEmailConfirmation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteAllByUser(@NonNull final User user) {
|
||||||
|
emailRepository.findAllByUser(user).forEach(email -> {
|
||||||
|
emailRepository.delete(email);
|
||||||
|
log.info("Email deleted: {}", email);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public class Group extends GroupAbstract implements IWebSocketMessage {
|
|||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private GroupUuid _uuid;
|
private GroupUuid _uuid;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package de.ph87.tools.group;
|
package de.ph87.tools.group;
|
||||||
|
|
||||||
import de.ph87.tools.group.dto.GroupDto;
|
import de.ph87.tools.group.dto.GroupDto;
|
||||||
|
import de.ph87.tools.user.User;
|
||||||
import de.ph87.tools.user.UserPublicDto;
|
import de.ph87.tools.user.UserPublicDto;
|
||||||
import de.ph87.tools.user.push.UserPushService;
|
import de.ph87.tools.user.push.UserPushService;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
@ -20,6 +21,8 @@ public class GroupMapper {
|
|||||||
|
|
||||||
private final UserPushService userPushService;
|
private final UserPushService userPushService;
|
||||||
|
|
||||||
|
private final GroupRepository groupRepository;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public GroupDto toDto(@NonNull final Group group) {
|
public GroupDto toDto(@NonNull final Group group) {
|
||||||
final UserPublicDto owner = new UserPublicDto(group.getOwner());
|
final UserPublicDto owner = new UserPublicDto(group.getOwner());
|
||||||
@ -35,4 +38,8 @@ public class GroupMapper {
|
|||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void pushAllByUser(@NonNull final User user) {
|
||||||
|
groupRepository.findAllByUsersContains(user).forEach(this::push);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import de.ph87.tools.user.User;
|
|||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.springframework.data.repository.ListCrudRepository;
|
import org.springframework.data.repository.ListCrudRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -12,6 +13,9 @@ public interface GroupRepository extends ListCrudRepository<Group, String> {
|
|||||||
@NonNull
|
@NonNull
|
||||||
Optional<Group> findByUuid(@NonNull String uuid);
|
Optional<Group> findByUuid(@NonNull String uuid);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
List<Group> findAllByOwner(@NonNull User user);
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
Set<Group> findAllByUsersContains(@NonNull User user);
|
Set<Group> findAllByUsersContains(@NonNull User user);
|
||||||
|
|
||||||
|
|||||||
@ -22,8 +22,6 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -62,7 +60,7 @@ public class GroupMemberService {
|
|||||||
// owner cannot remove itself from group
|
// owner cannot remove itself from group
|
||||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
_remove_user_from_group_unchecked(group, user, (g, u) -> log.info("User left Group: user={}, group={}", u, g));
|
_remove_user_from_group_unchecked(group, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -74,11 +72,11 @@ public class GroupMemberService {
|
|||||||
return groupMapper.push(group);
|
return groupMapper.push(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void _remove_user_from_group_unchecked(@NonNull final Group group, @NonNull final User user, @NonNull final BiConsumer<Group, User> beforePush) {
|
public void _remove_user_from_group_unchecked(@NonNull final Group group, @NonNull final User user) {
|
||||||
group.getUsers().remove(user);
|
group.getUsers().remove(user);
|
||||||
group.touch();
|
group.touch();
|
||||||
user.touch();
|
user.touch();
|
||||||
beforePush.accept(group, user);
|
log.info("User left Group: user={}, group={}", user, group);
|
||||||
userPushService.push(user, new GroupLeftEvent(group));
|
userPushService.push(user, new GroupLeftEvent(group));
|
||||||
groupMapper.push(group);
|
groupMapper.push(group);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,8 +29,6 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -69,12 +67,12 @@ public class GroupOwnerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void kick(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
|
public void kick(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
|
||||||
final OwnerRemoveResult result = _removeUser(privateUuid, request, (group, user) -> log.info("User kicked out of group: user={}, group={}", user, group));
|
final OwnerRemoveResult result = _removeUser(privateUuid, request);
|
||||||
groupMapper.push(result.group);
|
groupMapper.push(result.group);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ban(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
|
public void ban(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
|
||||||
final OwnerRemoveResult result = _removeUser(privateUuid, request, (group, user) -> log.info("User banned from group: user={}, group={}", user, group));
|
final OwnerRemoveResult result = _removeUser(privateUuid, request);
|
||||||
result.group.getBanned().add(result.kicked);
|
result.group.getBanned().add(result.kicked);
|
||||||
groupMapper.push(result.group);
|
groupMapper.push(result.group);
|
||||||
}
|
}
|
||||||
@ -114,14 +112,14 @@ public class GroupOwnerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private OwnerRemoveResult _removeUser(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request, @NonNull final BiConsumer<Group, User> beforePush) {
|
private OwnerRemoveResult _removeUser(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
|
||||||
final GroupAccess access = groupAccessService.ownerAccess(privateUuid, request.groupUuid);
|
final GroupAccess access = groupAccessService.ownerAccess(privateUuid, request.groupUuid);
|
||||||
final User user = access.group.getUsers().stream().filter(u -> u.getPublicUuid().equals(request.userPublicUuid)).findFirst().orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
|
final User user = access.group.getUsers().stream().filter(u -> u.getPublicUuid().equals(request.userPublicUuid)).findFirst().orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
|
||||||
if (user.equals(access.principal)) {
|
if (user.equals(access.principal)) {
|
||||||
// owner cannot kick itself from group
|
// owner cannot kick itself from group
|
||||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
groupMemberService._remove_user_from_group_unchecked(access.group, user, beforePush);
|
groupMemberService._remove_user_from_group_unchecked(access.group, user);
|
||||||
return new OwnerRemoveResult(access, user);
|
return new OwnerRemoveResult(access, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ public class Numbers extends NumbersAbstract {
|
|||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private NumbersUuid _uuid;
|
private NumbersUuid _uuid;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
package de.ph87.tools.tools.numbers;
|
package de.ph87.tools.tools.numbers;
|
||||||
|
|
||||||
import de.ph87.tools.group.Group;
|
import de.ph87.tools.group.Group;
|
||||||
|
import de.ph87.tools.user.User;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.repository.ListCrudRepository;
|
import org.springframework.data.repository.ListCrudRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface NumbersRepository extends ListCrudRepository<Numbers, String> {
|
public interface NumbersRepository extends ListCrudRepository<Numbers, String> {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -13,4 +16,7 @@ public interface NumbersRepository extends ListCrudRepository<Numbers, String> {
|
|||||||
|
|
||||||
void deleteAllByGroup(@NonNull Group group);
|
void deleteAllByGroup(@NonNull Group group);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
List<Numbers> findAllByLotsUser(@NonNull User user);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ public class User extends UserPublicAbstract {
|
|||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private UserPublicUuid _publicUuid;
|
private UserPublicUuid _publicUuid;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -41,6 +42,7 @@ public class User extends UserPublicAbstract {
|
|||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private UserPrivateUuid _privateUuid;
|
private UserPrivateUuid _privateUuid;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
@ -35,6 +35,9 @@ public class UserPrivateDto extends UserPublicAbstract {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public final ZonedDateTime created;
|
public final ZonedDateTime created;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final ZonedDateTime lastAccess;
|
||||||
|
|
||||||
private final boolean password;
|
private final boolean password;
|
||||||
|
|
||||||
private final String email;
|
private final String email;
|
||||||
@ -48,6 +51,7 @@ public class UserPrivateDto extends UserPublicAbstract {
|
|||||||
this.privateUuid = user.getPrivateUuid();
|
this.privateUuid = user.getPrivateUuid();
|
||||||
this.name = user.getName();
|
this.name = user.getName();
|
||||||
this.created = user.getCreated();
|
this.created = user.getCreated();
|
||||||
|
this.lastAccess = user.getLastAccess();
|
||||||
this.password = !user.getPassword().isEmpty();
|
this.password = !user.getPassword().isEmpty();
|
||||||
this.email = obfuscateEmail(user.getEmail());
|
this.email = obfuscateEmail(user.getEmail());
|
||||||
this.emailConfirmed = user.isEmailConfirmed();
|
this.emailConfirmed = user.isEmailConfirmed();
|
||||||
|
|||||||
@ -2,10 +2,11 @@ package de.ph87.tools.user;
|
|||||||
|
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.springframework.data.repository.ListCrudRepository;
|
import org.springframework.data.repository.ListCrudRepository;
|
||||||
|
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface UserRepository extends ListCrudRepository<User, String> {
|
public interface UserRepository extends ListCrudRepository<User, String>, PagingAndSortingRepository<User, String> {
|
||||||
|
|
||||||
boolean existsByName(@NonNull String name);
|
boolean existsByName(@NonNull String name);
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,6 @@ package de.ph87.tools.user;
|
|||||||
import de.ph87.tools.common.uuid.AbstractUuid;
|
import de.ph87.tools.common.uuid.AbstractUuid;
|
||||||
import de.ph87.tools.email.EmailService;
|
import de.ph87.tools.email.EmailService;
|
||||||
import de.ph87.tools.group.GroupMapper;
|
import de.ph87.tools.group.GroupMapper;
|
||||||
import de.ph87.tools.group.GroupRepository;
|
|
||||||
import de.ph87.tools.user.push.UserPushService;
|
import de.ph87.tools.user.push.UserPushService;
|
||||||
import de.ph87.tools.user.requests.UserLoginRequest;
|
import de.ph87.tools.user.requests.UserLoginRequest;
|
||||||
import de.ph87.tools.user.uuid.UserPrivateUuid;
|
import de.ph87.tools.user.uuid.UserPrivateUuid;
|
||||||
@ -50,8 +49,6 @@ public class UserService {
|
|||||||
|
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
private final GroupRepository groupRepository;
|
|
||||||
|
|
||||||
private final UserAccessService userAccessService;
|
private final UserAccessService userAccessService;
|
||||||
|
|
||||||
private final GroupMapper groupMapper;
|
private final GroupMapper groupMapper;
|
||||||
@ -133,7 +130,7 @@ public class UserService {
|
|||||||
}
|
}
|
||||||
user.setName(name);
|
user.setName(name);
|
||||||
log.info("User name changed: user={}", user);
|
log.info("User name changed: user={}", user);
|
||||||
groupRepository.findAllByUsersContains(user).forEach(groupMapper::push);
|
groupMapper.pushAllByUser(user);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
package de.ph87.tools.user.admin;
|
||||||
|
|
||||||
|
import de.ph87.tools.user.UserPrivateDto;
|
||||||
|
import de.ph87.tools.user.uuid.UserPrivateUuid;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@CrossOrigin
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("User/Admin")
|
||||||
|
public class UserAdminController {
|
||||||
|
|
||||||
|
private final UserAdminService userAdminService;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@PostMapping("page")
|
||||||
|
public Page<UserPrivateDto> page(@NonNull final UserPrivateUuid privateUuid, @NonNull @RequestBody final UserAdminPageRequest request) {
|
||||||
|
return userAdminService.page(privateUuid, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("delete")
|
||||||
|
public void delete(@NonNull final UserPrivateUuid privateUuid, @RequestBody @NonNull final String deletePrivateUuid) { // TODO we cannot use UserPrivateUuid for 'deletePrivateUuid' because it would be filled with cookie's UserPrivateUuid
|
||||||
|
userAdminService.delete(privateUuid, new UserPrivateUuid(deletePrivateUuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package de.ph87.tools.user.admin;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserAdminPageRequest {
|
||||||
|
|
||||||
|
public final int pageIndex;
|
||||||
|
|
||||||
|
public final int pageSize;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final List<Order> orders;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Pageable getPageable() {
|
||||||
|
return PageRequest.of(pageIndex, pageSize, Sort.by(orders.stream().map(Order::toSortOrder).toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Order {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final String property;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final Sort.Direction direction;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Sort.Order toSortOrder() {
|
||||||
|
return new Sort.Order(direction, property);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
75
src/main/java/de/ph87/tools/user/admin/UserAdminService.java
Normal file
75
src/main/java/de/ph87/tools/user/admin/UserAdminService.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package de.ph87.tools.user.admin;
|
||||||
|
|
||||||
|
import de.ph87.tools.email.EmailService;
|
||||||
|
import de.ph87.tools.group.GroupRepository;
|
||||||
|
import de.ph87.tools.group.member.GroupMemberService;
|
||||||
|
import de.ph87.tools.group.owner.GroupOwnerService;
|
||||||
|
import de.ph87.tools.tools.numbers.NumbersRepository;
|
||||||
|
import de.ph87.tools.user.User;
|
||||||
|
import de.ph87.tools.user.UserAccessService;
|
||||||
|
import de.ph87.tools.user.UserPrivateDto;
|
||||||
|
import de.ph87.tools.user.UserRepository;
|
||||||
|
import de.ph87.tools.user.uuid.UserPrivateUuid;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserAdminService {
|
||||||
|
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
|
private final UserAccessService userAccessService;
|
||||||
|
|
||||||
|
private final GroupRepository groupRepository;
|
||||||
|
|
||||||
|
private final GroupMemberService groupMemberService;
|
||||||
|
|
||||||
|
private final NumbersRepository numbersRepository;
|
||||||
|
|
||||||
|
private final GroupOwnerService groupOwnerService;
|
||||||
|
|
||||||
|
private final EmailService emailService;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Page<UserPrivateDto> page(@NonNull final UserPrivateUuid privateUuid, @NonNull final UserAdminPageRequest request) {
|
||||||
|
adminAccess(privateUuid);
|
||||||
|
return userRepository.findAll(request.getPageable()).map(UserPrivateDto::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(@NonNull final UserPrivateUuid privateUuid, @NonNull final UserPrivateUuid deletePrivateUuid) {
|
||||||
|
adminAccess(privateUuid);
|
||||||
|
final User user = userAccessService.access(deletePrivateUuid);
|
||||||
|
groupRepository.findAllByOwner(user).forEach(group -> groupOwnerService.delete(group.getOwner().getPrivateUuid(), group.getUuid()));
|
||||||
|
groupRepository.findAllByUsersContains(user).forEach(group -> groupMemberService._remove_user_from_group_unchecked(group, user));
|
||||||
|
numbersRepository.findAllByLotsUser(user).forEach(numbers -> numbers.getLots().removeIf(lot -> {
|
||||||
|
if (lot.getUser().equals(user)) {
|
||||||
|
log.info("Deleting NumbersLot: {}", lot);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}));
|
||||||
|
emailService.deleteAllByUser(user);
|
||||||
|
userRepository.delete(user);
|
||||||
|
log.info("User deleted: {}", user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
|
private User adminAccess(@NonNull final UserPrivateUuid privateUuid) {
|
||||||
|
final User user = userAccessService.access(privateUuid);
|
||||||
|
if (!user.isAdmin()) {
|
||||||
|
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user