From 9175d6088374d37f13528166d806701ee0cd9bad Mon Sep 17 00:00:00 2001 From: Nick Muerdter Date: Fri, 13 May 2016 09:14:26 -0600 Subject: [PATCH] Display admin accounts belonging to groups on the group pages. This makes it easier to browse the groups and figure out who group members. --- .../javascripts/admin/models/admin_group.js | 1 + .../admin/templates/admin_groups/_form.hbs | 19 ++ .../admin/views/admin_groups/table_view.js | 9 + .../admin/views/admins/table_view.js | 1 + src/api-umbrella/web-app/app/models/admin.rb | 6 +- .../web-app/app/models/admin_group.rb | 12 ++ .../app/views/api/v1/admin_groups/index.rabl | 1 + .../app/views/api/v1/admin_groups/show.rabl | 4 + .../api/v1/admin_groups_controller_spec.rb | 164 ++++++++++++++---- 9 files changed, 182 insertions(+), 35 deletions(-) diff --git a/src/api-umbrella/web-app/app/assets/javascripts/admin/models/admin_group.js b/src/api-umbrella/web-app/app/assets/javascripts/admin/models/admin_group.js index 2631be56e..d71c7522c 100644 --- a/src/api-umbrella/web-app/app/assets/javascripts/admin/models/admin_group.js +++ b/src/api-umbrella/web-app/app/assets/javascripts/admin/models/admin_group.js @@ -3,6 +3,7 @@ Admin.AdminGroup = Ember.Model.extend(Ember.Validations.Mixin, { name: Ember.attr(), apiScopeIds: Ember.attr(), permissionIds: Ember.attr(), + admins: Ember.attr(), createdAt: Ember.attr(), updatedAt: Ember.attr(), creator: Ember.attr(), diff --git a/src/api-umbrella/web-app/app/assets/javascripts/admin/templates/admin_groups/_form.hbs b/src/api-umbrella/web-app/app/assets/javascripts/admin/templates/admin_groups/_form.hbs index 66787f30f..fe2d41f32 100644 --- a/src/api-umbrella/web-app/app/assets/javascripts/admin/templates/admin_groups/_form.hbs +++ b/src/api-umbrella/web-app/app/assets/javascripts/admin/templates/admin_groups/_form.hbs @@ -23,6 +23,25 @@ {{view Admin.CheckboxListView checkedValuesBinding='permissionIds' contentBinding='permissionOptions'}} + + {{#if id}} +
+
+ +
+
+ {{#if admins}} +
    + {{#each admins}} +
  • {{#link-to 'admins.edit' id}}{{username}}{{/link-to}} (Last Login: {{#if last_sign_in_at}}{{formatDate last_sign_in_at}}{{else}}Never{{/if}})
  • + {{/each}} +
+ {{else}} + None + {{/if}} +
+
+ {{/if}}
diff --git a/src/api-umbrella/web-app/app/assets/javascripts/admin/views/admin_groups/table_view.js b/src/api-umbrella/web-app/app/assets/javascripts/admin/views/admin_groups/table_view.js index a992d41c7..8eaf21981 100644 --- a/src/api-umbrella/web-app/app/assets/javascripts/admin/views/admin_groups/table_view.js +++ b/src/api-umbrella/web-app/app/assets/javascripts/admin/views/admin_groups/table_view.js @@ -26,12 +26,21 @@ Admin.AdminGroupsTableView = Ember.View.extend({ { data: 'api_scope_display_names', title: 'API Scopes', + orderable: false, render: Admin.DataTablesHelpers.renderListEscaped, }, { data: 'permission_display_names', title: 'Access', defaultContent: '-', + orderable: false, + render: Admin.DataTablesHelpers.renderListEscaped, + }, + { + data: 'admin_usernames', + title: 'Admins', + defaultContent: '-', + orderable: false, render: Admin.DataTablesHelpers.renderListEscaped, } ] diff --git a/src/api-umbrella/web-app/app/assets/javascripts/admin/views/admins/table_view.js b/src/api-umbrella/web-app/app/assets/javascripts/admin/views/admins/table_view.js index 4ba232c0f..494355b57 100644 --- a/src/api-umbrella/web-app/app/assets/javascripts/admin/views/admins/table_view.js +++ b/src/api-umbrella/web-app/app/assets/javascripts/admin/views/admins/table_view.js @@ -42,6 +42,7 @@ Admin.AdminsTableView = Ember.View.extend({ data: 'group_names', name: 'Groups', title: 'Groups', + orderable: false, render: Admin.DataTablesHelpers.renderListEscaped, }, { diff --git a/src/api-umbrella/web-app/app/models/admin.rb b/src/api-umbrella/web-app/app/models/admin.rb index dd140294d..5a5da48f5 100644 --- a/src/api-umbrella/web-app/app/models/admin.rb +++ b/src/api-umbrella/web-app/app/models/admin.rb @@ -51,9 +51,13 @@ class Admin :group_ids, :as => [:admin] + def self.sorted + order_by(:username.asc) + end + def group_names unless @group_names - @group_names = self.groups.map { |group| group.name } + @group_names = self.groups.sorted.map { |group| group.name } if(self.superuser?) @group_names << "Superuser" end diff --git a/src/api-umbrella/web-app/app/models/admin_group.rb b/src/api-umbrella/web-app/app/models/admin_group.rb index c5fada553..b4448ab5d 100644 --- a/src/api-umbrella/web-app/app/models/admin_group.rb +++ b/src/api-umbrella/web-app/app/models/admin_group.rb @@ -28,11 +28,23 @@ class AdminGroup :api_scope_ids, :as => [:admin] + def self.sorted + order_by(:name.asc) + end + def can?(permission) permissions = self.permission_ids || [] permissions.include?(permission.to_s) end + def admins + @admins ||= Admin.where(:group_ids => self.id).all.sorted + end + + def admin_usernames + @admin_usernames ||= self.admins.map { |admin| admin.username } + end + private def validate_permissions diff --git a/src/api-umbrella/web-app/app/views/api/v1/admin_groups/index.rabl b/src/api-umbrella/web-app/app/views/api/v1/admin_groups/index.rabl index 56cfbd1fd..5a4459cd7 100644 --- a/src/api-umbrella/web-app/app/views/api/v1/admin_groups/index.rabl +++ b/src/api-umbrella/web-app/app/views/api/v1/admin_groups/index.rabl @@ -9,6 +9,7 @@ node :data do data.merge!({ "api_scope_display_names" => admin_group.api_scopes.map { |api_scope| api_scope.display_name }, "permission_display_names" => admin_group.permissions.sorted.map { |permission| permission.name }, + "admin_usernames" => admin_group.admin_usernames, }) data diff --git a/src/api-umbrella/web-app/app/views/api/v1/admin_groups/show.rabl b/src/api-umbrella/web-app/app/views/api/v1/admin_groups/show.rabl index 904441afb..8753a3d31 100644 --- a/src/api-umbrella/web-app/app/views/api/v1/admin_groups/show.rabl +++ b/src/api-umbrella/web-app/app/views/api/v1/admin_groups/show.rabl @@ -7,6 +7,10 @@ attributes :id, :created_at, :updated_at +child :admins, :object_root => false do + attributes :id, :username, :last_sign_in_at +end + child :creator => :creator do attributes :username end diff --git a/src/api-umbrella/web-app/spec/controllers/api/v1/admin_groups_controller_spec.rb b/src/api-umbrella/web-app/spec/controllers/api/v1/admin_groups_controller_spec.rb index 20b2fe728..cd652a469 100644 --- a/src/api-umbrella/web-app/spec/controllers/api/v1/admin_groups_controller_spec.rb +++ b/src/api-umbrella/web-app/spec/controllers/api/v1/admin_groups_controller_spec.rb @@ -1,46 +1,49 @@ require 'spec_helper' describe Api::V1::AdminGroupsController do - before(:all) do + before(:each) do AdminGroup.delete_all - - google_api_scope = FactoryGirl.create(:google_api_scope) - google2_api_scope = FactoryGirl.create(:google_api_scope, :host => "example.com") - yahoo_api_scope = FactoryGirl.create(:yahoo_api_scope) - - @group = FactoryGirl.create(:admin_group) - @google_group = FactoryGirl.create(:admin_group, :admin_manage_permission, :api_scopes => [ - google_api_scope, - google2_api_scope, - ]) - @google_single_scope_group = FactoryGirl.create(:admin_group, :admin_manage_permission, :api_scopes => [ - google_api_scope, - ]) - @unauthorized_google_group = FactoryGirl.create(:admin_group, :user_manage_permission, :api_scopes => [ - google_api_scope, - ]) - @yahoo_group = FactoryGirl.create(:admin_group, :api_scopes => [ - yahoo_api_scope, - ]) - @google_and_yahoo_multi_scope_group = FactoryGirl.create(:admin_group, :api_scopes => [ - google_api_scope, - yahoo_api_scope, - ]) - + Admin.delete_all @admin = FactoryGirl.create(:admin) - @google_admin = FactoryGirl.create(:limited_admin, :groups => [ - @google_group, - ]) - @google_single_scope_admin = FactoryGirl.create(:limited_admin, :groups => [ - @google_single_scope_group, - ]) - @unauthorized_google_admin = FactoryGirl.create(:limited_admin, :groups => [ - @unauthorized_google_group, - ]) end describe "GET index" do describe "admin permissions" do + before(:each) do + google_api_scope = FactoryGirl.create(:google_api_scope) + google2_api_scope = FactoryGirl.create(:google_api_scope, :host => "example.com") + yahoo_api_scope = FactoryGirl.create(:yahoo_api_scope) + + @group = FactoryGirl.create(:admin_group) + @google_group = FactoryGirl.create(:admin_group, :admin_manage_permission, :api_scopes => [ + google_api_scope, + google2_api_scope, + ]) + @google_single_scope_group = FactoryGirl.create(:admin_group, :admin_manage_permission, :api_scopes => [ + google_api_scope, + ]) + @unauthorized_google_group = FactoryGirl.create(:admin_group, :user_manage_permission, :api_scopes => [ + google_api_scope, + ]) + @yahoo_group = FactoryGirl.create(:admin_group, :api_scopes => [ + yahoo_api_scope, + ]) + @google_and_yahoo_multi_scope_group = FactoryGirl.create(:admin_group, :api_scopes => [ + google_api_scope, + yahoo_api_scope, + ]) + + @google_admin = FactoryGirl.create(:limited_admin, :group_ids => [ + @google_group.id, + ]) + @google_single_scope_admin = FactoryGirl.create(:limited_admin, :group_ids => [ + @google_single_scope_group.id, + ]) + @unauthorized_google_admin = FactoryGirl.create(:limited_admin, :group_ids => [ + @unauthorized_google_group.id, + ]) + end + it "includes all groups for superuser admins" do admin_token_auth(@admin) get :index, :format => "json" @@ -93,9 +96,102 @@ data["data"].length.should eql(0) end end + + describe "admin_usernames" do + it "returns an array of admin usernames belonging to the group" do + group = FactoryGirl.create(:admin_group) + admin_in_group = FactoryGirl.create(:limited_admin, :group_ids => [ + group.id, + ]) + + admin_token_auth(@admin) + get :index, :format => "json" + + data = MultiJson.load(response.body) + data["data"].length.should eql(1) + data["data"][0]["admin_usernames"].should eql([admin_in_group.username]) + end + + it "sorts usernames in alphabetical order" do + group = FactoryGirl.create(:admin_group) + admin_in_group1 = FactoryGirl.create(:limited_admin, :username => "b", :group_ids => [ + group.id, + ]) + admin_in_group2 = FactoryGirl.create(:limited_admin, :username => "a", :group_ids => [ + group.id, + ]) + + admin_token_auth(@admin) + get :index, :format => "json" + + data = MultiJson.load(response.body) + data["data"].length.should eql(1) + data["data"][0]["admin_usernames"].should eql([admin_in_group2.username, admin_in_group1.username]) + end + + it "returns an empty array when no admins belong to a group" do + FactoryGirl.create(:admin_group) + + admin_token_auth(@admin) + get :index, :format => "json" + + data = MultiJson.load(response.body) + data["data"].length.should eql(1) + data["data"][0]["admin_usernames"].should eql([]) + end + end end describe "GET show" do + describe "admins" do + it "returns metadata for the admins belonging to the group" do + group = FactoryGirl.create(:admin_group) + admin_in_group = FactoryGirl.create(:limited_admin, :last_sign_in_at => Time.now, :group_ids => [ + group.id, + ]) + + admin_token_auth(@admin) + get :show, :id => group.id, :format => "json" + + data = MultiJson.load(response.body) + data["admin_group"]["admins"].should eql([ + { + "id" => admin_in_group.id, + "username" => admin_in_group.username, + "last_sign_in_at" => admin_in_group.last_sign_in_at.iso8601, + }, + ]) + end + + it "sorts admins by username in alphabetical order" do + group = FactoryGirl.create(:admin_group) + admin_in_group1 = FactoryGirl.create(:limited_admin, :username => "b", :group_ids => [ + group.id, + ]) + admin_in_group2 = FactoryGirl.create(:limited_admin, :username => "a", :group_ids => [ + group.id, + ]) + + admin_token_auth(@admin) + get :show, :id => group.id, :format => "json" + + data = MultiJson.load(response.body) + data["admin_group"]["admins"].map { |admin| admin["id"] }.should eql([ + admin_in_group2.id, + admin_in_group1.id, + ]) + end + + it "returns an empty array when no admins belong to a group" do + group = FactoryGirl.create(:admin_group) + + admin_token_auth(@admin) + get :show, :id => group.id, :format => "json" + + data = MultiJson.load(response.body) + data["admin_group"]["admins"].should eql([]) + end + end end describe "POST create" do