@@ -0,0 +1,42 @@
<%#
Copyright 2011-2015, The Trustees of Indiana University and Northwestern
University. Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
--- END LICENSE_HEADER BLOCK ---
%>
<div id="content" class="col-md-12">
<h1><%= t('blacklight.bookmarks.title') %></h1>

<%- if current_or_guest_user.blank? -%>

<h2><%= t('blacklight.bookmarks.need_login') %></h2>

<%- elsif @document_list.blank? -%>

<h3><%= t('blacklight.bookmarks.no_bookmarks') %></h3>
<% else %>
<%# link_to t('blacklight.bookmarks.clear.action_title'), clear_bookmarks_path, :method => :delete, :data => { :confirm => t('blacklight.bookmarks.clear.action_confirm') }, :class => 'clear-bookmarks btn btn-danger pull-right' %>
<%= render 'sort_and_per_page' %>
<%= render partial: 'tools', locals: { document_list: @document_list } %>
<%= render_document_index %>
<%= render 'results_pagination' %>
<% end %>
</div>

<% content_for :page_styles do %>
<%= stylesheet_link_tag 'jquery-ui/datepicker', media: 'all' %>
<% end %>
<% content_for :page_scripts do %>
<%= javascript_include_tag 'access_control_step' %>
<%= javascript_include_tag 'autocomplete' %>
<% end %>
@@ -0,0 +1,49 @@
<%#
Copyright 2011-2015, The Trustees of Indiana University and Northwestern
University. Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
--- END LICENSE_HEADER BLOCK ---
%>
<% @candidates = get_user_collections %>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h1><%= t('blacklight.move.form.title') %></h1>
</div>

<%= form_tag url_for(:controller => "bookmarks", :action => "move"), :id => 'move_form', :class => "form-horizontal", :method => :post do %>
<div class="modal-body">
<div class="row-fluid">
<div class="btn-options">
<% if @candidates.count == 0 || @documents.empty? %>
<div class="alert alert-danger">
<% if @documents.empty? %>
<p><%= t('blacklight.bookmarks.no_bookmarks') %></p>
<% else %>
<p><%= t('blacklight.move.insufficient_rights') %></p>
<% end %>
</div>
<% else %>
<div class="alert">
<fieldset>
<p><%= t('blacklight.move.confirm') %></p>
<%= select_tag :target_collection_id, options_from_collection_for_select(@candidates, "id", "name") %>
</fieldset>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary"><%= t('blacklight.move.button') %></button>
</div>
<% end %>
</div>
</div>
</div>
<% end %>
@@ -0,0 +1,138 @@
<%#
Copyright 2011-2015, The Trustees of Indiana University and Northwestern
University. Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
--- END LICENSE_HEADER BLOCK ---
%>
<% @media_objects = @documents.collect {|doc| MediaObject.find(doc.id)} %>
<% visibility = @media_objects.first.visibility %>
<% @visibility = visibility if @media_objects.all? {|mo| mo.visibility == visibility} %>
<% @shown = @media_objects.all? {|doc| doc.hidden? == false} %>
<% @hidden = @media_objects.all? {|doc| doc.hidden? == true} %>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h1><%= t('blacklight.update_access_control.form.title') %></h1>
</div>

