first commit
This commit is contained in:
189
myteamwallet_backend/src/teams/public-team-access.service.ts
Normal file
189
myteamwallet_backend/src/teams/public-team-access.service.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { randomBytes } from 'crypto';
|
||||
import { PenaltyEntity } from '../penalty/entities/penalty.entity';
|
||||
import { Player } from '../players/entities/player.entity';
|
||||
import { Transaction } from '../transactions/entitites/transaction.entity';
|
||||
import { Repository } from 'typeorm';
|
||||
import {
|
||||
PublicAccessStatusDto,
|
||||
PublicPlayerDto,
|
||||
PublicPlayerHistoryDto,
|
||||
PublicTeamDto,
|
||||
PublicTransactionDto,
|
||||
} from './dto/public-access.dto';
|
||||
import { Team } from './entities/team.entity';
|
||||
import { TeamAccessService } from './team-access.service';
|
||||
|
||||
@Injectable()
|
||||
export class PublicTeamAccessService {
|
||||
constructor(
|
||||
@InjectRepository(Team)
|
||||
private readonly teamRepository: Repository<Team>,
|
||||
@InjectRepository(Player)
|
||||
private readonly playerRepository: Repository<Player>,
|
||||
@InjectRepository(Transaction)
|
||||
private readonly transactionRepository: Repository<Transaction>,
|
||||
@InjectRepository(PenaltyEntity)
|
||||
private readonly penaltyRepository: Repository<PenaltyEntity>,
|
||||
private readonly access: TeamAccessService,
|
||||
) {}
|
||||
|
||||
async getStatus(
|
||||
userId: number,
|
||||
teamId: number,
|
||||
): Promise<PublicAccessStatusDto> {
|
||||
await this.access.assertMember(userId, teamId);
|
||||
return this.toStatus(await this.loadManagedTeam(teamId));
|
||||
}
|
||||
|
||||
async setEnabled(
|
||||
userId: number,
|
||||
teamId: number,
|
||||
enabled: boolean,
|
||||
): Promise<PublicAccessStatusDto> {
|
||||
await this.access.assertManager(userId, teamId);
|
||||
const team = await this.loadManagedTeam(teamId);
|
||||
if (enabled && !team.publicAccessToken) {
|
||||
team.publicAccessToken = this.createToken();
|
||||
}
|
||||
team.publicAccessEnabled = enabled;
|
||||
await this.teamRepository.save(team);
|
||||
return this.toStatus(team);
|
||||
}
|
||||
|
||||
async rotate(userId: number, teamId: number): Promise<PublicAccessStatusDto> {
|
||||
await this.access.assertManager(userId, teamId);
|
||||
const team = await this.loadManagedTeam(teamId);
|
||||
team.publicAccessToken = this.createToken();
|
||||
await this.teamRepository.save(team);
|
||||
return this.toStatus(team);
|
||||
}
|
||||
|
||||
async getPublicTeam(token: string): Promise<PublicTeamDto> {
|
||||
const team = await this.loadPublicTeam(token);
|
||||
const [players, penalties] = await Promise.all([
|
||||
this.playerRepository.find({
|
||||
where: { team: { id: team.id }, active: true },
|
||||
order: { lastName: 'ASC', firstName: 'ASC' },
|
||||
}),
|
||||
this.penaltyRepository.find({
|
||||
where: { team: { id: team.id } },
|
||||
order: { description: 'ASC' },
|
||||
}),
|
||||
]);
|
||||
const publicPlayers = players.map((player) => this.toPublicPlayer(player));
|
||||
|
||||
return {
|
||||
name: team.name,
|
||||
balance: Number(team.balance),
|
||||
outstanding: publicPlayers.reduce(
|
||||
(total, player) => total - Number(player.balance),
|
||||
0,
|
||||
),
|
||||
players: publicPlayers,
|
||||
penalties: penalties.map((penalty) => ({
|
||||
id: penalty.id,
|
||||
description: penalty.description,
|
||||
amount: Number(penalty.amount),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
async getPublicPlayerHistory(
|
||||
token: string,
|
||||
playerId: number,
|
||||
): Promise<PublicPlayerHistoryDto> {
|
||||
const team = await this.loadPublicTeam(token);
|
||||
const player = await this.playerRepository.findOne({
|
||||
where: { id: playerId, team: { id: team.id }, active: true },
|
||||
});
|
||||
if (!player) throw new NotFoundException('Freigabe nicht gefunden.');
|
||||
|
||||
return {
|
||||
player: this.toPublicPlayer(player),
|
||||
transactions: await this.loadTransactions(player.id),
|
||||
};
|
||||
}
|
||||
|
||||
async getMemberPlayerTransactions(
|
||||
userId: number,
|
||||
teamId: number,
|
||||
playerId: number,
|
||||
): Promise<PublicTransactionDto[]> {
|
||||
await this.access.assertMember(userId, teamId);
|
||||
const player = await this.playerRepository.findOne({
|
||||
where: { id: playerId, team: { id: teamId } },
|
||||
});
|
||||
if (!player) throw new NotFoundException('Spieler nicht gefunden.');
|
||||
return this.loadTransactions(player.id);
|
||||
}
|
||||
|
||||
private async loadManagedTeam(teamId: number): Promise<Team> {
|
||||
const team = await this.teamRepository
|
||||
.createQueryBuilder('team')
|
||||
.addSelect('team.publicAccessToken')
|
||||
.where('team.id = :teamId', { teamId })
|
||||
.getOne();
|
||||
if (!team) throw new NotFoundException('Team nicht gefunden.');
|
||||
return team;
|
||||
}
|
||||
|
||||
private async loadPublicTeam(token: string): Promise<Team> {
|
||||
if (!/^[a-f0-9]{64}$/.test(token)) {
|
||||
throw new NotFoundException('Freigabe nicht gefunden.');
|
||||
}
|
||||
const team = await this.teamRepository.findOne({
|
||||
where: { publicAccessToken: token, publicAccessEnabled: true },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
balance: true,
|
||||
publicAccessEnabled: true,
|
||||
publicAccessToken: true,
|
||||
},
|
||||
});
|
||||
if (!team) throw new NotFoundException('Freigabe nicht gefunden.');
|
||||
return team;
|
||||
}
|
||||
|
||||
private async loadTransactions(
|
||||
playerId: number,
|
||||
): Promise<PublicTransactionDto[]> {
|
||||
const transactions = await this.transactionRepository.find({
|
||||
where: { player: { id: playerId } },
|
||||
order: { date: 'DESC' },
|
||||
take: 20,
|
||||
});
|
||||
return transactions.map((transaction) => ({
|
||||
id: transaction.id,
|
||||
note: transaction.note,
|
||||
date: transaction.date,
|
||||
amount: Number(transaction.amount),
|
||||
type: transaction.type
|
||||
? { id: transaction.type.id, name: transaction.type.name }
|
||||
: null,
|
||||
}));
|
||||
}
|
||||
|
||||
private toPublicPlayer(player: Player): PublicPlayerDto {
|
||||
return {
|
||||
id: player.id,
|
||||
firstName: player.firstName,
|
||||
lastName: player.lastName,
|
||||
balance: Number(player.balance),
|
||||
active: player.active,
|
||||
};
|
||||
}
|
||||
|
||||
private toStatus(team: Team): PublicAccessStatusDto {
|
||||
return {
|
||||
enabled: team.publicAccessEnabled,
|
||||
token: team.publicAccessToken ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
private createToken(): string {
|
||||
return randomBytes(32).toString('hex');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user