Compare commits

...

2 Commits

Author SHA1 Message Date
b07fc824af REFACTOR: UI UserService 2024-11-06 12:46:24 +01:00
19fd6cee7b UI: update Group on User name change 2024-11-06 12:13:27 +01:00
20 changed files with 234 additions and 133 deletions

View File

@ -23,7 +23,7 @@ export class UserPublic {
return a.name.localeCompare(b.name);
}
equals(user: UserPublic | UserPrivate | null) {
is(user: UserPublic | UserPrivate | null) {
return user !== null && this.publicUuid === user.publicUuid;
}

View File

@ -0,0 +1,7 @@
export class UserLogoutEvent {
static fromJson(_: any): UserLogoutEvent {
return new UserLogoutEvent();
}
}

View File

@ -3,13 +3,14 @@ import {ApiService} from "../common/api.service";
import {UserPrivate} from "./UserPrivate";
import {Next} from "../common/types";
import {UserPublic} from "./UserPublic";
import {EventType, Router} from "@angular/router";
import {BehaviorSubject, filter, map, Subject, Subscription} from "rxjs";
import {Router} from "@angular/router";
import {filter, map, Subject, Subscription} from "rxjs";
import {Group} from "../group/Group";
import {StompService} from "@stomp/ng2-stompjs";
import {Numbers} from "../tools/Numbers/Numbers";
import {GroupDeletedEvent} from "../group/events/GroupDeletedEvent";
import {GroupLeftEvent} from "../group/events/GroupLeftEvent";
import {UserLogoutEvent} from "./events/UserLogoutEvent";
function userPushMessageFromJson(json: any): object {
const type = json['_type_'];
@ -18,6 +19,8 @@ function userPushMessageFromJson(json: any): object {
return Numbers.fromJson(json['payload']);
case 'UserPrivateDto':
return UserPrivate.fromJson(json['payload']);
case 'UserLogoutEvent':
return UserLogoutEvent.fromJson(json['payload']);
case 'GroupDto':
return Group.fromJson(json['payload']);
case 'GroupDeletedEvent':
@ -33,14 +36,14 @@ function userPushMessageFromJson(json: any): object {
})
export class UserService {
private readonly subject: BehaviorSubject<UserPrivate | null> = new BehaviorSubject<UserPrivate | null>(null);
private readonly pushSubject: Subject<any> = new Subject<any>();
private userSubscriptions: Subscription[] = [];
private readonly subs: Subscription[] = [];
private _user: UserPrivate | null = null;
get user(): UserPrivate | null {
return this.subject.value;
return this._user;
}
constructor(
@ -48,12 +51,26 @@ export class UserService {
protected readonly api: ApiService,
protected readonly stompService: StompService,
) {
this.router.events.subscribe(e => {
if (e.type === EventType.NavigationEnd || e.type === EventType.NavigationSkipped) {
this.refresh();
this.stompService.connected$.subscribe(() => this.fetchUser());
this.fetchUser()
this.subscribePush(UserPrivate, user => this.setUser(user));
this.subscribePush(UserLogoutEvent, _ => this.setUser(null));
}
});
this.stompService.connected$.subscribe(() => this.refresh());
private fetchUser() {
this.api.getSingle(['User', 'whoAmI'], UserPrivate.fromJson, user => this.setUser(user));
}
private setUser(user: UserPrivate | null) {
if (!this.user?.is(user)) {
this.subs.forEach(sub => sub.unsubscribe());
this.subs.length = 0;
if (user) {
this.subs.push(this.stompService.subscribe('User/' + user.privateUuid).pipe(map(m => userPushMessageFromJson(JSON.parse(m.body)))).subscribe(m => this.pushSubject.next(m)));
}
}
this._user = user;
}
getByPublicUuid(publicUuid: any, next: Next<UserPublic>) {
@ -76,31 +93,12 @@ export class UserService {
this.router.navigate(['User', user.publicUuid]);
}
refresh() {
this.api.getSingle(['User', 'whoAmI'], UserPrivate.fromJsonOrNull, user => this.setUser(user));
}
subscribe(next: Next<UserPrivate | null>): Subscription {
return this.subject.subscribe(next);
}
iOwn(group: Group): boolean {
return group.owner.equals(this.user);
}
private setUser(user: UserPrivate | null) {
if (user === null || this.subject.value?.privateUuid !== user.privateUuid) {
this.userSubscriptions.forEach(subscription => subscription.unsubscribe());
this.userSubscriptions.length = 0;
if (user) {
this.userSubscriptions.push(this.api.subscribe(["User", user.privateUuid], userPushMessageFromJson, message => this.pushSubject.next(message)));
}
}
this.subject.next(user);
return group.owner.is(this.user);
}
iAm(user: UserPublic | UserPrivate | null) {
return this.user !== null && this.user.equals(user);
return this.user !== null && this.user.is(user);
}
subscribePush<T>(TYPE: Type<T>, next: Next<T>): Subscription {
@ -111,5 +109,4 @@ export class UserService {
)
.subscribe(next);
}
}

View File

@ -53,12 +53,16 @@ export class Group extends GroupUuid {
}
isOwnedBy(user: UserPublic | UserPrivate | null) {
return user !== null && user.equals(this.owner);
return user !== null && user.is(this.owner);
}
bannedByName() {
return this.banned.sort(UserPublic.compareName);
}
hasUser(user: UserPublic) {
return this.users.some(u => u.is(user));
}
}

View File

@ -2,8 +2,8 @@
<div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/SolarSystem">Planeten</div>
<div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/VoltageDrop">Kabel</div>
<div class="mainMenuItem" routerLinkActive="mainMenuItemActive" routerLink="/Groups">Gruppen</div>
<ng-container *ngIf="user !== null">
<div class="mainMenuItem mainMenuItemRight" routerLinkActive="mainMenuItemActive" routerLink="/Profile">{{ user.name }}</div>
<ng-container *ngIf="userService.user !== null">
<div class="mainMenuItem mainMenuItemRight" routerLinkActive="mainMenuItemActive" routerLink="/Profile">{{ userService.user.name }}</div>
</ng-container>
</div>
<router-outlet (activate)="onActivate($event)"/>

View File

@ -2,7 +2,6 @@ import {Component, OnDestroy, OnInit} from '@angular/core';
import {Router, RouterLink, RouterLinkActive, RouterOutlet} from '@angular/router';
import {NgIf} from "@angular/common";
import {UserService} from "./api/User/user.service";
import {UserPrivate} from "./api/User/UserPrivate";
import {Subscription} from "rxjs";
@Component({
@ -14,12 +13,10 @@ import {Subscription} from "rxjs";
})
export class AppComponent implements OnInit, OnDestroy {
private readonly subscriptions: Subscription[] = [];
private readonly subs: Subscription[] = [];
protected menuVisible = true;
protected user: UserPrivate | null = null;
constructor(
protected readonly router: Router,
protected readonly userService: UserService,
@ -32,16 +29,12 @@ export class AppComponent implements OnInit, OnDestroy {
}
ngOnInit(): void {
this.subscriptions.push(this.userService.subscribe(user => {
if (this.user !== null && user === null) {
this.router.navigate(['']);
}
this.user = user;
}));
// -
}
ngOnDestroy(): void {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
this.subs.forEach(sub => sub.unsubscribe());
this.subs.length = 0;
}
}

View File

@ -60,7 +60,9 @@
<div class="numbers">
<table>
<tr [class.user_owner]="group.isOwner(user)" *ngFor="let user of group.usersByNameOwnerFirst()">
<td (click)="userService.goto(user)">{{ user.name }}</td>
<td (click)="userService.goto(user)">
{{ user.name }}
</td>
<td>
<span class="owner" *ngIf="group.isOwnedBy(user)">
Admin
@ -87,8 +89,10 @@
<div class="tileContent">
<div class="numbers">
<table>
<tr [class.user_owner]="group.isOwner(user)" *ngFor="let user of group.bannedByName()" (click)="userService.goto(user)">
<td>{{ user.name }}</td>
<tr [class.user_owner]="group.isOwner(user)" *ngFor="let user of group.bannedByName()">
<td (click)="userService.goto(user)">
{{ user.name }}
</td>
<td>
<div class="buttons">
<ng-container *ngIf="userService.iOwn(group) && !userService.iAm(user)">

View File

@ -14,6 +14,7 @@ import {RelativePipe} from "../../../shared/relative.pipe";
import {Subscription, timer} from "rxjs";
import {GroupDeletedEvent} from "../../../api/group/events/GroupDeletedEvent";
import {GroupLeftEvent} from "../../../api/group/events/GroupLeftEvent";
import {UserPublic} from "../../../api/User/UserPublic";
@Component({
selector: 'app-group',
@ -35,6 +36,8 @@ export class GroupComponent implements OnInit, OnDestroy {
protected readonly subs: Subscription[] = [];
private readonly userSubs: Subscription[] = [];
protected group: Group | null = null;
protected numbersList: Page<Numbers> = Page.EMPTY;
@ -62,7 +65,7 @@ export class GroupComponent implements OnInit, OnDestroy {
}));
this.subs.push(this.userService.subscribePush(Group, group => {
if (group.is(this.group)) {
this.group = group;
this.setGroup(group);
}
}));
this.subs.push(this.userService.subscribePush(GroupDeletedEvent, event => {
@ -83,37 +86,47 @@ export class GroupComponent implements OnInit, OnDestroy {
this.groupService.canAccess(groupUuid, granted => {
this.granted = granted;
if (granted) {
this.groupService.get(groupUuid, group => {
this.group = group;
this.updateNumbersList();
});
this.updateGroup();
}
});
}
}));
}
ngOnDestroy(): void {
this.subs.forEach(sub => sub.unsubscribe());
this.subs.length=0;
this.userSubs.forEach(sub => sub.unsubscribe());
this.userSubs.length=0;
}
private setGroup(group: Group) {
this.group = group;
this.userSubs.forEach(sub => sub.unsubscribe());
this.userSubs.length = 0;
if (this.group !== null) {
this.group.users.forEach(_ => this.userSubs.push(this.userService.subscribePush(UserPublic, u => this.updateUser(u))));
}
}
private updateNumbersList() {
if (this.group) {
this.numbersService.page(this.group.uuid, 0, 10, numbersList => this.numbersList = numbersList);
}
}
ngOnDestroy(): void {
this.subs.forEach(sub => sub.unsubscribe());
}
protected changeTitle(group: Group, title: string): void {
this.groupService.changeTitle(group, title, group => this.group = group);
this.groupService.changeTitle(group, title, group => this.setGroup(group));
}
protected changePassword(group: Group, password: string): void {
this.groupService.changePassword(group, password, group => this.group = group);
this.groupService.changePassword(group, password, group => this.setGroup(group));
}
protected join(password: string): void {
if (this.uuid) {
this.groupService.join(this.uuid, password, group => this.group = group);
this.groupService.join(this.uuid, password, group => this.setGroup(group));
}
}
@ -123,4 +136,21 @@ export class GroupComponent implements OnInit, OnDestroy {
}
}
private updateUser(user: UserPublic) {
if (this.group?.hasUser(user)) {
this.updateGroup();
}
}
private updateGroup() {
if (this.uuid === null) {
this.group = null;
return;
}
this.groupService.get(this.uuid, group => {
this.setGroup(group);
this.updateNumbersList();
});
}
}

View File

@ -42,6 +42,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {
this.subs.forEach(sub => sub.unsubscribe());
this.subs.length = 0;
}
private updateGroups() {

View File

@ -7,6 +7,7 @@ import {GroupListComponent} from "../group/shared/group-list/group-list.componen
import {Group} from "../../api/group/Group";
import {Subscription} from "rxjs";
import {GroupService} from "../../api/group/group.service";
import {UserPrivate} from "../../api/User/UserPrivate";
const USER_NAME_MIN_LENGTH = 2;
@ -31,7 +32,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
protected readonly USER_PASSWORD_MIN_LENGTH = USER_PASSWORD_MIN_LENGTH;
private readonly subscriptions: Subscription[] = [];
private readonly subs: Subscription[] = [];
protected password0: string = "";
@ -50,13 +51,14 @@ export class ProfileComponent implements OnInit, OnDestroy {
}
ngOnInit(): void {
this.subscriptions.push(this.userService.subscribe(_ => {
this.subs.push(this.userService.subscribePush(UserPrivate, _ => {
this.groupService.findAllJoined(groups => this.groups = groups);
}));
}
ngOnDestroy(): void {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
this.subs.forEach(sub => sub.unsubscribe());
this.subs.length = 0;
}
protected nameValidator(name: string): boolean {

View File

@ -2,7 +2,7 @@ package de.ph87.tools.group;
import de.ph87.tools.group.uuid.GroupUuid;
import de.ph87.tools.user.User;
import de.ph87.tools.user.UserService;
import de.ph87.tools.user.UserAccessService;
import de.ph87.tools.user.uuid.UserPrivateUuid;
import jakarta.annotation.Nullable;
import lombok.NonNull;
@ -21,10 +21,10 @@ public class GroupAccessService {
private final GroupRepository groupRepository;
private final UserService userService;
private final UserAccessService userAccessService;
public boolean canAccess(@Nullable final UserPrivateUuid userPrivateUuid, @NonNull final GroupUuid groupUuid) {
final User user = userService.accessOrNull(userPrivateUuid);
final User user = userAccessService.accessOrNull(userPrivateUuid);
if (user == null) {
return false;
}
@ -34,7 +34,7 @@ public class GroupAccessService {
@NonNull
public GroupAccess access(@NonNull final UserPrivateUuid userPrivateUuid, @NonNull final GroupUuid groupUuid) {
final User user = userService.access(userPrivateUuid);
final User user = userAccessService.access(userPrivateUuid);
final Group group = getByUuidOrThrow(groupUuid);
return new GroupAccess(user, group);
}

View File

@ -0,0 +1,38 @@
package de.ph87.tools.group;
import de.ph87.tools.group.dto.GroupDto;
import de.ph87.tools.user.UserPublicDto;
import de.ph87.tools.user.push.UserPushService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class GroupMapper {
private final UserPushService userPushService;
@NonNull
public GroupDto toDto(@NonNull final Group group) {
final UserPublicDto owner = new UserPublicDto(group.getOwner());
final Set<UserPublicDto> users = group.getUsers().stream().map(UserPublicDto::new).collect(Collectors.toSet());
final Set<UserPublicDto> banned = group.getBanned().stream().map(UserPublicDto::new).collect(Collectors.toSet());
return new GroupDto(group, owner, users, banned);
}
@NonNull
public GroupDto push(@NonNull final Group group) {
final GroupDto dto = toDto(group);
group.getUsers().forEach(user -> userPushService.push(user, dto));
return dto;
}
}

View File

@ -5,6 +5,7 @@ import de.ph87.tools.group.events.GroupLeftEvent;
import de.ph87.tools.group.requests.GroupJoinRequest;
import de.ph87.tools.group.uuid.GroupUuid;
import de.ph87.tools.user.User;
import de.ph87.tools.user.UserAccessService;
import de.ph87.tools.user.UserService;
import de.ph87.tools.user.push.UserPushService;
import de.ph87.tools.user.uuid.UserPrivateUuid;
@ -32,6 +33,10 @@ public class GroupMemberService {
private final UserPushService userPushService;
private final UserAccessService userAccessService;
private final GroupMapper groupMapper;
@NonNull
public GroupDto join(@Nullable final UserPrivateUuid privateUuid, @NonNull final GroupJoinRequest request, @NonNull final HttpServletResponse response) {
final User user = userService.getUserByPrivateUuidOrElseCreate(privateUuid, response);
@ -48,7 +53,7 @@ public class GroupMemberService {
}
public void leave(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUuid groupUuid) {
final User user = userService.access(privateUuid);
final User user = userAccessService.access(privateUuid);
final Group group = groupReadService.getGroupByGroupUuid(groupUuid);
if (group.isOwnedBy(user)) {
// owner cannot remove itself from group
@ -63,7 +68,7 @@ public class GroupMemberService {
group.touch();
user.touch();
log.info("User joined Group: user={}, group={}", user, group);
return groupReadService.publish(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) {
@ -72,7 +77,7 @@ public class GroupMemberService {
user.touch();
beforePush.accept(group, user);
userPushService.push(user, new GroupLeftEvent(group));
groupReadService.publish(group);
groupMapper.push(group);
}
}

View File

@ -37,14 +37,14 @@ public class GroupOwnerService {
private final UserService userService;
private final GroupReadService groupReadService;
private final GroupMemberService groupMemberService;
private final NumbersRepository numbersRepository;
private final UserPushService userPushService;
private final GroupMapper groupMapper;
@NonNull
public GroupDto create(@Nullable final UserPrivateUuid privateUuid, @NonNull final HttpServletResponse response) {
final User user = userService.getUserByPrivateUuidOrElseCreate(privateUuid, response);
@ -64,13 +64,13 @@ public class GroupOwnerService {
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));
groupReadService.publish(result.group);
groupMapper.push(result.group);
}
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));
result.group.getBanned().add(result.kicked);
groupReadService.publish(result.group);
groupMapper.push(result.group);
}
public void unban(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
@ -78,7 +78,7 @@ public class GroupOwnerService {
final User user = access.group.getBanned().stream().filter(u -> u.getPublicUuid().equals(request.userPublicUuid)).findFirst().orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
access.group.getBanned().remove(user);
log.info("User unbanned from group: user={}, group={}", user, access.group);
groupReadService.publish(access.group);
groupMapper.push(access.group);
}
@NonNull
@ -88,14 +88,14 @@ public class GroupOwnerService {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
ug.group.setTitle(request.title);
return groupReadService.publish(ug.group);
return groupMapper.push(ug.group);
}
@NonNull
public GroupDto changePassword(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupChangePasswordRequest request) {
final GroupAccess access = groupAccessService.ownerAccess(privateUuid, request.groupUuid);
access.group.setPassword(request.password);
return groupReadService.publish(access.group);
return groupMapper.push(access.group);
}
/* EXECUTORS ------------------------------------------------------------------------------------ */

View File

@ -3,9 +3,8 @@ package de.ph87.tools.group;
import de.ph87.tools.group.dto.GroupDto;
import de.ph87.tools.group.uuid.GroupUuid;
import de.ph87.tools.user.User;
import de.ph87.tools.user.UserPublicDto;
import de.ph87.tools.user.UserAccessService;
import de.ph87.tools.user.UserService;
import de.ph87.tools.user.push.UserPushService;
import de.ph87.tools.user.uuid.UserPrivateUuid;
import de.ph87.tools.user.uuid.UserPublicUuid;
import lombok.NonNull;
@ -29,14 +28,16 @@ public class GroupReadService {
private final GroupRepository groupRepository;
private final UserPushService userPushService;
private final UserService userService;
private final UserAccessService userAccessService;
private final GroupMapper groupMapper;
@NonNull
public GroupDto get(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUuid groupUuid) {
final GroupAccess ug = groupAccessService.access(privateUuid, groupUuid);
return toDto(ug.group);
return groupMapper.toDto(ug.group);
}
@NonNull
@ -44,41 +45,22 @@ public class GroupReadService {
return groupRepository.findByUuid(groupUuid.uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
}
/* DTO ------------------------------------------------------------------------------------------ */
@NonNull
public GroupDto toDto(@NonNull final Group group) {
final UserPublicDto owner = new UserPublicDto(group.getOwner());
final Set<UserPublicDto> users = group.getUsers().stream().map(UserPublicDto::new).collect(Collectors.toSet());
final Set<UserPublicDto> banned = group.getBanned().stream().map(UserPublicDto::new).collect(Collectors.toSet());
return new GroupDto(group, owner, users, banned);
}
/* PUBLISH -------------------------------------------------------------------------------------- */
@NonNull
public GroupDto publish(@NonNull final Group group) {
final GroupDto dto = toDto(group);
group.getUsers().forEach(user -> userPushService.push(user, dto));
return dto;
}
/* FIND & GET ----------------------------------------------------------------------------------- */
@NonNull
public Set<GroupDto> findAllCommonGroups(@NonNull final User a, @NonNull final User b) {
return groupRepository.findAllByUsersContainsAndUsersContains(a, b).stream().map(this::toDto).collect(Collectors.toSet());
return groupRepository.findAllByUsersContainsAndUsersContains(a, b).stream().map(groupMapper::toDto).collect(Collectors.toSet());
}
@NonNull
public Set<GroupDto> findAllJoined(@NonNull final UserPrivateUuid privateUuid) {
final User principal = userService.access(privateUuid);
return groupRepository.findAllByUsersContains(principal).stream().map(this::toDto).collect(Collectors.toSet());
final User principal = userAccessService.access(privateUuid);
return groupRepository.findAllByUsersContains(principal).stream().map(groupMapper::toDto).collect(Collectors.toSet());
}
@NonNull
public Set<GroupDto> findAllCommon(@NonNull final UserPrivateUuid privateUuid, @NonNull final UserPublicUuid targetUuid) {
final User principal = userService.access(privateUuid);
final User principal = userAccessService.access(privateUuid);
final User target = userService.getByPublicUuid(targetUuid);
return findAllCommonGroups(principal, target);
}

View File

@ -26,6 +26,7 @@ public class Numbers extends NumbersAbstract {
private String uuid = UUID.randomUUID().toString();
@Transient
@ToString.Exclude
private NumbersUuid _uuid;
@NonNull

View File

@ -2,12 +2,12 @@ package de.ph87.tools.tools.numbers;
import de.ph87.tools.group.GroupAccess;
import de.ph87.tools.group.GroupAccessService;
import de.ph87.tools.group.GroupMapper;
import de.ph87.tools.group.dto.GroupDto;
import de.ph87.tools.group.GroupReadService;
import de.ph87.tools.group.uuid.GroupUuid;
import de.ph87.tools.tools.numbers.uuid.NumbersUuid;
import de.ph87.tools.user.User;
import de.ph87.tools.user.UserService;
import de.ph87.tools.user.UserAccessService;
import de.ph87.tools.user.push.UserPushService;
import de.ph87.tools.user.reference.UserReference;
import de.ph87.tools.user.reference.UserReferenceService;
@ -41,11 +41,11 @@ public class NumbersService {
private final UserReferenceService userReferenceService;
private final GroupReadService groupReadService;
private final UserPushService userPushService;
private final UserService userService;
private final UserAccessService userAccessService;
private final GroupMapper groupMapper;
public void create(@NonNull final UserPrivateUuid userPrivateUuid, @NonNull final GroupUuid groupUuid) {
final GroupAccess access = groupAccessService.ownerAccess(userPrivateUuid, groupUuid);
@ -71,13 +71,13 @@ public class NumbersService {
@NonNull
public NumbersDto toDto(@NonNull final Numbers numbers, @NonNull final User user) {
final GroupDto group = groupReadService.toDto(numbers.getGroup());
final GroupDto group = groupMapper.toDto(numbers.getGroup());
final Integer number = numbers.getNumberForUser(user);
return new NumbersDto(numbers, group, number);
}
public boolean canAccess(@NonNull final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
final User user = userService.access(privateUuid);
final User user = userAccessService.access(privateUuid);
final Numbers numbers = numbersRepository.findById(numbersUuid.uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
return numbers.containsUser(user);
}
@ -98,7 +98,7 @@ public class NumbersService {
@NonNull
private NumbersAccess access(@NonNull final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
final User user = userService.access(privateUuid);
final User user = userAccessService.access(privateUuid);
final Numbers numbers = numbersRepository.findById(numbersUuid.uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
if (!numbers.containsUser(user)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);

View File

@ -23,6 +23,7 @@ public class User extends UserPublicAbstract {
private String publicUuid = UUID.randomUUID().toString();
@Transient
@ToString.Exclude
private UserPublicUuid _publicUuid;
@NonNull
@ -39,6 +40,7 @@ public class User extends UserPublicAbstract {
private String privateUuid = UUID.randomUUID().toString();
@Transient
@ToString.Exclude
private UserPrivateUuid _privateUuid;
@NonNull

View File

@ -0,0 +1,36 @@
package de.ph87.tools.user;
import de.ph87.tools.user.uuid.UserPrivateUuid;
import jakarta.annotation.Nullable;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;
@Slf4j
@Service
@Transactional
@EnableScheduling
@RequiredArgsConstructor
public class UserAccessService {
private final UserRepository userRepository;
@Nullable
public User accessOrNull(@Nullable final UserPrivateUuid userPrivateUuid) {
if (userPrivateUuid == null) {
return null;
}
return access(userPrivateUuid);
}
@NonNull
public User access(@NonNull final UserPrivateUuid privateUuid) {
return userRepository.findByPrivateUuid(privateUuid.uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
}
}

View File

@ -1,6 +1,9 @@
package de.ph87.tools.user;
import de.ph87.tools.common.uuid.AbstractUuid;
import de.ph87.tools.group.GroupMapper;
import de.ph87.tools.group.GroupRepository;
import de.ph87.tools.user.push.UserPushService;
import de.ph87.tools.user.requests.UserLoginRequest;
import de.ph87.tools.user.uuid.UserPrivateUuid;
import de.ph87.tools.user.uuid.UserPublicUuid;
@ -45,6 +48,14 @@ public class UserService {
private final PasswordEncoder passwordEncoder;
private final GroupRepository groupRepository;
private final UserAccessService userAccessService;
private final GroupMapper groupMapper;
private final UserPushService userPushService;
@NonNull
public UserPrivateDto login(@NonNull final UserLoginRequest loginRequest, @NonNull final HttpServletResponse response) {
final User user = userRepository.findByName(loginRequest.name).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
@ -100,6 +111,7 @@ public class UserService {
}
user.setName(name);
log.info("User name changed: user={}", user);
groupRepository.findAllByUsersContains(user).forEach(groupMapper::push);
});
}
@ -147,9 +159,11 @@ public class UserService {
@NonNull
private UserPrivateDto modify(@NonNull final UserPrivateUuid privateUuid, @NonNull Consumer<User> modifier) {
final User user = access(privateUuid);
final User user = userAccessService.access(privateUuid);
modifier.accept(user);
return new UserPrivateDto(user);
final UserPrivateDto privateDto = new UserPrivateDto(user);
userPushService.push(user, privateDto);
return privateDto;
}
private void deleteUnchecked(final HttpServletResponse response, final User user) {
@ -158,16 +172,6 @@ public class UserService {
writeUserUuidCookie(response, null);
}
/* ACCESS --------------------------------------------------------------------------------------- */
@Nullable
public User accessOrNull(@Nullable final UserPrivateUuid userPrivateUuid) {
if (userPrivateUuid == null) {
return null;
}
return access(userPrivateUuid);
}
/* GETTERS & FINDERS ---------------------------------------------------------------------------- */
@NonNull
@ -175,11 +179,6 @@ public class UserService {
return new UserPublicDto(getByPublicUuid(publicUuid));
}
@NonNull
public User access(@NonNull final UserPrivateUuid privateUuid) {
return userRepository.findByPrivateUuid(privateUuid.uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
}
@NonNull
public User getByPublicUuid(@NonNull final UserPublicUuid publicUuid) {
return userRepository.findByPublicUuid(publicUuid.uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));