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