forked from StellarSplit/StellarSplit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgroup.service.ts
More file actions
118 lines (91 loc) · 3.01 KB
/
Copy pathgroup.service.ts
File metadata and controls
118 lines (91 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import {
Injectable,
ForbiddenException,
NotFoundException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Group, SplitType } from './entities/group.entity';
import { GroupActivity } from './entities/group-activity.entity';
@Injectable()
export class GroupService {
constructor(
@InjectRepository(Group)
private groupRepo: Repository<Group>,
@InjectRepository(GroupActivity)
private activityRepo: Repository<GroupActivity>,
) {}
async createGroup(data: Partial<Group>, creatorWallet: string) {
const group = this.groupRepo.create({
...data,
creatorId: creatorWallet,
members: [{ wallet: creatorWallet, role: 'admin' }],
});
await this.groupRepo.save(group);
await this.log(group.id, creatorWallet, 'CREATE_GROUP');
return group;
}
async addMember(groupId: string, wallet: string, actor: string) {
const group = await this.groupRepo.findOneBy({ id: groupId });
if (!group) throw new NotFoundException('Group not found');
this.assertAdmin(group, actor);
if (group.members.some(m => m.wallet === wallet)) return group;
group.members.push({ wallet, role: 'member' });
await this.groupRepo.save(group);
await this.log(groupId, actor, 'ADD_MEMBER', { wallet });
return group;
}
async removeMember(groupId: string, wallet: string, actor: string) {
const group = await this.groupRepo.findOneBy({ id: groupId });
if (!group) throw new NotFoundException('Group not found');
this.assertAdmin(group, actor);
group.members = group.members.filter(m => m.wallet !== wallet);
await this.groupRepo.save(group);
await this.log(groupId, actor, 'REMOVE_MEMBER', { wallet });
return group;
}
async createSplitFromGroup(groupId: string, actor: string) {
const group = await this.groupRepo.findOneBy({ id: groupId });
if (!group) throw new NotFoundException('Group not found');
this.assertMember(group, actor);
const participants = group.members.map(m => m.wallet);
await this.log(groupId, actor, 'CREATE_SPLIT', {
participants,
splitType: group.defaultSplitType,
});
return {
participants,
splitType: group.defaultSplitType,
};
}
async getActivity(groupId: string) {
return this.activityRepo.find({
where: { groupId },
order: { createdAt: 'DESC' },
});
}
private assertAdmin(group: Group, wallet: string) {
const member = group.members.find(m => m.wallet === wallet);
if (!member || member.role !== 'admin') {
throw new ForbiddenException('Admin access required');
}
}
private assertMember(group: Group, wallet: string) {
if (!group.members.some(m => m.wallet === wallet)) {
throw new ForbiddenException('Not a group member');
}
}
private async log(
groupId: string,
actor: string,
action: string,
metadata?: any,
) {
await this.activityRepo.save({
groupId,
actor,
action,
metadata,
});
}
}