/
group_service.rb
183 lines (150 loc) · 5.4 KB
/
group_service.rb
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
module GroupService
def self.remote_cover_photo
# id like to use unsplash api but need to work out how to meet their attribution requirements
filename = %w[
cover1.jpg
cover2.jpg
cover3.jpg
cover4.jpg
cover5.jpg
cover6.jpg
cover7.jpg
cover8.jpg
cover9.jpg
cover10.jpg
cover11.jpg
cover12.jpg
cover13.jpg
cover14.jpg
].sample
Rails.root.join("public/theme/group_cover_photos/#{filename}")
end
def self.invite(group:, params:, actor:)
group_ids = if params[:invited_group_ids]
Array(params[:invited_group_ids]).map(&:to_i)
else
Array(group.id)
end
# restrict group_ids to a single organization
parent_group = Group.where(id: group_ids).first.parent_or_self
group_ids = parent_group.id_and_subgroup_ids & group_ids
UserInviter.authorize_add_members!(
parent_group: parent_group,
group_ids: group_ids,
emails: Array(params[:recipient_emails]),
user_ids: Array(params[:recipient_user_ids]),
actor: actor,
)
users = UserInviter.where_or_create!(
actor: actor,
model: group,
emails: params[:recipient_emails],
user_ids: params[:recipient_user_ids]
)
Group.where(id: group_ids).each do |g|
revoked_memberships = Membership.revoked.where(group_id: g.id, user_id: users.map(&:id))
revoked_memberships.update_all(
inviter_id: actor.id,
accepted_at: nil,
revoked_at: nil,
revoker_id: nil,
admin: false,
volume: 2
)
new_memberships = users.map do |user|
Membership.new(inviter: actor, user: user, group: g, volume: 2)
end
Membership.import(new_memberships, on_duplicate_key_ignore: true)
# mark as accepted all invitiations to people who are already part of the org.
if g.parent
parent_members = g.parent.accepted_members.where(id: users.verified.pluck(:id))
Membership.pending.where(group_id: g.id,
user_id: parent_members.pluck(:id)).update_all(accepted_at: Time.now)
end
g.update_pending_memberships_count
g.update_memberships_count
GenericWorker.perform_async('PollService', 'group_members_added', g.id)
end
Events::MembershipCreated.publish!(
group: group,
actor: actor,
recipient_user_ids: users.pluck(:id),
recipient_message: params[:recipient_message]
)
Membership.active.where(group_id: group.id, user_id: users.pluck(:id))
end
def self.create(group:, actor: , skip_authorize: false)
actor.ability.authorize!(:create, group) unless skip_authorize
return false unless group.valid?
group.is_referral = actor.groups.size > 0
if group.is_parent?
url = remote_cover_photo
group.cover_photo.attach(io: URI.open(url), filename: File.basename(url))
group.creator = actor if actor.is_logged_in?
group.subscription = Subscription.new
end
group.save!
group.add_admin!(actor)
EventBus.broadcast('group_create', group, actor)
end
def self.update(group:, params:, actor:)
actor.ability.authorize! :update, group
group.assign_attributes_and_files(params)
group.group_privacy = params[:group_privacy] if params.has_key?(:group_privacy)
privacy_change = PrivacyChange.new(group)
return false unless group.valid?
group.save!
privacy_change.commit!
EventBus.broadcast('group_update', group, params, actor)
end
def self.destroy(group:, actor:)
actor.ability.authorize! :destroy, group
group.admins.each do |admin|
GroupMailer.destroy_warning(group.id, admin.id, actor.id).deliver_later
end
group.archive!
DestroyGroupWorker.perform_in(2.weeks, group.id)
EventBus.broadcast('group_destroy', group, actor)
end
def self.destroy_without_warning!(group_id)
Group.find(group_id).archive!
DestroyGroupWorker.perform_async(group_id)
end
def self.move(group:, parent:, actor:)
actor.ability.authorize! :move, group
group.update(handle: "#{parent.handle}-#{group.handle}") if group.handle?
group.update(parent: parent, subscription_id: nil)
EventBus.broadcast('group_move', group, parent, actor)
end
def self.export(group: , actor: )
actor.ability.authorize! :show, group
group_ids = actor.groups.where(id: group.all_groups).pluck(:id)
GroupExportWorker.perform_async(group_ids, group.name, actor.id)
end
def self.merge(source:, target:, actor:)
actor.ability.authorize! :merge, source
actor.ability.authorize! :merge, target
Group.transaction do
source.subgroups.update_all(parent_id: target.id)
source.discussions.update_all(group_id: target.id)
source.polls.update_all(group_id: target.id)
source.membership_requests.update_all(group_id: target.id)
source.group_identities.update_all(group_id: target.id)
source.memberships.where.not(user_id: target.member_ids).update_all(group_id: target.id)
source.destroy
end
end
def self.suggest_handle(name:, parent_handle:)
attempt = 0
while(Group.where(handle: generate_handle(name, parent_handle, attempt)).exists?) do
attempt += 1
end
generate_handle(name, parent_handle, attempt)
end
private
def self.generate_handle(name, parent_handle, attempt)
[parent_handle,
name,
(attempt == 0) ? nil : attempt].compact.map{|t| t.to_s.strip.parameterize}.join('-')
end
end