GroupDeletedEvent + GroupLeftEvent + removed UI Subscriber
This commit is contained in:
parent
452e5f27f6
commit
e7dba8139b
@ -1,50 +0,0 @@
|
||||
import {Subscription} from "rxjs";
|
||||
import {Next} from "./common/types";
|
||||
|
||||
export class Subscribed<T> {
|
||||
|
||||
private subscription: Subscription | null = null;
|
||||
|
||||
private _value: T | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly same: (a: T, b: T) => boolean,
|
||||
private readonly subscribe: (value: T, next: Next<T>) => Subscription,
|
||||
) {
|
||||
// -
|
||||
}
|
||||
|
||||
get value(): T | null {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
set value(value: T | null) {
|
||||
if (!this.isSame(value)) {
|
||||
this.unsubscribe();
|
||||
if (value) {
|
||||
this.subscription = this.subscribe(value, next => this.value = next);
|
||||
}
|
||||
}
|
||||
this._value = value;
|
||||
}
|
||||
|
||||
public unsubscribe() {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
this.subscription = null;
|
||||
}
|
||||
}
|
||||
|
||||
private isSame(value: T | null) {
|
||||
if (this._value === null) {
|
||||
return value === null;
|
||||
} else {
|
||||
if (value === null) {
|
||||
return false
|
||||
} else {
|
||||
return this.same(this._value, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,13 +1,15 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Injectable, Type} from '@angular/core';
|
||||
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, Subject, Subscription} from "rxjs";
|
||||
import {BehaviorSubject, 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";
|
||||
|
||||
function userPushMessageFromJson(json: any): object {
|
||||
const type = json['_type_'];
|
||||
@ -18,6 +20,10 @@ function userPushMessageFromJson(json: any): object {
|
||||
return UserPrivate.fromJson(json['payload']);
|
||||
case 'GroupDto':
|
||||
return Group.fromJson(json['payload']);
|
||||
case 'GroupDeletedEvent':
|
||||
return GroupDeletedEvent.fromJson(json['payload']);
|
||||
case 'GroupLeftEvent':
|
||||
return GroupLeftEvent.fromJson(json['payload']);
|
||||
}
|
||||
throw new Error("Not implemented UserPushMessage._type_ = " + type);
|
||||
}
|
||||
@ -78,12 +84,6 @@ export class UserService {
|
||||
return this.subject.subscribe(next);
|
||||
}
|
||||
|
||||
subscribePush<T>(predicate: (m: any) => boolean, next: Next<T>): Subscription {
|
||||
return this.pushSubject
|
||||
.pipe(filter(predicate))
|
||||
.subscribe(next);
|
||||
}
|
||||
|
||||
iOwn(group: Group): boolean {
|
||||
return group.owner.equals(this.user);
|
||||
}
|
||||
@ -103,4 +103,13 @@ export class UserService {
|
||||
return this.user !== null && this.user.equals(user);
|
||||
}
|
||||
|
||||
subscribePush<T>(TYPE: Type<T>, next: Next<T>): Subscription {
|
||||
return this.pushSubject
|
||||
.pipe(
|
||||
filter(m => m instanceof TYPE),
|
||||
map(m => m as T),
|
||||
)
|
||||
.subscribe(next);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import {UserPublic} from "../User/UserPublic";
|
||||
import {validateBoolean, validateDate, validateList, validateString} from "../common/validators";
|
||||
import {UserPrivate} from "../User/UserPrivate";
|
||||
import {GroupUuid} from "./GroupUuid";
|
||||
|
||||
export class Group {
|
||||
export class Group extends GroupUuid {
|
||||
|
||||
protected constructor(
|
||||
readonly uuid: string,
|
||||
constructor(
|
||||
uuid: string,
|
||||
readonly owner: UserPublic,
|
||||
readonly created: Date,
|
||||
readonly title: string,
|
||||
@ -14,7 +15,7 @@ export class Group {
|
||||
readonly banned: UserPublic[],
|
||||
readonly initial: boolean,
|
||||
) {
|
||||
// -
|
||||
super(uuid);
|
||||
}
|
||||
|
||||
isOwner(user: UserPublic) {
|
||||
@ -47,10 +48,6 @@ export class Group {
|
||||
return UserPublic.compareName(a, b);
|
||||
}
|
||||
|
||||
static sameUuid(a: Group, b: Group): boolean {
|
||||
return a.uuid === b.uuid;
|
||||
}
|
||||
|
||||
static compareCreated(a: Group, b: Group): number {
|
||||
return a.created.getTime() - b.created.getTime();
|
||||
}
|
||||
|
||||
13
src/main/angular/src/app/api/group/GroupUuid.ts
Normal file
13
src/main/angular/src/app/api/group/GroupUuid.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export class GroupUuid {
|
||||
|
||||
protected constructor(
|
||||
readonly uuid: string,
|
||||
) {
|
||||
// -
|
||||
}
|
||||
|
||||
is(other: GroupUuid | null) {
|
||||
return other !== null && this.uuid === other.uuid;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import {validateString} from "../../common/validators";
|
||||
|
||||
import {GroupUuid} from "../GroupUuid";
|
||||
|
||||
export class GroupDeletedEvent extends GroupUuid {
|
||||
|
||||
constructor(
|
||||
uuid: string,
|
||||
) {
|
||||
super(uuid);
|
||||
}
|
||||
|
||||
static fromJson(json: any): GroupDeletedEvent {
|
||||
return new GroupDeletedEvent(
|
||||
validateString(json['uuid']),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
19
src/main/angular/src/app/api/group/events/GroupLeftEvent.ts
Normal file
19
src/main/angular/src/app/api/group/events/GroupLeftEvent.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {GroupUuid} from "../GroupUuid";
|
||||
import {validateString} from "../../common/validators";
|
||||
import {GroupDeletedEvent} from "./GroupDeletedEvent";
|
||||
|
||||
export class GroupLeftEvent extends GroupUuid {
|
||||
|
||||
constructor(
|
||||
uuid: string,
|
||||
) {
|
||||
super(uuid);
|
||||
}
|
||||
|
||||
static fromJson(json: any): GroupDeletedEvent {
|
||||
return new GroupDeletedEvent(
|
||||
validateString(json['uuid']),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,6 @@ import {Router} from "@angular/router";
|
||||
import {UserService} from "../User/user.service";
|
||||
import {validateBoolean} from "../common/validators";
|
||||
import {Injectable} from "@angular/core";
|
||||
import {Subscribed} from "../Subscribed";
|
||||
import {UserPublic} from "../User/UserPublic";
|
||||
import {GroupUserRequest} from "./requests/GroupUserRequest";
|
||||
import {GroupChangeTitleRequest} from "./requests/GroupChangeTitleRequest";
|
||||
@ -68,10 +67,6 @@ export class GroupService {
|
||||
this.router.navigate(['Group', uuid]);
|
||||
}
|
||||
|
||||
newSubscriber(): Subscribed<Group> {
|
||||
return new Subscribed<Group>(Group.sameUuid, (group, next) => this.api.subscribe(['Group', group.uuid], Group.fromJson, next));
|
||||
}
|
||||
|
||||
gotoGroups(): void {
|
||||
this.router.navigate(['Groups']);
|
||||
}
|
||||
|
||||
@ -17,9 +17,7 @@ export class NumbersService {
|
||||
protected readonly router: Router,
|
||||
protected readonly userService: UserService
|
||||
) {
|
||||
this.userService.subscribePush<Numbers>(m => m instanceof Numbers, message => {
|
||||
this.router.navigate(['Numbers', message.uuid])
|
||||
});
|
||||
// -
|
||||
}
|
||||
|
||||
create(groupUuid: string): void {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<div class="tileContainer">
|
||||
|
||||
<div class="tile" *ngIf="group.value === null && granted === false">
|
||||
<div class="tile" *ngIf="group === null && granted === false">
|
||||
<div class="tileInner">
|
||||
<div class="tileTitle">
|
||||
Passwort
|
||||
@ -11,7 +11,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="group.value">
|
||||
<ng-container *ngIf="group">
|
||||
|
||||
<div class="tile">
|
||||
<div class="tileInner">
|
||||
@ -23,26 +23,26 @@
|
||||
<table>
|
||||
<tr>
|
||||
<th>Erstellt</th>
|
||||
<td>{{ group.value.created | date:'yyyy-MM-dd HH:mm' }}</td>
|
||||
<td>{{ group.created | date:'yyyy-MM-dd HH:mm' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Titel</th>
|
||||
<td>
|
||||
<app-text [initial]="group.value.title" [editable]="userService.iOwn(group.value)" (onChange)="changeTitle(group.value, $event)"></app-text>
|
||||
<ng-container *ngIf="!userService.iOwn(group.value)"></ng-container>
|
||||
<app-text [initial]="group.title" [editable]="userService.iOwn(group)" (onChange)="changeTitle(group, $event)"></app-text>
|
||||
<ng-container *ngIf="!userService.iOwn(group)"></ng-container>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Passwort</th>
|
||||
<td>
|
||||
<app-text [initial]="group.value.password" [editable]="userService.iOwn(group.value)" (onChange)="changePassword(group.value, $event)"></app-text>
|
||||
<ng-container *ngIf="!userService.iOwn(group.value)"></ng-container>
|
||||
<app-text [initial]="group.password" [editable]="userService.iOwn(group)" (onChange)="changePassword(group, $event)"></app-text>
|
||||
<ng-container *ngIf="!userService.iOwn(group)"></ng-container>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="buttons">
|
||||
<div class="button buttonRight buttonDelete" (click)="groupDelete(group.value)">
|
||||
<div class="button buttonRight buttonDelete" (click)="groupDelete(group)">
|
||||
Gruppe löschen
|
||||
</div>
|
||||
</div>
|
||||
@ -59,16 +59,16 @@
|
||||
<div class="tileContent">
|
||||
<div class="numbers">
|
||||
<table>
|
||||
<tr [class.user_owner]="group.value.isOwner(user)" *ngFor="let user of group.value.usersByNameOwnerFirst()">
|
||||
<tr [class.user_owner]="group.isOwner(user)" *ngFor="let user of group.usersByNameOwnerFirst()">
|
||||
<td (click)="userService.goto(user)">{{ user.name }}</td>
|
||||
<td>
|
||||
<span class="owner" *ngIf="group.value.isOwnedBy(user)">
|
||||
<span class="owner" *ngIf="group.isOwnedBy(user)">
|
||||
Admin
|
||||
</span>
|
||||
<div class="buttons">
|
||||
<ng-container *ngIf="userService.iOwn(group.value) && !userService.iAm(user)">
|
||||
<div class="button buttonRight buttonBan" (click)="groupService.ban(group.value, user)">Verbannen</div>
|
||||
<div class="button buttonRight buttonRemove" (click)="groupService.kick(group.value, user)">Entfernen</div>
|
||||
<ng-container *ngIf="userService.iOwn(group) && !userService.iAm(user)">
|
||||
<div class="button buttonRight buttonBan" (click)="groupService.ban(group, user)">Verbannen</div>
|
||||
<div class="button buttonRight buttonRemove" (click)="groupService.kick(group, user)">Entfernen</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</td>
|
||||
@ -79,7 +79,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tile" *ngIf="group.value.banned.length > 0">
|
||||
<div class="tile" *ngIf="group.banned.length > 0">
|
||||
<div class="tileInner">
|
||||
<div class="tileTitle">
|
||||
Verbannt
|
||||
@ -87,12 +87,12 @@
|
||||
<div class="tileContent">
|
||||
<div class="numbers">
|
||||
<table>
|
||||
<tr [class.user_owner]="group.value.isOwner(user)" *ngFor="let user of group.value.bannedByName()" (click)="userService.goto(user)">
|
||||
<tr [class.user_owner]="group.isOwner(user)" *ngFor="let user of group.bannedByName()" (click)="userService.goto(user)">
|
||||
<td>{{ user.name }}</td>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<ng-container *ngIf="userService.iOwn(group.value) && !userService.iAm(user)">
|
||||
<div class="button buttonRight buttonUnban" (click)="groupService.unban(group.value, user)">Aufheben</div>
|
||||
<ng-container *ngIf="userService.iOwn(group) && !userService.iAm(user)">
|
||||
<div class="button buttonRight buttonUnban" (click)="groupService.unban(group, user)">Aufheben</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</td>
|
||||
@ -110,7 +110,7 @@
|
||||
</div>
|
||||
<div class="tileContent">
|
||||
<div class="buttons">
|
||||
<div class="button buttonRight buttonNext" *ngIf="userService.iOwn(group.value)" (click)="numbersService.create(group.value.uuid)">+ Nächste Runde</div>
|
||||
<div class="button buttonRight buttonNext" *ngIf="userService.iOwn(group)" (click)="numbersService.create(group.uuid)">+ Nächste Runde</div>
|
||||
</div>
|
||||
<div class="numbers">
|
||||
<table>
|
||||
|
||||
@ -6,13 +6,14 @@ import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {GroupService} from "../../../api/group/group.service";
|
||||
import {UserService} from "../../../api/User/user.service";
|
||||
import {Group} from "../../../api/group/Group";
|
||||
import {Subscribed} from "../../../api/Subscribed";
|
||||
import {NumbersService} from "../../../api/tools/Numbers/numbers.service";
|
||||
import {PasswordComponent} from "../../../shared/password/password.component";
|
||||
import {Numbers} from "../../../api/tools/Numbers/Numbers";
|
||||
import {Page} from "../../../api/common/Page";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
selector: 'app-group',
|
||||
@ -32,7 +33,9 @@ import {Subscription, timer} from "rxjs";
|
||||
})
|
||||
export class GroupComponent implements OnInit, OnDestroy {
|
||||
|
||||
protected readonly group: Subscribed<Group>;
|
||||
protected readonly subs: Subscription[] = [];
|
||||
|
||||
protected group: Group | null = null;
|
||||
|
||||
protected numbersList: Page<Numbers> = Page.EMPTY;
|
||||
|
||||
@ -42,8 +45,6 @@ export class GroupComponent implements OnInit, OnDestroy {
|
||||
|
||||
protected now: Date = new Date();
|
||||
|
||||
private timer?: Subscription;
|
||||
|
||||
constructor(
|
||||
protected readonly router: Router,
|
||||
protected readonly activatedRoute: ActivatedRoute,
|
||||
@ -51,12 +52,30 @@ export class GroupComponent implements OnInit, OnDestroy {
|
||||
protected readonly userService: UserService,
|
||||
protected readonly numbersService: NumbersService,
|
||||
) {
|
||||
this.group = this.groupService.newSubscriber();
|
||||
// -
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.timer = timer(1000, 1000).subscribe(() => this.now = new Date());
|
||||
this.activatedRoute.params.subscribe(params => {
|
||||
this.subs.push(timer(1000, 1000).subscribe(() => this.now = new Date()));
|
||||
this.subs.push(this.userService.subscribePush(Numbers, _ => {
|
||||
this.updateNumbersList();
|
||||
}));
|
||||
this.subs.push(this.userService.subscribePush(Group, group => {
|
||||
if (group.is(this.group)) {
|
||||
this.group = group;
|
||||
}
|
||||
}));
|
||||
this.subs.push(this.userService.subscribePush(GroupDeletedEvent, event => {
|
||||
if (event.is(this.group)) {
|
||||
this.groupService.gotoGroups();
|
||||
}
|
||||
}));
|
||||
this.subs.push(this.userService.subscribePush(GroupLeftEvent, event => {
|
||||
if (event.is(this.group)) {
|
||||
this.groupService.gotoGroups();
|
||||
}
|
||||
}));
|
||||
this.subs.push(this.activatedRoute.params.subscribe(params => {
|
||||
const groupUuid = params['uuid'];
|
||||
this.uuid = groupUuid;
|
||||
this.granted = null;
|
||||
@ -64,33 +83,37 @@ export class GroupComponent implements OnInit, OnDestroy {
|
||||
this.groupService.canAccess(groupUuid, granted => {
|
||||
this.granted = granted;
|
||||
if (granted) {
|
||||
this.groupService.get(groupUuid, group => this.group.value = group);
|
||||
this.numbersService.page(groupUuid, 0, 10, numbersList => this.numbersList = numbersList);
|
||||
this.groupService.get(groupUuid, group => {
|
||||
this.group = group;
|
||||
this.updateNumbersList();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
private updateNumbersList() {
|
||||
if (this.group) {
|
||||
this.numbersService.page(this.group.uuid, 0, 10, numbersList => this.numbersList = numbersList);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.timer) {
|
||||
this.timer.unsubscribe();
|
||||
this.timer = undefined;
|
||||
}
|
||||
this.group.unsubscribe();
|
||||
this.subs.forEach(sub => sub.unsubscribe());
|
||||
}
|
||||
|
||||
protected changeTitle(group: Group, title: string): void {
|
||||
this.groupService.changeTitle(group, title, group => this.group.value = group);
|
||||
this.groupService.changeTitle(group, title, group => this.group = group);
|
||||
}
|
||||
|
||||
protected changePassword(group: Group, password: string): void {
|
||||
this.groupService.changePassword(group, password, group => this.group.value = group);
|
||||
this.groupService.changePassword(group, password, group => this.group = group);
|
||||
}
|
||||
|
||||
protected join(password: string): void {
|
||||
if (this.uuid) {
|
||||
this.groupService.join(this.uuid, password, group => this.group.value = group);
|
||||
this.groupService.join(this.uuid, password, group => this.group = group);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ import {GroupService} from "../../../api/group/group.service";
|
||||
import {Group} from "../../../api/group/Group";
|
||||
import {Subscription} from "rxjs";
|
||||
import {ReactiveFormsModule} from "@angular/forms";
|
||||
import {GroupLeftEvent} from "../../../api/group/events/GroupLeftEvent";
|
||||
import {GroupDeletedEvent} from "../../../api/group/events/GroupDeletedEvent";
|
||||
|
||||
@Component({
|
||||
selector: 'app-groups',
|
||||
@ -20,7 +22,7 @@ import {ReactiveFormsModule} from "@angular/forms";
|
||||
})
|
||||
export class GroupsComponent implements OnInit, OnDestroy {
|
||||
|
||||
private readonly subscriptions: Subscription[] = [];
|
||||
private readonly subs: Subscription[] = [];
|
||||
|
||||
protected groups: Group[] = [];
|
||||
|
||||
@ -32,13 +34,18 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.subscriptions.push(this.userService.subscribe(_ => {
|
||||
this.groupService.findAllJoined(groups => this.groups = groups);
|
||||
}));
|
||||
this.subs.push(this.userService.subscribePush(Group, _ => this.updateGroups()));
|
||||
this.subs.push(this.userService.subscribePush(GroupLeftEvent, _ => this.updateGroups()));
|
||||
this.subs.push(this.userService.subscribePush(GroupDeletedEvent, _ => this.updateGroups()));
|
||||
this.updateGroups();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||
this.subs.forEach(sub => sub.unsubscribe());
|
||||
}
|
||||
|
||||
private updateGroups() {
|
||||
this.groupService.findAllJoined(groups => this.groups = groups);
|
||||
}
|
||||
|
||||
create(): void {
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package de.ph87.tools.group;
|
||||
|
||||
import de.ph87.tools.group.dto.GroupDto;
|
||||
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.UserService;
|
||||
import de.ph87.tools.user.push.UserPushService;
|
||||
import de.ph87.tools.user.uuid.UserPrivateUuid;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
@ -16,6 +18,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
@ -26,6 +30,8 @@ public class GroupMemberService {
|
||||
|
||||
private final GroupReadService groupReadService;
|
||||
|
||||
private final UserPushService userPushService;
|
||||
|
||||
@NonNull
|
||||
public GroupDto join(@Nullable final UserPrivateUuid privateUuid, @NonNull final GroupJoinRequest request, @NonNull final HttpServletResponse response) {
|
||||
final User user = userService.getUserByPrivateUuidOrElseCreate(privateUuid, response);
|
||||
@ -38,7 +44,7 @@ public class GroupMemberService {
|
||||
log.error("Wrong password: user={}, group={}", user, group);
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
|
||||
}
|
||||
return _join_unchecked(group, user);
|
||||
return _add_user_to_group_unchecked(group, user);
|
||||
}
|
||||
|
||||
public void leave(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUuid groupUuid) {
|
||||
@ -48,11 +54,11 @@ public class GroupMemberService {
|
||||
// owner cannot remove itself from group
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
_leave_unchecked(group, user);
|
||||
_remove_user_from_group_unchecked(group, user, (g, u) -> log.info("User left Group: user={}, group={}", u, g));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public GroupDto _join_unchecked(@NonNull final Group group, @NonNull final User user) {
|
||||
public GroupDto _add_user_to_group_unchecked(@NonNull final Group group, @NonNull final User user) {
|
||||
group.getUsers().add(user);
|
||||
group.touch();
|
||||
user.touch();
|
||||
@ -60,11 +66,12 @@ public class GroupMemberService {
|
||||
return groupReadService.publish(group);
|
||||
}
|
||||
|
||||
private void _leave_unchecked(final Group group, final User user) {
|
||||
public void _remove_user_from_group_unchecked(@NonNull final Group group, @NonNull final User user, @NonNull final BiConsumer<Group, User> beforePush) {
|
||||
group.getUsers().remove(user);
|
||||
group.touch();
|
||||
user.touch();
|
||||
log.info("User left Group: user={}, group={}", user, group);
|
||||
beforePush.accept(group, user);
|
||||
userPushService.push(user, new GroupLeftEvent(group));
|
||||
groupReadService.publish(group);
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
@ -47,7 +49,7 @@ public class GroupOwnerService {
|
||||
public GroupDto create(@Nullable final UserPrivateUuid privateUuid, @NonNull final HttpServletResponse response) {
|
||||
final User user = userService.getUserByPrivateUuidOrElseCreate(privateUuid, response);
|
||||
final Group group = _create_unchecked(user);
|
||||
return groupMemberService._join_unchecked(group, user);
|
||||
return groupMemberService._add_user_to_group_unchecked(group, user);
|
||||
}
|
||||
|
||||
public void delete(@NonNull final UserPrivateUuid userPrivateUuid, @NonNull final GroupUuid groupUuid) {
|
||||
@ -61,15 +63,13 @@ public class GroupOwnerService {
|
||||
}
|
||||
|
||||
public void kick(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
|
||||
final OwnerRemoveResult result = _removeUser(privateUuid, request);
|
||||
log.info("User kicked out of group: user={}, group={}", result.kicked, result.group);
|
||||
final OwnerRemoveResult result = _removeUser(privateUuid, request, (group, user) -> log.info("User kicked out of group: user={}, group={}", user, group));
|
||||
groupReadService.publish(result.group);
|
||||
}
|
||||
|
||||
public void ban(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
|
||||
final OwnerRemoveResult result = _removeUser(privateUuid, 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);
|
||||
log.info("User banned from group: user={}, group={}", result.kicked, result.group);
|
||||
groupReadService.publish(result.group);
|
||||
}
|
||||
|
||||
@ -108,14 +108,14 @@ public class GroupOwnerService {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private GroupOwnerService.OwnerRemoveResult _removeUser(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request) {
|
||||
private OwnerRemoveResult _removeUser(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUserRequest request, @NonNull final BiConsumer<Group, User> beforePush) {
|
||||
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));
|
||||
if (user.equals(access.user)) {
|
||||
// owner cannot kick itself from group
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
access.group.getUsers().remove(user);
|
||||
groupMemberService._remove_user_from_group_unchecked(access.group, user, beforePush);
|
||||
return new OwnerRemoveResult(access, user);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package de.ph87.tools.group.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import de.ph87.tools.common.uuid.UuidSerializer;
|
||||
import de.ph87.tools.group.Group;
|
||||
@ -27,17 +28,40 @@ public class GroupDto {
|
||||
public final ZonedDateTime created;
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
public final String password;
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
public final UserPublicDto owner;
|
||||
|
||||
@NonNull
|
||||
public final Set<UserPublicDto> users;
|
||||
@JsonIgnore
|
||||
@ToString.Include
|
||||
public String ownerPublicUuid() {
|
||||
return owner.publicUuid.uuid;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
public final Set<UserPublicDto> users;
|
||||
|
||||
@JsonIgnore
|
||||
@ToString.Include
|
||||
public int users() {
|
||||
return users.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
public final Set<UserPublicDto> banned;
|
||||
|
||||
@JsonIgnore
|
||||
@ToString.Include
|
||||
public int banned() {
|
||||
return banned.size();
|
||||
}
|
||||
|
||||
public final boolean initial;
|
||||
|
||||
public GroupDto(@NonNull final Group group, @NonNull final UserPublicDto owner, @NonNull final Set<UserPublicDto> users, @NonNull final Set<UserPublicDto> banned) {
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package de.ph87.tools.group.events;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import de.ph87.tools.common.uuid.UuidSerializer;
|
||||
import de.ph87.tools.group.Group;
|
||||
import de.ph87.tools.group.uuid.GroupUuid;
|
||||
import lombok.Getter;
|
||||
@ -10,10 +12,11 @@ import lombok.ToString;
|
||||
@ToString
|
||||
public class GroupDeletedEvent {
|
||||
|
||||
public final GroupUuid groupUuid;
|
||||
@JsonSerialize(using = UuidSerializer.class)
|
||||
public final GroupUuid uuid;
|
||||
|
||||
public GroupDeletedEvent(@NonNull final Group group) {
|
||||
this.groupUuid = group.getUuid();
|
||||
this.uuid = group.getUuid();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
22
src/main/java/de/ph87/tools/group/events/GroupLeftEvent.java
Normal file
22
src/main/java/de/ph87/tools/group/events/GroupLeftEvent.java
Normal file
@ -0,0 +1,22 @@
|
||||
package de.ph87.tools.group.events;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import de.ph87.tools.common.uuid.UuidSerializer;
|
||||
import de.ph87.tools.group.Group;
|
||||
import de.ph87.tools.group.uuid.GroupUuid;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public class GroupLeftEvent {
|
||||
|
||||
@JsonSerialize(using = UuidSerializer.class)
|
||||
public final GroupUuid uuid;
|
||||
|
||||
public GroupLeftEvent(@NonNull final Group group) {
|
||||
this.uuid = group.getUuid();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user