<%= form_for "add", url: url_for(:controller => "bookmarks", :action => "update_access_control"), html: { :id => 'update_access_control_form', :class => "form-horizontal" } do |form| %>
<div class="modal-body">
<div class="row-fluid">
<div class="btn-options">
<% if @documents.empty? %>
<div class="alert alert-danger">
<p><%= t('blacklight.bookmarks.no_bookmarks') %></p>
</div>
<% else %>
<div class="alert hidden">
<p><%= t('blacklight.update_access_control.confirm') %></p>
</div>
<fieldset class="item-discovery">
<legend>Discovery</legend>
<%= label_tag :hidden do %>
<%= radio_button_tag :hidden, false, @shown %>
Show these items in search results
<br>
<%= radio_button_tag :hidden, true, @hidden %>
Hide these items from search results
<% end %>
</fieldset>
<fieldset class="item-access">
<legend>Item Access</legend>
<%= label_tag :visibility do %>
<%= radio_button_tag :visibility, 'public', (@visibility == 'public') %>
Available to the general public
<% end %>
<%= label_tag :visibility do %>
<%= radio_button_tag :visibility, 'restricted', (@visibility == 'restricted') %>
Logged in users only
<% end %>
<%= label_tag :visibility do %>
<%= radio_button_tag :visibility, 'private', (@visibility == 'private') %>
Collection staff only
<% end %>
</fieldset>
<fieldset class="special-access">
<legend>Special Access</legend>
<%= label_tag "user" do %>
<%= render partial: "modules/tooltip", locals: { form: form, field: 'user', tooltip: t("access_control.user"), options: {display_label: t("access_control.userlabel").html_safe} } %>
<div style='display:inline-block;position:relative'>
<%= hidden_field_tag "user" %>
<%= text_field_tag "user_display", nil,
class: "typeahead from-model form-control",
data: { model: 'user', target: "user" } %><br>
<%= text_field_tag "add_user_begin", nil, placeholder: 'Begin Date (yyyy-mm-dd)', class: 'form-control date-input access_date' %><br>
<%= text_field_tag "add_user_end", nil, placeholder: 'End Date (yyyy-mm-dd)', class: 'form-control date-input access_date' %>
</div>
<%= button_tag "Add", name: 'submit_add_user', class:'btn btn-default', value: 'Add' %>
<%= button_tag "Remove", name: 'submit_remove_user', class:'btn btn-default remove_access', value: 'Remove' %>
<% end %>
<%= label_tag "group" do %>
<%= render partial: "modules/tooltip", locals: { form: form, field: 'group', tooltip: t("access_control.group"), options: {display_label: t("access_control.grouplabel").html_safe} } %>
<% dropdown_values = [Admin::Group.non_system_groups, 'name', 'name'] %>
<% dropdown_values = options_from_collection_for_select(*dropdown_values) %>
<%= select_tag "group",
dropdown_values,
{ include_blank: true, class: "form-control"}%><br>
<%= text_field_tag "add_group_begin", nil, placeholder: 'Begin Date (yyyy-mm-dd)', class: 'form-control date-input access_date' %><br>
<%= text_field_tag "add_group_end", nil, placeholder: 'End Date (yyyy-mm-dd)', class: 'form-control date-input access_date' %>
<%= button_tag "Add", name: 'submit_add_group', class:'btn btn-default', value: 'Add' %>
<%= button_tag "Remove", name: 'submit_remove_group', class:'btn btn-default remove_access', value: 'Remove' %>
<% end %>
<%= label_tag "class" do %>
<%= render partial: "modules/tooltip", locals: { form: form, field: 'class', tooltip: t("access_control.class"), options: {display_label: t("access_control.classlabel").html_safe} } %>
<div style='display:inline-block;position:relative;'>
<%= hidden_field_tag "class" %>
<%= text_field_tag "class_display", nil,
class: "typeahead from-model form-control",
data: { model: 'externalGroup', target: "class" } %><br>
<%= text_field_tag "add_class_begin", nil, placeholder: 'Begin Date (yyyy-mm-dd)', class: 'form-control date-input access_date' %><br>
<%= text_field_tag "add_class_end", nil, placeholder: 'End Date (yyyy-mm-dd)', class: 'form-control date-input access_date' %>
</div>
<%= button_tag "Add", name: 'submit_add_class', class:'btn btn-default', value: 'Add' %>
<%= button_tag "Remove", name: 'submit_remove_class', class:'btn btn-default remove_access', value: 'Remove' %>
<% end %>
<%= label_tag "ipaddress" do %>
<%= render partial: "modules/tooltip", locals: { form: form, field: 'ipaddress', tooltip: t("access_control.ipaddress"), options: {display_label: t("access_control.ipaddresslabel").html_safe} } %>
<div style='display:inline-block;top:1px;position:relative;'>
<%= text_field_tag "ipaddress", nil, class: "form-control" %><br>
<%= text_field_tag "add_ipaddress_begin", nil, placeholder: 'Begin Date (yyyy-mm-dd)', class: 'form-control date-input access_date' %><br>
<%= text_field_tag "add_ipaddress_end", nil, placeholder: 'End Date (yyyy-mm-dd)', class: 'form-control date-input access_date' %>
</div>
<%= button_tag "Add", name: 'submit_add_ipaddress', class:'btn btn-default', value: 'Add' %>
<%= button_tag "Remove", name: 'submit_remove_ipaddress', class:'btn btn-default remove_access', value: 'Remove' %>
<% end %>


