From f4c1c2832b1b2a340067c2ea3cb3fc7ae88366e9 Mon Sep 17 00:00:00 2001 From: Simon Williams Date: Fri, 13 Jul 2012 12:33:15 -0600 Subject: [PATCH] api: list current user's groups; closes #4749 an api endpoint which lists the active groups for which the current user is an active member. test plan: - hit /api/v1/users/self/groups - you should get back the groups you belong to Change-Id: Iace05a70f4a77af0cebbb7dbaa3e6f77eb6785c8 Reviewed-on: https://gerrit.instructure.com/12230 Tested-by: Jenkins Reviewed-by: Brian Palmer --- app/controllers/groups_controller.rb | 37 +++++++++++++++++++++++++++- config/routes.rb | 1 + lib/api/v1/group.rb | 5 +++- spec/apis/v1/groups_api_spec.rb | 17 +++++++++++-- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index d62c677a289..e509652a7cc 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -72,6 +72,18 @@ # // The url of the group's avatar # avatar_url: "https:///files/avatar_image.png", # +# // The course or account that the group belongs to. The pattern here is +# // that whatever the context_type is, there will be an _id field named +# // after that type. So if instead context_type was "account", the +# // course_id field would be replaced by an account_id field. +# context_type: "Course", +# course_id: 3, +# +# // Certain types of groups have special role designations. Currently, +# // these include: "communities", "student_organized", and "imported". +# // Regular course/account groups have a role of null. +# role: null, +# # // The ID of the group's category. # group_category_id: 4, # } @@ -123,9 +135,32 @@ class GroupsController < ApplicationController end end + # @API List your groups + # + # Returns a list of active groups for the current user. + # + # @example_request + # curl https:///api/v1/users/self/groups \ + # -H 'Authorization: Bearer ' + # + # @returns [Group] def index return context_index if @context - @groups = @current_user ? @current_user.groups.active : [] + scope = @current_user.try(:current_groups) + respond_to do |format| + format.html do + @groups = scope || [] + end + format.json do + scope = scope.scoped({ + :include => :group_category, + :order => "groups.id ASC", + }) + route = polymorphic_url([:api_v1, :groups]) + @groups = Api.paginate(scope, self, route) + render :json => @groups.map { |g| group_json(g, @current_user, session) } + end + end end def context_index diff --git a/config/routes.rb b/config/routes.rb index 359b40c143e..2db591fb9fa 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -869,6 +869,7 @@ ActionController::Routing::Routes.draw do |map| api.with_options(:controller => :groups) do |groups| groups.resources :groups, :except => [:index] + groups.get 'users/self/groups', :action => :index groups.post 'groups/:group_id/invite', :action => :invite groups.post 'groups/:group_id/files', :action => :create_file groups.get 'groups/:group_id/activity_stream', :action => :activity_stream, :path_name => 'group_activity_stream' diff --git a/lib/api/v1/group.rb b/lib/api/v1/group.rb index 30d9de9dc1f..394c699dc28 100644 --- a/lib/api/v1/group.rb +++ b/lib/api/v1/group.rb @@ -18,6 +18,7 @@ module Api::V1::Group include Api::V1::Json + include Api::V1::Context API_GROUP_JSON_OPTS = { :only => %w(id name description is_public join_level group_category_id), @@ -30,12 +31,15 @@ module Api::V1::Group def group_json(group, user, session, options = {}) hash = api_json(group, user, session, API_GROUP_JSON_OPTS) + hash.merge!(context_data(group)) followed = ::UserFollow.followed_by_user([group], user) hash['followed_by_user'] = !!followed.include?(group) image = group.avatar_attachment hash['avatar_url'] = image && thumbnail_image_url(image, image.uuid) + hash['role'] = group.group_category.role include = options[:include] || [] if include.include?('users') + # TODO: this should be switched to user_display_json hash['users'] = group.users.map{ |u| user_json(u, user, session) } end hash @@ -45,4 +49,3 @@ module Api::V1::Group api_json(membership, user, session, API_GROUP_MEMBERSHIP_JSON_OPTS) end end - diff --git a/spec/apis/v1/groups_api_spec.rb b/spec/apis/v1/groups_api_spec.rb index e24901a0651..bf304f5be37 100644 --- a/spec/apis/v1/groups_api_spec.rb +++ b/spec/apis/v1/groups_api_spec.rb @@ -29,8 +29,11 @@ describe "Groups API", :type => :integration do 'join_level' => group.join_level, 'members_count' => group.members_count, 'avatar_url' => group.avatar_attachment && "http://www.example.com/images/thumbnails/#{group.avatar_attachment.id}/#{group.avatar_attachment.uuid}", - 'group_category_id' => group.group_category_id, 'followed_by_user' => group.followers.include?(user), + 'context_type' => group.context_type, + "#{group.context_type.downcase}_id" => group.context_id, + 'role' => group.group_category.role, + 'group_category_id' => group.group_category_id, } end @@ -49,7 +52,7 @@ describe "Groups API", :type => :integration do @member = user_with_pseudonym @communities = GroupCategory.communities_for(Account.default) - @community = group_model(:name => "Algebra Teachers", :group_category => @communities) + @community = group_model(:name => "Algebra Teachers", :group_category => @communities, :context => Account.default) @community.add_user(@member, 'accepted', false) @community.add_user(@moderator, 'accepted', true) @community_path = "/api/v1/groups/#{@community.id}" @@ -57,6 +60,16 @@ describe "Groups API", :type => :integration do @context = @community end + it "should allow listing all a user's groups" do + course_with_student(:user => @member) + @group = @course.groups.create!(:name => "My Group") + @group.add_user(@member, 'accepted', true) + + @user = @member + json = api_call(:get, "/api/v1/users/self/groups", @community_path_options.merge(:action => "index")) + json.should == [group_json(@community, @user), group_json(@group, @user)] + end + it "should allow a member to retrieve the group" do @user = @member json = api_call(:get, @community_path, @community_path_options.merge(:group_id => @community.to_param, :action => "show"))