/
group_memberships_controller.rb
245 lines (228 loc) · 8.23 KB
/
group_memberships_controller.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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# frozen_string_literal: true
#
# Copyright (C) 2012 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# @API Groups
#
# Group memberships are the objects that tie users and groups together.
#
# @model GroupMembership
# {
# "id": "GroupMembership",
# "description": "",
# "properties": {
# "id": {
# "description": "The id of the membership object",
# "example": 92,
# "type": "integer"
# },
# "group_id": {
# "description": "The id of the group object to which the membership belongs",
# "example": 17,
# "type": "integer"
# },
# "user_id": {
# "description": "The id of the user object to which the membership belongs",
# "example": 3,
# "type": "integer"
# },
# "workflow_state": {
# "description": "The current state of the membership. Current possible values are 'accepted', 'invited', and 'requested'",
# "example": "accepted",
# "type": "string",
# "allowableValues": {
# "values": [
# "accepted",
# "invited",
# "requested"
# ]
# }
# },
# "moderator": {
# "description": "Whether or not the user is a moderator of the group (the must also be an active member of the group to moderate)",
# "example": true,
# "type": "boolean"
# },
# "just_created": {
# "description": "optional: whether or not the record was just created on a create call (POST), i.e. was the user just added to the group, or was the user already a member",
# "example": true,
# "type": "boolean"
# },
# "sis_import_id": {
# "description": "The id of the SIS import if created through SIS. Only included if the user has permission to manage SIS information.",
# "example": 4,
# "type": "integer"
# }
# }
# }
#
class GroupMembershipsController < ApplicationController
before_action :find_group, only: %i[index show create update destroy]
include Api::V1::Group
ALLOWED_MEMBERSHIP_FILTER = %w[accepted invited requested].freeze
# @API List group memberships
#
# @subtopic Group Memberships
#
# A paginated list of the members of a group.
#
# @argument filter_states[] [String, "accepted"|"invited"|"requested"]
# Only list memberships with the given workflow_states. By default it will
# return all memberships.
#
# @example_request
# curl https://<canvas>/api/v1/groups/<group_id>/memberships \
# -F 'filter_states[]=invited&filter_states[]=requested' \
# -H 'Authorization: Bearer <token>'
#
# @returns [GroupMembership]
def index
if authorized_action(@group, @current_user, :read_roster)
memberships_route = polymorphic_url([:api_v1, @group, :memberships])
scope = @group.group_memberships.preload(group: :root_account)
only_states = ALLOWED_MEMBERSHIP_FILTER
only_states &= params[:filter_states] if params[:filter_states]
scope = scope.where(workflow_state: only_states)
scope = scope.preload(group: :root_account)
@memberships = Api.paginate(scope, self, memberships_route)
render json: @memberships.map { |gm| group_membership_json(gm, @current_user, session) }
end
end
# @API Get a single group membership
#
# @subtopic Group Memberships
#
# Returns the group membership with the given membership id or user id.
#
# @example_request
# curl https://<canvas>/api/v1/groups/<group_id>/memberships/<membership_id> \
# -H 'Authorization: Bearer <token>'
# @example_request
# curl https://<canvas>/api/v1/groups/<group_id>/users/<user_id> \
# -H 'Authorization: Bearer <token>'
#
# @returns GroupMembership
def show
find_membership
if authorized_action(@membership, @current_user, :read)
render json: group_membership_json(@membership, @current_user, session)
end
end
# @API Create a membership
#
# @subtopic Group Memberships
#
# Join, or request to join, a group, depending on the join_level of the
# group. If the membership or join request already exists, then it is simply
# returned
#
# @argument user_id [String]
#
# @example_request
# curl https://<canvas>/api/v1/groups/<group_id>/memberships \
# -F 'user_id=self'
# -H 'Authorization: Bearer <token>'
#
# @returns GroupMembership
def create
@user = api_find(User, params[:user_id])
if authorized_action(GroupMembership.new(group: @group, user: @user), @current_user, :create)
SubmissionLifecycleManager.with_executing_user(@current_user) do
@membership = @group.add_user(@user)
if @membership.valid?
render json: group_membership_json(@membership, @current_user, session, include: ["just_created"])
else
render json: @membership.errors, status: :bad_request
end
end
end
end
UPDATABLE_MEMBERSHIP_ATTRIBUTES = %w[workflow_state moderator].freeze
# @API Update a membership
#
# @subtopic Group Memberships
#
# Accept a membership request, or add/remove moderator rights.
#
# @argument workflow_state [String, "accepted"]
# Currently, the only allowed value is "accepted"
#
# @argument moderator
#
# @example_request
# curl https://<canvas>/api/v1/groups/<group_id>/memberships/<membership_id> \
# -F 'moderator=true'
# -H 'Authorization: Bearer <token>'
# @example_request
# curl https://<canvas>/api/v1/groups/<group_id>/users/<user_id> \
# -F 'moderator=true'
# -H 'Authorization: Bearer <token>'
#
# @returns GroupMembership
def update
find_membership
if authorized_action(@membership, @current_user, :update)
attrs = params.permit(*UPDATABLE_MEMBERSHIP_ATTRIBUTES)
attrs.delete(:workflow_state) unless attrs[:workflow_state] == "accepted"
SubmissionLifecycleManager.with_executing_user(@current_user) do
if @membership.update(attrs)
render json: group_membership_json(@membership, @current_user, session)
else
render json: @membership.errors, status: :bad_request
end
end
end
end
# @API Leave a group
#
# @subtopic Group Memberships
#
# Leave a group if you are allowed to leave (some groups, such as sets of
# course groups created by teachers, cannot be left). You may also use 'self'
# in place of a membership_id.
#
# @example_request
# curl https://<canvas>/api/v1/groups/<group_id>/memberships/<membership_id> \
# -X DELETE \
# -H 'Authorization: Bearer <token>'
# @example_request
# curl https://<canvas>/api/v1/groups/<group_id>/users/<user_id> \
# -X DELETE \
# -H 'Authorization: Bearer <token>'
def destroy
find_membership
if authorized_action(@membership, @current_user, :delete)
@membership.workflow_state = "deleted"
@membership.save
render json: { "ok" => true }
end
end
protected
def find_group
@group = api_find(Group.active, params[:group_id])
end
def find_membership
if (params[:membership_id] && params[:membership_id] == "self") || (params[:user_id] && params[:user_id] == "self")
@membership = @group.group_memberships.where(user_id: @current_user).first!
elsif params[:membership_id]
@membership = @group.group_memberships.find(params[:membership_id])
else
user_id = Api.map_ids([params[:user_id]], @group.users, @domain_root_account, @current_user).first
@membership = @group.group_memberships.where(user_id:).first!
end
end
end