</fieldset>
<div class="modal-footer">
<button type="submit" class="btn btn-primary"><%= t('blacklight.update_access_control.button') %></button>
</div>
<% end %>
</div>
</div>
</div>
<% end %>

<script>
$('.tooltip-label').on("click", function(event){
event.preventDefault()
targetNode = $(this).data('tooltip')
$(targetNode).collapse('toggle')
});
$('.help-block .close').on("click", function(event){
event.preventDefault()
$(this).parent().collapse('toggle')
});
$('.typeahead.from-model').each(function() {
initialize_typeahead($(this));
});
</script>
@@ -1,7 +1,7 @@
# windows doesn't properly require hydra-head (from the gemfile), so we need to require it explicitly here:
require 'hydra/head' unless defined? Hydra
# require 'hydra/datastream/rights_metadata'
# require 'hydra/multiple_policy_aware_access_controls_enforcement'
require 'hydra/multiple_policy_aware_access_controls_enforcement'
require 'hydra/multiple_policy_aware_ability'

# TODO: remove the next line after fix is made for this method in hydra-access-controls
@@ -1,4 +1,4 @@
Rails.application.routes.draw do
Rails.application.routes.draw do

mount Blacklight::Engine => '/'
root to: "catalog#index"
@@ -19,6 +19,14 @@

collection do
delete 'clear'
get 'delete'#, as: :delete_bookmarks
post 'delete'
get 'move'#, as: :move_bookmarks
post 'move'
get 'update_access_control'#, as: :update_access_control_bookmarks
post 'update_access_control'
post 'publish'#, as: :publish_bookmarks
post 'unpublish'#, as: :unpublish_bookmarks
end
end

@@ -0,0 +1,81 @@
# Repeats access controls evaluation methods, but checks against a governing "Policy" object (or "Collection" object) that provides inherited access controls.
module Hydra::MultiplePolicyAwareAccessControlsEnforcement

# Extends Hydra::AccessControlsEnforcement.apply_gated_discovery to reflect policy-provided access
# appends the result of policy_clauses into the :fq
# @param solr_parameters the current solr parameters
# @param user_parameters the current user-subitted parameters
def apply_gated_discovery(solr_parameters)
super
Rails.logger.debug("POLICY-aware Solr parameters: #{ solr_parameters.inspect }")
end

# returns solr query for finding all objects whose policies grant discover access to current_user
def policy_clauses
policy_ids = policies_with_access
return nil if policy_ids.empty?
'(' + policy_ids.map {|id| ActiveFedora::SolrQueryBuilder.construct_query_for_rel(isGovernedBy: id)}.join(' OR '.freeze) + ')'
end

# find all the policies that grant discover/read/edit permissions to this user or any of its groups
def policies_with_access
policy_classes.collect do |policy_class|
#### TODO -- Memoize this and put it in the session?
user_access_filters = []
# Grant access based on user id & group
policy_class_clause = policy_class_clause(policy_class)
user_access_filters += apply_policy_group_permissions(discovery_permissions, policy_class_clause)
user_access_filters += apply_policy_user_permissions(discovery_permissions, policy_class_clause)
result = policy_class.search_with_conditions( user_access_filters.join(" OR "), :fl => "id", :rows => policy_class.count )
Rails.logger.debug "get policies: #{result}\n\n"
result.map {|h| h['id']}
end.flatten.uniq
end

