WIP migrating to wide ContentPage usage

This commit is contained in:
Andrew Brown 2021-08-09 01:29:58 -07:00
parent b12900a59b
commit 5c972738db
7 changed files with 131 additions and 28 deletions

View File

@ -0,0 +1,48 @@
class ContentPageAuthorizer < CoreContentAuthorizer
def self.creatable_by?(user)
return false unless user.present?
return false if ENV.key?('CONTENT_BLACKLIST') && ENV['CONTENT_BLACKLIST'].split(',').include?(user.email)
if resource.page_type == 'Universe'
return true if PermissionService.user_has_fewer_owned_universes_than_plan_limit?(user: user)
else
is_premium_page = Rails.application.config.content_types[:premium].include?(resource.page_type)
return true if !is_premium_page
return true if is_premium_page && PermissionService.user_is_on_premium_plan?(user: user)
end
return false
end
def readable_by?(user)
return true if PermissionService.content_is_public?(content: resource)
return true if PermissionService.user_owns_content?(user: user, content: resource)
if resource.page_type == 'Universe'
return true if PermissionService.user_can_contribute_to_universe?(user: user, universe: resource)
else
return true if PermissionService.user_can_contribute_to_containing_universe?(user: user, content: resource)
end
return false
end
def updatable_by?(user)
return true if PermissionService.user_owns_content?(user: user, content: resource)
if resource.page_type == 'Universe'
return true if PermissionService.user_can_contribute_to_universe?(user: user, universe: resource)
else
return true if PermissionService.user_can_contribute_to_containing_universe?(user: user, content: resource)
end
return false
end
def deletable_by?(user)
[
PermissionService.user_owns_content?(user: user, content: resource)
].any?
end
end

View File

@ -177,6 +177,7 @@ class ApplicationController < ActionController::Base
end
filtered_fields = ContentPage.polymorphic_content_fields.map(&:to_s)
filtered_fields.push 'universe_id' unless page_type == Universe.name
pages_to_add.each do |page_data|
filtered_page_data = page_data.attributes.slice(*filtered_fields)
@linkables_raw[page_type].push ContentPage.new(filtered_page_data)

View File

