Skip to content

Commit

Permalink
User management of ingestion sources with admin approval TEMP
Browse files Browse the repository at this point in the history
  • Loading branch information
fbacall committed Nov 9, 2022
1 parent 4fd50d3 commit 830f626
Show file tree
Hide file tree
Showing 21 changed files with 320 additions and 66 deletions.
43 changes: 28 additions & 15 deletions app/controllers/sources_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
class SourcesController < ApplicationController

before_action :set_source, only: [:show, :edit, :update, :destroy]
before_action :set_content_provider, only: [:index, :new, :create]
before_action :set_content_provider
before_action :set_content_provider_for_admin, only: [:create, :update]
before_action :set_breadcrumbs

include SearchableIndex
Expand Down Expand Up @@ -38,8 +39,7 @@ def edit
# POST /sources.json
def create
authorize Source
@source = Source.new(source_params)
@source.created_at = Time.now
@source = @content_provider.sources.build(source_params)
@source.user = current_user

respond_to do |format|
Expand Down Expand Up @@ -101,15 +101,18 @@ def destroy

private

def set_content_provider_for_admin
if policy(Source).administration?
@content_provider ||= ContentProvider.friendly.find_by_id(source_params[:content_provider_id])
end
end

def set_content_provider
@content_provider = nil
slug = params[:content_provider]
@content_provider = ContentProvider.find_by_slug(slug) unless slug.nil?
if @content_provider.nil?
id = params[:content_provider_id]
@content_provider = ContentProvider.find(id) unless id.nil?
@content_provider ||= ContentProvider.friendly.find_by_id(params[:content_provider_id])
unless policy(Source).administration? && ['index', 'create', 'new'].include?(action_name)
raise ActiveRecord::RecordNotFound unless @content_provider
authorize @content_provider, :manage?
end
@content_provider
end

# Use callbacks to share common setup or constraints between actions.
Expand All @@ -119,11 +122,21 @@ def set_source

# Never trust parameters from the scary internet, only allow the white list through.
def source_params
params.require(:source).permit(:content_provider_id, :created_at,
:url, :method, :finished_at,
:records_read, :records_written, :token,
:resources_added, :resources_updated,
:resources_rejected, :log, :enabled )
permitted = [:url, :method, :token, :enabled]
permitted << :approval_status if policy(Source).approve?
permitted << :content_provider_id if policy(Source).index?

params.require(:source).permit(permitted)
end

def set_breadcrumbs
if @content_provider
add_base_breadcrumbs('content_providers')
add_show_breadcrumb(@content_provider)
add_breadcrumb 'New Source', new_content_provider_source_path(@content_provider)
else
super
end
end

end
2 changes: 2 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ def icon_class_for_model(model)
'fa fa-sitemap'
when 'nodes'
'fa fa-share-alt'
when 'sources'
'fa fa-cloud-download'
else
'fa fa-folder-open'
end
Expand Down
15 changes: 15 additions & 0 deletions app/helpers/sources_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,19 @@ def grouped_ingestor_options_for_select

opts
end

def source_enabled_badge(enabled)
content_tag(:span, enabled ? 'Enabled' : 'Disabled', class: "label label-#{enabled ? 'success' : 'danger'}")
end

def source_approval_badge(status)
case status
when :not_approved
content_tag(:span, t("sources.approval_status.#{status}"), class: 'label label-danger')
when :approval_requested
content_tag(:span, t("sources.approval_status.#{status}"), class: 'label label-warning')
when :approved
content_tag(:span, t("sources.approval_status.#{status}"), class: 'label label-success')
end
end
end
2 changes: 1 addition & 1 deletion app/models/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def self.facet_fields
end