def apply_policy_group_permissions(permission_types = discovery_permissions, policy_class_clause = "")
# for groups
user_access_filters = []
current_ability.user_groups.each_with_index do |group, i|
permission_types.each do |type|
user_access_filters << "(" + escape_filter(Hydra.config.permissions.inheritable[type.to_sym].group, group) + policy_class_clause + ")"
end
end
user_access_filters
end

def apply_policy_user_permissions(permission_types = discovery_permissions, policy_class_clause = "")
# for individual user access
user = current_ability.current_user
return [] unless user && user.user_key.present?
permission_types.map do |type|
"(" + escape_filter(Hydra.config.permissions.inheritable[type.to_sym].individual, user.user_key) + policy_class_clause + ")"
end
end

# Returns the Model used for AdminPolicy objects.
# You can set this by overriding this method or setting Hydra.config[:permissions][:policy_class]
# Defults to Hydra::AdminPolicy
def policy_classes
classes = Hydra.config.permissions.policy_class.keys if Hydra.config.permissions.policy_class.is_a? Hash
classes ||= Array(Hydra.config.permissions.policy_class || Hydra::AdminPolicy)
classes
end

def policy_class_clause(klass)
clause = Hydra.config.permissions.policy_class[klass][:clause] if policy_classes.include?(klass)
clause ||= ""
clause
end

protected

def gated_discovery_filters
filters = super
additional_clauses = policy_clauses
unless additional_clauses.blank?
filters << additional_clauses
end
filters
end

end
@@ -0,0 +1,339 @@
# Copyright 2011-2015, The Trustees of Indiana University and Northwestern
# University. Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
# --- END LICENSE_HEADER BLOCK ---

require 'rails_helper'

describe BookmarksController, type: :controller do
render_views

let!(:collection) { FactoryGirl.create(:collection) }
let!(:media_objects) { [] }

before(:each) do
request.env["HTTP_REFERER"] = '/'
Delayed::Worker.delay_jobs = false
login_user collection.managers.first
3.times do
media_objects << mo = FactoryGirl.create(:media_object, collection: collection)
post :create, id: mo.id
end
end

after(:each) do
Delayed::Worker.delay_jobs = true
end

describe "#destroy" do
it "should remove multiple items" do
post :delete
expect(flash[:success]).to eq(I18n.t("blacklight.delete.success", count: 3))
media_objects.each {|mo| expect(MediaObject.exists?(mo.id)).to be_falsey }
end
end

describe "#update_status" do
context 'publishing' do
before(:each) do
Permalink.on_generate { |obj| "http://example.edu/permalink" }
end

it "should publish multiple items" do
post 'publish'
expect(flash[:success]).to eq( I18n.t("blacklight.status.success", count: 3, status: 'publish'))
media_objects.each do |mo|
mo.reload
expect(mo).to be_published
expect(mo.permalink).to be_present
end
end
end

context 'unpublishing' do
it "should unpublish multiple items" do
post 'unpublish'
expect(flash[:success]).to eq( I18n.t("blacklight.status.success", count: 3, status: 'unpublish'))
media_objects.each do |mo|
mo.reload
expect(mo).not_to be_published
end
end
end
end

describe "index" do
context 'action buttons' do
it 'are displayed for authorized user' do
get 'index'
expect(response.body).to have_css('#moveLink')
expect(response.body).to have_css('#publishLink')
expect(response.body).to have_css('#unpublishLink')
expect(response.body).to have_css('#deleteLink')
end
it 'are not displayed for unauthorized user' do
collection.managers = [FactoryGirl.create(:manager).username]
collection.save
get 'index'
expect(response.body).not_to have_css('#moveLink')
expect(response.body).not_to have_css('#publishLink')
expect(response.body).not_to have_css('#unpublishLink')
expect(response.body).not_to have_css('#deleteLink')
end
end
end