@ -21,33 +21,45 @@ class ContentController < ApplicationController
before_action :set_sidenav_expansion, except: [:api_sort]
def index
cache_linkable_content_for_each_content_type
@content_type_class = content_type_from_controller(self.class)
pluralized_content_name = @content_type_class.name.downcase.pluralize
@page_title = "My #{pluralized_content_name}"
# Create the default fields for this user if they don't have any already
# TODO: uh, this probably doesn't belong here!
@content_type_class.attribute_categories(current_user)
if @universe_scope.present? && @content_type_class != Universe
@content = @universe_scope.send(pluralized_content_name)
.includes(:page_tags, :image_uploads)
.unarchived
# Linkables cache is already scoped per-universe, includes contributor pages
@content = @linkables_raw.fetch(@content_type_class.name, [])
@show_scope_notice = true
else
@content = (
current_user.send(pluralized_content_name).unarchived.includes(:page_tags, :image_uploads) +
current_user.send("contributable_#{pluralized_content_name}").unarchived.includes(:page_tags, :image_uploads)
)
@show_scope_notice = @universe_scope.present? && content_type_class != Universe
if @content_type_class != Universe
my_universe_ids = current_user.universes.pluck(:id)
@content.concat(@content_type_class.where(universe_id: my_universe_ids).unarchived)
end
end
# if @universe_scope.present? && @content_type_class != Universe
# # Linkables cache is already scoped per-universe
@content = @content.to_a.flatten.uniq
# @content = @current_user_content.fetch(@content_type_class.name, [])
# .select { |page| page.universe_id == @universe_scope.id }
# @content = @universe_scope.send(pluralized_content_name)
# .includes(:page_tags, :image_uploads)
# .unarchived
# @show_scope_notice = true
# else
# @content = (
# current_user.send(pluralized_content_name).unarchived.includes(:page_tags, :image_uploads) +
# current_user.send("contributable_#{pluralized_content_name}").unarchived.includes(:page_tags, :image_uploads)
# )
# if @content_type_class != Universe
# my_universe_ids = current_user.universes.pluck(:id)
# @content.concat(@content_type_class.where(universe_id: my_universe_ids).unarchived)
# end
# end
# @content = @content.to_a.flatten.uniq
# Filters
@page_tags = PageTag.where(

View File

@ -16,16 +16,46 @@ module HasContent
has_many :attribute_categories
has_many :attribute_values, class_name: 'Attribute', dependent: :destroy
def content_with_multiple_queries(
content_types: Rails.application.config.content_type_names[:all],
page_scoping: { user_id: self.id },
universe_id: nil
)
@content_by_page_type = {}
content_types.each do |content_type|
type_specific_fields = ContentPage.polymorphic_content_fields
type_specific_fields.push 'universe_id' unless content_type == 'Universe'
pages_of_this_type = content_type.constantize
.where(page_scoping)
.select(type_specific_fields)
if content_type != 'Universe' && universe_id.present?
pages_of_this_type = pages_of_this_type.where(universe_id: universe_id)
end
@content_by_page_type[content_type] = []
pages_of_this_type.each do |page_data|
@content_by_page_type[content_type].push ContentPage.new(page_data.attributes)
end
end
@content_by_page_type
end
# {
# characters: [...],
# locations: [...]
# }
def content(
content_types: Rails.application.config.content_types[:all].map(&:name),
content_types: Rails.application.config.content_type_names[:all],
page_scoping: { user_id: self.id },
universe_id: nil
)
return content_with_multiple_queries(content_types: content_types, page_scoping: page_scoping, universe_id: universe_id)
return {} if content_types.empty?
# TODO: we should return early if we already have @content_by_page_type!!!
polymorphic_content_fields = ContentPage.polymorphic_content_fields
where_conditions = page_scoping.map { |key, value| "#{key} = #{value}" }.join(' AND ') + ' AND deleted_at IS NULL AND archived_at IS NULL'

View File

@ -1,7 +1,14 @@
class ContentPage < ApplicationRecord
include Rails.application.routes.url_helpers
belongs_to :user
belongs_to :universe
attr_accessor :favorite
include Authority::Abilities
self.authorizer_name = 'ContentPageAuthorizer'
def random_image_including_private(format: :small)
ImageUpload.where(content_type: self.page_type, content_id: self.id).sample.try(:src, format) || "card-headers/#{self.page_type.downcase.pluralize}.jpg"
end
@ -23,6 +30,14 @@ class ContentPage < ApplicationRecord
end
def view_path
send("#{self.page_type.downcase}_path", self.id)
end
def edit_path
send("edit_#{self.page_type.downcase}_path", self.id)
end
def self.polymorphic_content_fields
[:id, :name, :favorite, :page_type, :user_id, :created_at, :updated_at, :deleted_at, :archived_at, :privacy]
end
end

View File

@ -27,7 +27,11 @@ class PermissionService < Service
def self.user_can_contribute_to_containing_universe?(user:, content:)
return false if user.nil?
return true if [AttributeCategory, AttributeField, Attribute].include?(content.class) #todo audit this
content.universe.present? && user.contributable_universes.pluck(:id).include?(content.universe.id)
return true if user.contributable_universe_ids.include?(content.universe_id)
return true if user.universes.pluck(:id).include?(content.universe_id)
return false
end
def self.content_has_no_containing_universe?(content:)

View File

@ -4,14 +4,7 @@
<div class="hoverable card sticky-action" style="margin-bottom: 2px">
<div class="card-image waves-effect waves-block waves-light">
<%= render partial: 'content/display/favorite_control', locals: { content: content } %>
<% content_image = asset_path("card-headers/#{content_type.name.downcase.pluralize}.jpg") %>
<% if content.respond_to?(:image_uploads) %>
<% images = content.image_uploads %>
<% if images.any? %>
<% content_image = images.sample.src(:medium) %>
<% end %>
<% end %>
<div class="activator" style="height: 265px; background: url('<%= content_image %>'); background-size: cover;"></div>
<div class="activator" style="height: 265px; background: url('<%= content.random_image_including_private(format: :medium) %>'); background-size: cover;"></div>
<span class="card-title js-content-name activator">
<div class="bordered-text">
@ -35,13 +28,13 @@
</div>
<div class="card-action">
<% if current_user.can_update?(content) %>
<%= link_to edit_polymorphic_path(content), class: 'green-text right', target: content.is_a?(Document) ? '_new' : '_self' do %>
<%= link_to content.edit_path, class: 'green-text right', target: content.is_a?(Document) ? '_new' : '_self' do %>
<i class="material-icons left"><%= content_type.icon %></i>
Edit
<% end %>
<% end %>
<% if current_user.can_read?(content) %>
<%= link_to polymorphic_path(content), class: 'blue-text text-lighten-1' do %>
<%= link_to content.view_path, class: 'blue-text text-lighten-1' do %>
<i class="material-icons left"><%= content_type.icon %></i>
View
<% end %>