def self.visible_by(user)
if user && user.is_admin?
if user&.is_admin?
all
elsif user
references(:collaborations).includes(:collaborations).
Expand Down
4 changes: 2 additions & 2 deletions app/models/concerns/searchable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def search_and_filter(user, search_params = '', selected_facets = {}, page: 1, s
end
end

if attribute_method?(:public) && !(user && user.is_admin?) # Find a better way of checking this
if attribute_method?(:public) && !user&.is_admin? # Find a better way of checking this
any_of do
with(:public, true)
with(:user_id, user.id) if user
Expand All @@ -99,7 +99,7 @@ def search_and_filter(user, search_params = '', selected_facets = {}, page: 1, s

# Hide records the urls of which are failing
if method_defined?(:link_monitor)
unless user && user.is_admin?
unless user&.is_admin?
without(:failing, true)
end
end
Expand Down
56 changes: 55 additions & 1 deletion app/models/source.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
class Source < ApplicationRecord
APPROVAL_STATUS = {
0 => :not_approved,
1 => :requested,
2 => :approved
}.freeze

APPROVAL_STATUS_CODES = APPROVAL_STATUS.invert.freeze

include PublicActivity::Model
include Searchable

Expand All @@ -7,8 +15,12 @@ class Source < ApplicationRecord

validates :url, :method, presence: true
validates :url, url: true
validates :approval_status, inclusion: { in: APPROVAL_STATUS.values }
validate :check_method

before_save :set_approval_status
after_update :log_approval_status_change

if TeSS::Config.solr_enabled
# :nocov:
searchable do
Expand All @@ -24,6 +36,9 @@ class Source < ApplicationRecord
string :content_provider do
self.content_provider.try(:title)
end
string :approval_status do
I18n.t("sources.approval_status.#{approval_status}")
end
integer :user_id
boolean :enabled
end
Expand All @@ -44,7 +59,7 @@ def ingestor_class
end

def self.facet_fields
%w( content_provider method enabled )
%w( content_provider method enabled approval_status )
end

def self.check_exists(source_params)
Expand All @@ -58,10 +73,49 @@ def self.check_exists(source_params)
source
end

def self.enabled
where(enabled: true)
end

def check_method
c = ingestor_class rescue nil
if c.nil?
errors.add(:method, 'is invalid')
end
end

def self.approved
where(approval_status: APPROVAL_STATUS_CODES[:approved])
end

def self.approval_requested
where(approval_status: APPROVAL_STATUS_CODES[:requested])
end

def approval_status
APPROVAL_STATUS[super] || APPROVAL_STATUS[0]
end

def approval_status=(key)
super(APPROVAL_STATUS_CODES[key.to_sym])
end

private

def set_approval_status
if TeSS::Config.feature['source_approval'] && !User.current_user&.is_admin?
self.approval_status = :not_approved
else
self.approval_status = :approved
end
end

def log_approval_status_change
if saved_change_to_approval_status?
old = (APPROVAL_STATUS[approval_status_before_last_save.to_i] || APPROVAL_STATUS[0]).to_s
new = approval_status.to_s
create_activity(:approval_status_changed, owner: User.current_user,
parameters: { old: old, new: new })
end
end
end
40 changes: 28 additions & 12 deletions app/policies/source_policy.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
class SourcePolicy < ApplicationPolicy

class SourcePolicy < ResourcePolicy
def show?
@user && !@user.role.blank?
manage?
end

def manage?
@user && (
@user.has_role?(:curator) ||
@user.has_role?(:admin) ||
@user.has_role?(:scraper_user))
if TeSS::Config.feature['source_approval']
super
else
administration?
end
end

def index?
show?
administration?
end

def new?
manage?
def create?
if TeSS::Config.feature['source_approval']
super
else
administration?
end
end

def create?
manage?
def approve?
@user && @user.has_role?(:admin)
end

def administration? # Can edit sources for any content provider
curators_and_admin
end

private

def curators_and_admin
@user && (
@user.has_role?(:curator) ||
@user.has_role?(:admin) ||
@user.has_role?(:scraper_user))
end
end
28 changes: 19 additions & 9 deletions app/views/content_providers/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<% events = @content_provider.events.from_verified_users %>
<% materials = @content_provider.materials.from_verified_users %>
<% sources = @content_provider.sources %>

<div class="wrapper collapsing-wrapper">
<%# SIDEBAR %>
Expand All @@ -9,15 +10,6 @@
</div>
<div id="content">
<div class="row">
<% if !current_user.nil? and policy(@content_provider).update? and TeSS::Config.feature['sources'] %>
<div class="content_action pull-left">
<%= link_to sources_path(content_provider: @content_provider.title),
class: 'btn btn-primary align-self-end' do %>
Ingestion Sources
<% end %>
</div>
<% end %>

<div class="content_action pull-right">
<%= link_to t('.back', :default => t("helpers.links.back")),
content_providers_path, :class => 'btn btn-info' %>
Expand Down Expand Up @@ -78,6 +70,10 @@
disabled: { check: events.none?, message: 'No associated events' },
count: events.count) %>

<% if TeSS::Config.feature['source_approval'] && policy(@content_provider).update? %>
<%= tab('Sources', icon_class_for_model('sources'), 'sources', count: sources.count) %>
<% end %>

<%= tab('Activity log', icon_class_for_model('activity_logs'), 'activity_log',
disabled: { check: @content_provider.activities.none?, message: 'No activities recorded' }) %>
</ul>
Expand Down Expand Up @@ -122,6 +118,20 @@
</div>
</div>
</div>
<% if policy(@content_provider).update? && TeSS::Config.feature['sources'] %>
<p id="sources" class="tab-pane fade">
<% if policy(Source).new? %>
<p>
<%= link_to new_content_provider_source_path(@content_provider), class: 'btn btn-primary' do %>
<i class="fa fa-plus-square"></i> Add source
<% end %>
</p>
<% end %>
<div class="row">
<%= render partial: 'common/masonry_grid', locals: { objects: sources } %>
</div>
</div>
<% end %>
<div id="activity_log" class="tab-pane fade" data-activity-path="<%= content_provider_activities_path(@content_provider) -%>">
<%= image_tag('ajax-loader.gif') %>
</div>
Expand Down
8 changes: 2 additions & 6 deletions app/views/sources/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
<%= simple_form_for @source, html: { class: 'source', multipart: true } do |f| %>

<%= simple_form_for (@content_provider ? [@content_provider, @source] : @source), html: { class: 'source', multipart: true } do |f| %>
<%= render partial: 'common/error_summary', locals: { resource: @source } %>

<% if @content_provider.nil? %>
<% unless @content_provider %>
<%= f.input :content_provider_id,
collection: current_user.get_editable_providers,
label_method: :title,
value_method: :id,
include_blank: false %>
<% else %>
<h4>Provider: <%= @content_provider.title %></h4>
<%= f.hidden_field :content_provider_id, value: @content_provider.id %>
<% end %>

<%= render partial: 'common/url_checker',
Expand Down
5 changes: 2 additions & 3 deletions app/views/sources/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
<div id="content">
<div class="row">
<div class="content_action pull-left">
<% if !current_user.nil? and (current_user.is_curator? or current_user.is_admin?) %>
<%= link_to new_source_path(content_provider: @content_provider),
class: 'btn btn-primary' do %>
<% if policy(Source).new? %>
<%= link_to new_source_path(content_provider: @content_provider), class: 'btn btn-primary' do %>
<i class="fa fa-plus-square"></i> Create source
<% end %>
<% end %>
Expand Down
Loading

0 comments on commit 830f626

Please sign in to comment.