describe "#move" do
let!(:collection2) { FactoryGirl.create(:collection) }

context 'user has no permission on target collection' do
it 'responds with error message' do
post 'move', target_collection_id: collection2.id
expect(flash[:error]).to eq( I18n.t("blacklight.move.error", collection_name: collection2.name))
end
end
context 'user has permission on target collection' do
it 'moves items to selected collection' do
collection2.managers = collection.managers
collection2.save
post 'move', target_collection_id: collection2.id
expect(flash[:success]).to eq( I18n.t("blacklight.move.success", count: 3, collection_name: collection2.name))
media_objects.each do |mo|
mo.reload
expect(mo.collection).to eq(collection2)
end
end
end
end

describe '#update_access_control' do
it 'changes to hidden' do
post 'update_access_control', hidden: "true"
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.hidden?).to be_truthy
end
end
it 'changes to shown' do
post 'update_access_control', hidden: "false"
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.hidden?).to be_falsey
end
end
it 'changes the visibility' do
post 'update_access_control', visibility: 'public'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.visibility).to eq 'public'
end
end
context 'Limited access' do
context 'users' do
it 'adds a user to the selected items' do
post 'update_access_control', submit_add_user: 'Add', user: 'cjcolvar'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.read_users).to include 'cjcolvar'
end
end
it 'adds a time-based user to the selected items' do
post 'update_access_control', submit_add_user: 'Add', add_user_begin: Date.yesterday, add_user_end: Date.today, user: 'cjcolvar'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
lease = mo.governing_policies.to_a.find { |gp| gp.is_a? Lease }
expect(lease.inherited_read_users).to include 'cjcolvar'
expect(lease.begin_time).to eq DateTime.parse(Date.yesterday.to_s).utc.beginning_of_day.iso8601
expect(lease.end_time).to eq DateTime.parse(Date.today.to_s).utc.end_of_day.iso8601
end
end

