diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb index 64c59b12c..784441b3b 100644 --- a/app/controllers/collections_controller.rb +++ b/app/controllers/collections_controller.rb @@ -44,14 +44,6 @@ def create @collection.depositor = current_user @collection.save! - # if (params[:thumbnail]) - # params[:thumbnail] = create_temp_file(params[:thumbnail]) - # @collection.add_thumbnail(:filepath => params[:thumbnail]) - # @collection.save! - # end - # can this be used instead of individually spelling out the methods? - # TapasRails::Application::Queue.push TapasObjectUpsertJob.new params - redirect_to @collection and return end diff --git a/app/controllers/communities_controller.rb b/app/controllers/communities_controller.rb index 93ec30aa3..a22dd34be 100644 --- a/app/controllers/communities_controller.rb +++ b/app/controllers/communities_controller.rb @@ -23,10 +23,8 @@ def upsert def index @page_title = "All Projects" - logger.debug repository.inspect - logger.debug repository.connection + (@response, @document_list) = search_results(params) - (@response, @document_list) = search_results(params) #, search_params_logic) respond_to do |format| format.html { render :template => 'shared/index' } format.js { render :template => 'shared/index', :layout => false } @@ -59,14 +57,10 @@ def new # TODO: CoreFiles can belong to many collections (many-to-many), but will always point back to one project def create - @community = Community.new(community_params) - @community.depositor = current_user - @community.save! + @community = Community.create!(community_params.merge({ depositor_id: current_user.id })) - if (thumbnail_params[:thumbnail]) - # TODO: (pletcher) Create Thumbnail by uploading (to S3?) and saving URL - # Thumbnail.create!(url: url, owner: @community) - end + add_institutions + add_members redirect_to @community end @@ -82,12 +76,33 @@ def edit def update @community = Community.find(params[:id]) @community.community_members.destroy_all - @community.communities_institutions.destroy_all + @community.institutions.destroy_all @community.update(community_params) + add_institutions + add_members + + if params[:community][:remove_thumbnail].present? + @community.thumbnail.purge_later + end + redirect_to @community end + def add_institutions + child_params[:institutions].reject(&:empty?).map { |iid| CommunitiesInstitution.create!(community_id: @community.id, institution_id: iid) } + end + + def add_members + child_params[:project_members].reject(&:empty?).map { |uid| CommunityMember.create(community_id: @community.id, user_id: uid, member_type: 'member') } + child_params[:project_editors].reject(&:empty?).map { |uid| CommunityMember.create!(community_id: @community.id, user_id: uid, member_type: 'editor') } + child_params[:project_admins].reject(&:empty?).map { |uid| CommunityMember.create!(community_id: @community.id, user_id: uid, member_type: 'admin') } + + unless child_params[:project_admins].include?(current_user.id.to_s) + CommunityMember.create!(community_id: @community.id, user_id: current_user.id, member_type: 'admin') + end + end + def destroy community = Community.find(params[:id]) community.discard @@ -115,15 +130,16 @@ def community_params .permit( :description, :thumbnail, - :title, - :institutions => [], - :project_admins => [], - :project_editors => [], - :project_members => [] + :title ) end - def thumbnail_params - params.permit(:thumbnail) + def child_params + params.require(:community).permit( + :institutions => [], + :project_admins => [], + :project_editors => [], + :project_members => [] + ) end end diff --git a/app/controllers/core_files_controller.rb b/app/controllers/core_files_controller.rb index 0957afd63..0a3a096ce 100644 --- a/app/controllers/core_files_controller.rb +++ b/app/controllers/core_files_controller.rb @@ -32,28 +32,13 @@ def index def new @page_title = "Create New Record" - @collections = Collection - .joins(community: :community_members) - .where(community: { community_members: { user_id: current_user.id } }) + @collections = Collection.accessible_by(current_ability) @core_file = CoreFile.new(is_public: true) @users = User.order(:name) - - # FIXME: (charles) What is this supposed to do? - @file_types = [['TEI Record',""]] - @sel_file_types = [] - CoreFile.all_ography_types.each do |o| - @file_types << [o.titleize,o] - end end def create - file = CoreFile.new(core_file_params.merge({ depositor_id: current_user.id })) - - params[:core_file][:collections].each do |c| - file.collections << Collection.find(c) unless c.blank? - end - - file.save! + file = CoreFile.create!(core_file_params.merge({ depositor_id: current_user.id })) redirect_to file end @@ -61,7 +46,7 @@ def create def destroy file = CoreFile.find(params[:id]) # FIXME: (charles) Should go to the collection where the user is, but the routes aren't set up RESTfully - collection = file.collections.first + collection = file.collections.kept.first file.destroy! @@ -70,40 +55,17 @@ def destroy def edit @core_file = CoreFile.find(params[:id]) - - @collections = @core_file.collections - - @file_types = [['TEI Record',""]] - @sel_file_types = [] - CoreFile.all_ography_types.each do |o| - @file_types << [o.titleize,o] - end - @core_file.ography_type.each do |o| - @sel_file_types << o - end - if @sel_file_types.blank? - @sel_file_types << "" - end - + @collections = Collection.accessible_by(current_ability) + @users = User.order(:name) @page_title = "Edit #{@core_file.title}" end #This method contains the logic for editing/submission of edit form def update cf = CoreFile.find(params[:id]) - params[:did] = cf.did - if params[:core_file][:remove_thumbnail] == "1" - params[:core_file].delete :thumbnail - cf.thumbnails = [] - cf.save! - end - params[:core_file].delete :remove_thumbnail - params[:file_types].reject! { |c| c.blank? } - logger.warn("we are about to edit #{params[:did]}") - logger.warn params + cf.update(core_file_params) - create - redirect_to cf and return + redirect_to cf end def view_package_html @@ -141,7 +103,7 @@ def rebuild_reading_interfaces pretty_json(200) and return end - def show #inherited from catalog controller + def show @core_file = CoreFile.find(params[:id]) end @@ -232,14 +194,15 @@ def can_read? def core_file_params params.require(:core_file).permit( - :authors, :canonical_object, :collections, - :contributors, :depositor, :description, - :thumbnails, - :title + :featured, + :title, + :authors => [], + :contributors => [], + :thumbnails => [] ) end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index eb5b5cf63..9f314a161 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,7 +2,7 @@ class UsersController < CatalogController self.copy_blacklight_config_from(CatalogController) before_action :check_for_logged_in_user, :only => [:my_tapas, :my_projects] - # before_action :verify_admin, :only => [:index, :show, :create] + before_action :verify_admin, :only => [:index, :show, :create, :delete] def my_tapas @page_title = "My TAPAS" @@ -78,6 +78,18 @@ def update redirect_to @user end + def destroy + user = User.find(params[:id]) + + if user.discarded? + user.delete + else + user.discard + end + + redirect_to users_path + end + def search_action_url(options = {}) # Rails 4.2 deprecated url helpers accepting string keys for 'controller' or 'action' # catalog_index_path(options.except(:controller, :action)) @@ -103,22 +115,21 @@ def mail_all_users private def five_communities - @user.communities.limit(5).order("RAND()") + @user.communities.kept.limit(5).order("RAND()") end def five_collections Collection - .joins(community: :community_members) - .where(community: { community_members: { user_id: @user.id } }) + .kept + .accessible_by(current_ability) .limit(5) .order("RAND()") - end def five_records CoreFile - .joins(collections: { community: :community_members }) - .where(collections: { community: { community_members: { user_id: @user.id } } }) + .kept + .accessible_by(current_ability) .limit(5) .order("RAND()") end diff --git a/app/models/community.rb b/app/models/community.rb index 61eafc880..e53329dce 100644 --- a/app/models/community.rb +++ b/app/models/community.rb @@ -14,59 +14,16 @@ class Community < ActiveRecord::Base belongs_to :depositor, class_name: "User" - has_many_attached :thumbnails + has_one_attached :thumbnail validates_presence_of :title - # Look up or create the root community of the graph - # FIXME: (charles) I'm not sure why communities are related in a graph here -- is this used anywhere, or can we drop it? - # def self.root_community - # if Community.exists?(Rails.configuration.tap_root) - # Community.find(Rails.configuration.tap_root) - # else - # community = Community.new(:pid => Rails.configuration.tap_root, :title => "Root community") - # community.depositor = "000000000" - # community.mass_permissions = "private" - # community.save! - # return community - # end - # end - - def create_members(user_ids = [], member_type = 'member') - # NOTE: (charles) This means that the order in which CommunityMembers are created matters: the last - # (community_id, user_id, member_type) will prevail for that community_id + user_id. In other words, - # selecting the same user in multiple roles is undefined behavior. - - user_ids.reject(&:empty?).each do |uid| - CommunityMember.find_or_create_by(community_id: id, user_id: uid, member_type: member_type) - end - end - - def institutions=(institution_ids) - puts "creating institutions" - institution_ids.reject(&:empty?).each do |iid| - CommunitiesInstitution.find_or_create_by(community_id: id, institution_id: iid) - end - end - - def project_members=(user_ids) - create_members(user_ids) - end - def project_members - users - end - - def project_editors=(user_ids) - create_members(user_ids, 'editor') + users.where(community_members: { member_type: "member" }) end def project_editors - users.where(community_members: { member_type: ["editor", "admin"] }) - end - - def project_admins=(user_ids) - create_members(user_ids, 'admin') + users.where(community_members: { member_type: "editor" }) end def project_admins diff --git a/app/models/core_file.rb b/app/models/core_file.rb index f63b7e5c6..243993b60 100644 --- a/app/models/core_file.rb +++ b/app/models/core_file.rb @@ -1,50 +1,6 @@ class CoreFile < ActiveRecord::Base - # include Did - # include OGReference - # include DrupalAccess - # include TapasQueries - # include StatusTracking - # include SolrHelpers - # include TapasRails::ViewPackages - - # Configure mods_display gem - # include ModsDisplay::ModelExtension - # mods_xml_source do |model| - # model.mods.content - # end - - # before_save :match_dc_to_mods - - # before_save :ensure_unique_did, :calculate_drupal_access - - # has_and_belongs_to_many :collections, :property => :is_member_of, - # :class_name => 'Collection' - - # has_many :page_images, :property => :is_page_image_for, - # :class_name => "ImageMasterFile" - # has_many :tfc, :property => :is_tfc_for, :class_name => "TEIFile" - # has_many :html_files, :property => :is_html_for, :class_name => "HTMLFile" - - # has_and_belongs_to_many :personography_for, :property => :is_personography_for, - # :class_name => 'Collection' - # has_and_belongs_to_many :orgography_for, :property => :is_orgography_for, - # :class_name => 'Collection' - # has_and_belongs_to_many :bibliography_for, :property => :is_bibliography_for, - # :class_name => 'Collection' - # has_and_belongs_to_many :otherography_for, :property => :is_otherography_for, - # :class_name => 'Collection' - # has_and_belongs_to_many :odd_file_for, :property => :is_odd_file_for, - # :class_name => 'Collection' - # has_and_belongs_to_many :placeography_for, :property => :is_placeography_for, - # :class_name => 'Collection' - - # has_metadata :name => "mods", :type => ModsDatastream - # has_metadata :name => "properties", :type => PropertiesDatastream - # has_attributes :title, datastream: "DC" - # has_attributes :description, datastream: "DC" - # has_attributes :featured, :datastream => :properties, :multiple => false - # delegate :authors, to: "mods" - # delegate :contributors, to: "mods" + include Discard::Model + belongs_to :depositor, class_name: "User" has_and_belongs_to_many :users @@ -64,22 +20,28 @@ def self.all_ography_read_methods end def authors - users.where(user_type: "author") + users.where(core_files_users: { user_type: "author" }) end def authors=(user_ids) user_ids.reject(&:blank?).each do |user_id| - UsersCoreFile.find_or_create_by(core_file_id: id, user_id: user_id, user_type: "author") + CoreFilesUser.find_or_create_by(core_file_id: id, user_id: user_id, user_type: "author") end end def contributors - users.where(user_type: "contributor") + users.where(core_files_users: { user_type: "contributor" }) end def contributors=(user_ids) user_ids.reject(&:blank?).each do |user_id| - UsersCoreFile.find_or_create_by(core_file_id: id, user_id: user_id, user_type: "contributor") + CoreFilesUser.find_or_create_by(core_file_id: id, user_id: user_id, user_type: "contributor") + end + end + + def collections=(collection_ids) + collection_ids.reject(&:blank?).each do |collection_id| + collections << Collection.find(collection_id) end end diff --git a/app/models/users_core_file.rb b/app/models/core_files_user.rb similarity index 71% rename from app/models/users_core_file.rb rename to app/models/core_files_user.rb index d9a29c83f..9bf98c63a 100644 --- a/app/models/users_core_file.rb +++ b/app/models/core_files_user.rb @@ -1,4 +1,4 @@ -class UsersCoreFile < ActiveRecord::Base +class CoreFilesUser < ActiveRecord::Base belongs_to :user belongs_to :core_file diff --git a/app/models/user.rb b/app/models/user.rb index cf6ad56f5..5f4c748d8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,6 @@ class User < ActiveRecord::Base + include Discard::Model + require "net/http" require "uri" # Connects this user object to Hydra behaviors. @@ -25,8 +27,6 @@ class User < ActiveRecord::Base has_many :community_members has_many :communities, through: :community_members - ROLES = %w[admin paid_user unpaid_user] - ACCOUNT_TYPES = %w[free teic teic_inst] def api_key=(api_key) @@ -62,15 +62,15 @@ def unpaid_user? end def self.find_by_user_key(key) - self.send("find_by_nuid".to_sym, key) + send("find_by_nuid".to_sym, key) end def forem_name - self.name + name end def forem_email - self.email + email end def check_paid_status @@ -124,15 +124,15 @@ def after_database_authentication private - def generate_api_key - key = Devise.friendly_token + def generate_api_key + key = Devise.friendly_token - @api_key = Digest::SHA512.hexdigest key + @api_key = Digest::SHA512.hexdigest key - if User.where(:encrypted_api_key => @api_key) - generate_api_key - else - self.encrypted_api_key = @api_key - end + if User.where(:encrypted_api_key => @api_key) + generate_api_key + else + self.encrypted_api_key = @api_key end + end end diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml index 01003ea50..555d9f944 100644 --- a/app/views/admin/index.html.haml +++ b/app/views/admin/index.html.haml @@ -42,7 +42,7 @@ %h3 = "Forums" -= link_to "Forum Admin", forem.admin_root_url, class:['btn', 'btn-primary', 'btn-large'] +-# = link_to "Forum Admin", forem.admin_root_url, class:['btn', 'btn-primary', 'btn-large'] %h3 = "Resque Workers" diff --git a/app/views/communities/_data_form.html.haml b/app/views/communities/_data_form.html.haml index 43e1ac034..086caceea 100644 --- a/app/views/communities/_data_form.html.haml +++ b/app/views/communities/_data_form.html.haml @@ -15,13 +15,13 @@ = f.label :is_public, "Public?", class: "control-label col-md-2" = f.check_box :is_public, { checked: true } .form-group - = f.label :thumbnail, "Thumbnail", name: 'thumbnail', class: "control-label col-md-2" + = f.label :thumbnail, "Thumbnail", class: "control-label col-md-2" .col-md-6 - - if !@community.thumbnails.blank? - =image_tag @community.download_path('thumbnail_1') + - if @community.thumbnail.attached? + =image_tag url_for(@community.thumbnail) = f.label :remove_thumbnail, "Remove Thumbnail" = f.check_box "remove_thumbnail", {:checked => false} - = f.file_field :thumbnail, accept: ".jpeg, .jpeg, .png", name: "thumbnail" + = f.file_field :thumbnail, accept: ".jpeg, .jpeg, .png", direct_upload: true .row.form-group.institutions diff --git a/app/views/communities/show.html.haml b/app/views/communities/show.html.haml index 2d813c291..ef4358484 100644 --- a/app/views/communities/show.html.haml +++ b/app/views/communities/show.html.haml @@ -6,10 +6,10 @@ %div.row %div.col-md-3 - - if @community.thumbnails.blank? + - if !@community.thumbnail.attached? =image_tag "tapaslogo-opaque.png" -else - %img{src:@community.thumbnails.first} + %img{src: url_for(@community.thumbnail)} %dt= "Description" %dd= @community.description -# external links TODO diff --git a/app/views/core_files/_data_form.html.haml b/app/views/core_files/_data_form.html.haml index 8c2937dd0..e5f17ada4 100644 --- a/app/views/core_files/_data_form.html.haml +++ b/app/views/core_files/_data_form.html.haml @@ -16,19 +16,19 @@ = f.label :authors, "Authors", class: "control-label col-md-2" .col-md-6 %span.author - = f.select :authors, options_from_collection_for_select(@users, 'id', 'email'), {}, {class: "form-control", multiple: true} + = f.select :authors, options_from_collection_for_select(@users, 'id', 'email', @core_file.authors.map(&:id)), {}, {class: "form-control", multiple: true} | .form-group.contributors = f.label :contributors, "Contributors", class: "control-label col-md-2" .col-md-6 %span.contributor - = f.select :contributors, options_from_collection_for_select(@users, 'id', 'email'), {}, { class: "form-control", multiple: true } + = f.select :contributors, options_from_collection_for_select(@users, 'id', 'email', @core_file.contributors.map(&:id)), {}, { class: "form-control", multiple: true } .form-group = f.label :collections, "Collection", class: "control-label col-md-2" .col-md-6 %span.collection - = f.select :collections, options_from_collection_for_select(@collections, 'id', 'title'), {}, {class: "form-control", multiple: true} + = f.select :collections, options_from_collection_for_select(@collections, 'id', 'title', @core_file.collections.map(&:id)), {}, {class: "form-control", multiple: true} -# TODO: (charles) Figure out why we need Ography Type and reimplement it -# .form-group @@ -40,10 +40,9 @@ - if current_user.admin? .form-group - = f.label :featured, class: "control-label col-md-2" + = f.label :featured, "Featured?", class: "control-label col-md-2" .col-md-6 - .checkbox - = f.check_box :featured, {}, "true" + = f.check_box :featured, {}, true .form-group = f.label :canonical_object, "File", class: "control-label col-md-2" .col-md-6 @@ -59,13 +58,14 @@ .col-md-6 = f.check_box :is_public, { checked: true } .form-group - = f.label :thumbnail, "Thumbnail", class: "control-label col-md-2" + = f.label :thumbnails, "Thumbnails", class: "control-label col-md-2" .col-md-6 - - if @core_file.thumbnail.attached? - =image_tag url_for(@core_file.thumbnail) + - if @core_file.thumbnails.attached? + - @core_file.thumbnails.each do |t| + =image_tag url_for(t) = f.label :remove_thumbnail, "Remove Thumbnail" = f.check_box "remove_thumbnail", {:checked => false} - = f.file_field :thumbnail, accept: ".jpeg, .jpeg, .png", direct_upload: true + = f.file_field :thumbnails, accept: ".jpeg, .jpeg, .png", direct_upload: true, multiple: true -# TODO add support_files? diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml index a819f7819..c3fb266fb 100644 --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -13,6 +13,8 @@ = "Last Login" %th = "Role" + %th + = "Discarded at" - @users.each do |user| %tr %td @@ -21,12 +23,21 @@ - if current_user.try(:admin?) %a.btn.btn-default.btn-sm{:href=>edit_user_path(user.id)} = "Edit" + = link_to "Delete", user_path(user.id), class: ['btn', 'btn-default', 'btn-sm', 'btn-danger'], method: :delete, data: { confirm: "Are you sure you want to delete #{user.name}?" } %td = user.updated_at %td = user.current_sign_in_at %td - - if user.role - = user.role.gsub("_"," ").titleize + - if !user.admin_at.nil? + = "Admin" + - elsif !user.paid_at.nil? + = "Paid user" + - else + = "Unpaid user" + %td + - unless user.discarded_at.nil? + = user.discarded_at + = link_to "Really delete", user_path(user.id), class: ['btn', 'btn-default', 'btn-sm', 'btn-danger'], method: :delete, data: { confirm: "Are you sure you want to delete #{user.name} for real? This record will no longer exist." } -else There are currently no users available diff --git a/config/routes.rb b/config/routes.rb index a886026e5..3634c5849 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -84,7 +84,7 @@ get 'users/:id' => 'users#profile' get 'mail_users' => 'users#mail_all_users', as: 'mail_users' post 'mail_users' => 'users#mail_all_users' - resources :users, :only => ['index', 'edit', 'create', 'update'] + resources :users, :only => ['index', 'edit', 'create', 'update', 'destroy'] resources :menu_links, path: "/menu" post 'update_menu_order' => 'menu_links#update_menu_order' diff --git a/db/migrate/20200725202301_add_featured_to_core_files.rb b/db/migrate/20200725202301_add_featured_to_core_files.rb new file mode 100644 index 000000000..0a1e28b5d --- /dev/null +++ b/db/migrate/20200725202301_add_featured_to_core_files.rb @@ -0,0 +1,5 @@ +class AddFeaturedToCoreFiles < ActiveRecord::Migration[5.2] + def change + add_column :core_files, :featured, :boolean + end +end diff --git a/db/migrate/20200726214450_add_discarded_at_to_core_files.rb b/db/migrate/20200726214450_add_discarded_at_to_core_files.rb new file mode 100644 index 000000000..ca30bc86d --- /dev/null +++ b/db/migrate/20200726214450_add_discarded_at_to_core_files.rb @@ -0,0 +1,6 @@ +class AddDiscardedAtToCoreFiles < ActiveRecord::Migration[5.2] + def change + add_column :core_files, :discarded_at, :datetime + add_index :core_files, :discarded_at + end +end diff --git a/db/migrate/20200726221259_add_discarded_at_to_users.rb b/db/migrate/20200726221259_add_discarded_at_to_users.rb new file mode 100644 index 000000000..33782914e --- /dev/null +++ b/db/migrate/20200726221259_add_discarded_at_to_users.rb @@ -0,0 +1,6 @@ +class AddDiscardedAtToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :discarded_at, :datetime + add_index :users, :discarded_at + end +end diff --git a/db/schema.rb b/db/schema.rb index b935e164a..1f097f450 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_07_25_165611) do +ActiveRecord::Schema.define(version: 2020_07_26_221259) do create_table "active_storage_attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "name", null: false @@ -141,6 +141,9 @@ t.datetime "updated_at", null: false t.boolean "is_public", default: true t.integer "depositor_id", null: false + t.boolean "featured" + t.datetime "discarded_at" + t.index ["discarded_at"], name: "index_core_files_on_discarded_at" end create_table "core_files_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| @@ -333,7 +336,9 @@ t.text "account_type" t.datetime "admin_at" t.datetime "paid_at" + t.datetime "discarded_at" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true + t.index ["discarded_at"], name: "index_users_on_discarded_at" t.index ["email"], name: "index_users_on_email", unique: true t.index ["institution_id"], name: "index_users_on_institution_id" t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true