it 'removes a user from the selected items' do
media_objects.each do |mo|
mo.read_users += ["john.doe"]
mo.save
mo.reload
end
post 'update_access_control', submit_remove_user: 'Remove', user: 'john.doe'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.read_users).not_to include 'john.doe'
end
end
it 'removes a time-based user from the selected items' do
media_objects.each do |mo|
mo.governing_policies += [Lease.create(begin_time: Date.today-2.day, end_time: Date.yesterday, inherited_read_users: ['jane.doe'])]
mo.save
mo.reload
end
post 'update_access_control', submit_remove_user: 'Remove', user: 'john.doe'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
leases = mo.governing_policies.to_a.select { |gp| gp.is_a? Lease }
expect(leases.collect{|p|p.inherited_read_users}.flatten.uniq.compact).not_to include 'john.doe'
end
end
end
context 'groups' do
it 'adds a group to the selected items' do
post 'update_access_control', submit_add_group: 'Add', group: 'students'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.read_groups).to include 'students'
end
end
it 'adds a time-based group to the selected items' do
post 'update_access_control', submit_add_group: 'Add', add_group_begin: Date.yesterday, add_group_end: Date.today, group: 'students'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
lease = mo.governing_policies.to_a.find { |gp| gp.is_a? Lease }
expect(lease.inherited_read_groups).to include 'students'
expect(lease.begin_time).to eq DateTime.parse(Date.yesterday.to_s).utc.beginning_of_day.iso8601
expect(lease.end_time).to eq DateTime.parse(Date.today.to_s).utc.end_of_day.iso8601
end
end
it 'removes a group from the selected items' do
media_objects.each do |mo|
mo.read_groups += ["test-group"]
mo.save
mo.reload
end
post 'update_access_control', submit_remove_group: 'Remove', group: 'test-group'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.read_groups).not_to include 'test-group'
end
end
it 'removes a time-based group from the selected items' do
media_objects.each do |mo|
mo.governing_policies += [Lease.create(begin_time: Date.today-2.day, end_time: Date.yesterday, inherited_read_groups: ['test-group'])]
mo.save
mo.reload
end
post 'update_access_control', submit_remove_group: 'Remove', group: 'test-group'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
leases = mo.governing_policies.to_a.select { |gp| gp.is_a? Lease }
expect(leases.collect{|p|p.inherited_read_groups}.flatten.uniq.compact).not_to include 'test-group'
end
end
end
context 'external groups' do
it 'adds an external group to the selected items' do
post 'update_access_control', submit_add_class: 'Add', class: 'ECON-101'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.read_groups).to include 'ECON-101'
end
end
it 'adds a time-based external group to the selected items' do
post 'update_access_control', submit_add_class: 'Add', add_class_begin: Date.yesterday, add_class_end: Date.today, class: 'ECON-101'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
lease = mo.governing_policies.to_a.find { |gp| gp.is_a? Lease }
expect(lease.inherited_read_groups).to include 'ECON-101'
expect(lease.begin_time).to eq DateTime.parse(Date.yesterday.to_s).utc.beginning_of_day.iso8601
expect(lease.end_time).to eq DateTime.parse(Date.today.to_s).utc.end_of_day.iso8601
end
end
it 'removes an external group from the selected items' do
media_objects.each do |mo|
mo.read_groups += ["MUSIC-101"]
mo.save
mo.reload
end
post 'update_access_control', submit_remove_class: 'Remove', class: 'MUSIC-101'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.read_groups).not_to include 'MUSIC-101'
end
end
it 'removes a time-based external group from the selected items' do
media_objects.each do |mo|
mo.governing_policies += [Lease.create(begin_time: Date.today-2.day, end_time: Date.yesterday, inherited_read_groups: ['MUSIC-101'])]
mo.save
mo.reload
end
post 'update_access_control', submit_remove_class: 'Remove', class: 'MUSIC-101'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
leases = mo.governing_policies.to_a.select { |gp| gp.is_a? Lease }
expect(leases.collect{|p|p.inherited_read_groups}.flatten.uniq.compact).not_to include 'MUSIC-101'
end
end
end
context 'ip groups' do
it 'adds an ip group to the selected items' do
post 'update_access_control', submit_add_ipaddress: 'Add', ipaddress: '127.0.0.127'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.read_groups).to include '127.0.0.127'
end
end
it 'adds a time-based ip group to the selected items' do
post 'update_access_control', submit_add_ipaddress: 'Add', add_ipaddress_begin: Date.yesterday, add_ipaddress_end: Date.today, ipaddress: '127.0.0.127'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
lease = mo.governing_policies.to_a.find { |gp| gp.is_a? Lease }
expect(lease.inherited_read_groups).to include '127.0.0.127'
expect(lease.begin_time).to eq DateTime.parse(Date.yesterday.to_s).utc.beginning_of_day.iso8601
expect(lease.end_time).to eq DateTime.parse(Date.today.to_s).utc.end_of_day.iso8601
end
end
it 'removes an ip group from the selected items' do
media_objects.each do |mo|
mo.read_groups += ["127.0.0.127"]
mo.save
mo.reload
end
post 'update_access_control', submit_remove_ipaddress: 'Remove', ipaddress: '127.0.0.127'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
expect(mo.read_groups).not_to include '127.0.0.127'
end
end
it 'removes a time-based ip group from the selected items' do
media_objects.each do |mo|
mo.governing_policies += [Lease.create(begin_time: Date.today-2.day, end_time: Date.yesterday, inherited_read_groups: ['127.0.0.127'])]
mo.save
mo.reload
end
post 'update_access_control', submit_remove_ipaddress: 'Remove', ipaddress: '127.0.0.127'
expect(flash[:success]).to eq( I18n.t("blacklight.update_access_control.success", count: 3))
media_objects.each do |mo|
mo.reload
leases = mo.governing_policies.to_a.select { |gp| gp.is_a? Lease }
expect(leases.collect{|p|p.inherited_read_groups}.flatten.uniq.compact).not_to include '127.0.0.127'
end
end
end
end
end
end