Skip to content

Commit 9086d34

Browse files
authored
Merge branch 'master' into oct-2021-release
2 parents 255a497 + e34a211 commit 9086d34

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1132
-318
lines changed

Gemfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ gem 'paranoia'
4242
# Javascript
4343
gem 'coffee-rails'
4444
gem 'rails-jquery-autocomplete'
45-
gem 'animate-rails'
4645
gem 'webpacker'
4746
gem 'react-rails'
4847

Gemfile.lock

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,6 @@ GEM
108108
activerecord (>= 4.2)
109109
addressable (2.7.0)
110110
public_suffix (>= 2.0.2, < 5.0)
111-
animate-rails (1.0.10)
112-
rails
113111
authority (3.3.0)
114112
activesupport (>= 3.0.0)
115113
autoprefixer-rails (9.8.4)
@@ -1629,7 +1627,6 @@ PLATFORMS
16291627
DEPENDENCIES
16301628
active_storage_validations
16311629
acts_as_list
1632-
animate-rails
16331630
authority
16341631
aws-sdk (~> 3.1)
16351632
aws-sdk-s3

app/assets/stylesheets/application.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
*= require font-awesome
1414
*= require medium-editor/medium-editor
1515
*= require medium-editor/themes/beagle
16-
*= require animate
1716
*= require tribute
1817
*= require_tree .
1918
*/

app/assets/stylesheets/layout.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
.card-panel-title {
1010
font-size: 1.3em;
1111
font-weight: bold;
12+
margin-top: 0.5em;
1213
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
class ContentPageAuthorizer < CoreContentAuthorizer
2+
def self.creatable_by?(user)
3+
return false unless user.present?
4+
return false if ENV.key?('CONTENT_BLACKLIST') && ENV['CONTENT_BLACKLIST'].split(',').include?(user.email)
5+
6+
if resource.page_type == 'Universe'
7+
return true if PermissionService.user_has_fewer_owned_universes_than_plan_limit?(user: user)
8+
9+
else
10+
is_premium_page = Rails.application.config.content_types[:premium].include?(resource.page_type)
11+
return true if !is_premium_page
12+
return true if is_premium_page && PermissionService.user_is_on_premium_plan?(user: user)
13+
end
14+
15+
return false
16+
end
17+
18+
def readable_by?(user)
19+
return true if PermissionService.content_is_public?(content: resource)
20+
return true if PermissionService.user_owns_content?(user: user, content: resource)
21+
22+
if resource.page_type == 'Universe'
23+
return true if PermissionService.user_can_contribute_to_universe?(user: user, universe: resource)
24+
else
25+
return true if PermissionService.user_can_contribute_to_containing_universe?(user: user, content: resource)
26+
end
27+
28+
return false
29+
end
30+
31+
def updatable_by?(user)
32+
return true if PermissionService.user_owns_content?(user: user, content: resource)
33+
34+
if resource.page_type == 'Universe'
35+
return true if PermissionService.user_can_contribute_to_universe?(user: user, universe: resource)
36+
else
37+
return true if PermissionService.user_can_contribute_to_containing_universe?(user: user, content: resource)
38+
end
39+
40+
return false
41+
end
42+
43+
def deletable_by?(user)
44+
[
45+
PermissionService.user_owns_content?(user: user, content: resource)
46+
].any?
47+
end
48+
end

app/authorizers/document_authorizer.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ def self.creatable_by?(user)
77

88
def readable_by?(user)
99
return true if user && resource.user_id == user.id
10+
return true if user && user.site_administrator?
1011
return true if resource.privacy == 'public'
1112
return true if resource.universe.present? && resource.universe.privacy == 'public'
1213
return true if user && resource.universe.present? && resource.universe.contributors.pluck(:user_id).include?(user.id)
Lines changed: 132 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
# frozen_string_literal: true
12
class ApplicationController < ActionController::Base
23
protect_from_forgery
34

45
before_action :set_universe_session
56
before_action :set_universe_scope
67

78
before_action :cache_most_used_page_information
8-
before_action :cache_forums_unread_counts
99

1010
before_action :set_metadata
1111

@@ -27,7 +27,7 @@ def set_universe_session
2727
session.delete(:universe_id)
2828
elsif params[:universe].is_a?(String) && params[:universe].to_i.to_s == params[:universe]
2929
found_universe = Universe.find_by(id: params[:universe])
30-
found_universe = nil unless current_user.universes.include?(found_universe) || current_user.contributable_universes.include?(found_universe)
30+
found_universe = nil unless found_universe.user_id == current_user.id || found_universe.contributors.pluck(:user_id).include?(current_user.id)
3131
session[:universe_id] = found_universe.id if found_universe
3232
end
3333
end
@@ -36,52 +36,116 @@ def set_universe_session
3636
def set_universe_scope
3737
if user_signed_in? && session.key?(:universe_id)
3838
@universe_scope = Universe.find_by(id: session[:universe_id])
39-
@universe_scope = nil unless current_user.universes.include?(@universe_scope) || current_user.contributable_universes.include?(@universe_scope)
39+
40+
if @universe_scope && @universe_scope.user_id != current_user.try(:id)
41+
# Verify the current user has access to this universe by looking up their
42+
# universe contributorship
43+
contributorship = Contributor.find_by(
44+
user: current_user,
45+
universe: @universe_scope
46+
)
47+
48+
if contributorship.nil?
49+
# If the user doesn't have current contributor access to this universe,
50+
# then revert back to unscoped universe actions
51+
@universe_scope = nil
52+
end
53+
end
54+
4055
else
4156
@universe_scope = nil
4257
end
4358
end
4459

45-
# Cache some super-common stuff we need for every page. For example, content lists for the side nav.
60+
# Cache some super-common stuff we need for every page. For example, content lists for the side nav. This is a catch-all for most pages that render
61+
# UI, but methods are also free to skip this filter and call the individual cache methods they need instead.
4662
def cache_most_used_page_information
63+
return unless user_signed_in?
64+
65+
cache_activated_content_types
66+
cache_current_user_content
67+
cache_notifications
68+
cache_recently_edited_pages
69+
cache_forums_unread_counts
70+
end
71+
72+
def cache_activated_content_types
73+
@activated_content_types ||= if user_signed_in?
74+
(
75+
# Use config to dictate order, but AND to only include what a user has turned on
76+
Rails.application.config.content_type_names[:all] & current_user.user_content_type_activators.pluck(:content_type)
77+
)
78+
else
79+
[]
80+
end
81+
end
82+
83+
def cache_current_user_content
84+
return if @current_user_content
85+
4786
@current_user_content = {}
4887
return unless user_signed_in?
4988

50-
@activated_content_types = (
51-
Rails.application.config.content_types[:all].map(&:name) & # Use config to dictate order, but AND to only include what a user has turned on
52-
current_user.user_content_type_activators.pluck(:content_type)
53-
)
89+
cache_activated_content_types
5490

5591
# We always want to cache Universes, even if they aren't explicitly turned on.
56-
@current_user_content = current_user.content(content_types: @activated_content_types + ['Universe'], universe_id: @universe_scope.try(:id))
92+
@current_user_content = current_user.content(
93+
content_types: @activated_content_types + [Universe.name],
94+
universe_id: @universe_scope.try(:id)
95+
)
5796

5897
# Likewise, we should also always cache Timelines & Documents
5998
if @universe_scope
6099
@current_user_content['Timeline'] = current_user.timelines.where(universe_id: @universe_scope.try(:id)).to_a
61-
@current_user_content['Document'] = current_user.linkable_documents.includes([:user]).where(universe_id: @universe_scope.try(:id)).order('updated_at DESC').to_a
100+
@current_user_content['Document'] = current_user.documents.where(universe_id: @universe_scope.try(:id)).order('updated_at DESC').to_a
62101
else
63102
@current_user_content['Timeline'] = current_user.timelines.to_a
64-
@current_user_content['Document'] = current_user.linkable_documents.includes([:user]).order('updated_at DESC').to_a
103+
@current_user_content['Document'] = current_user.documents.order('updated_at DESC').to_a
104+
end
105+
end
106+
107+
def cache_notifications
108+
@user_notifications ||= if user_signed_in?
109+
current_user.notifications.order('happened_at DESC').limit(100)
110+
else
111+
[]
65112
end
113+
end
66114

67-
# Fetch notifications
68-
@user_notifications = current_user.notifications.order('happened_at DESC').limit(100)
115+
def cache_recently_created_pages(amount=50)
116+
cache_current_user_content
69117

70-
# Cache recently-edited pages
71-
@recently_edited_pages = @current_user_content.values.flatten
72-
.sort_by(&:updated_at)
73-
.last(50)
74-
.reverse
118+
@recently_created_pages = if user_signed_in?
119+
@current_user_content.values.flatten
120+
.sort_by(&:created_at)
121+
.last(amount)
122+
.reverse
123+
else
124+
[]
125+
end
126+
end
127+
128+
def cache_recently_edited_pages(amount=50)
129+
cache_current_user_content
130+
131+
@recently_edited_pages ||= if user_signed_in?
132+
@current_user_content.values.flatten
133+
.sort_by(&:updated_at)
134+
.last(amount)
135+
.reverse
136+
else
137+
[]
138+
end
75139
end
76140

77141
def cache_forums_unread_counts
78-
@unread_threads = if user_signed_in?
142+
@unread_threads ||= if user_signed_in?
79143
Thredded::Topic.unread_followed_by(current_user).count
80144
else
81145
0
82146
end
83147

84-
@unread_private_messages = if user_signed_in?
148+
@unread_private_messages ||= if user_signed_in?
85149
Thredded::PrivateTopic
86150
.for_user(current_user)
87151
.unread(current_user)
@@ -91,33 +155,60 @@ def cache_forums_unread_counts
91155
end
92156
end
93157

94-
def cache_linkable_content_for_each_content_type
95-
linkable_classes = Rails.application.config.content_types[:all].map(&:name) & current_user.user_content_type_activators.pluck(:content_type)
96-
linkable_classes += %w(Document Timeline)
158+
def cache_contributable_universe_ids
159+
cache_current_user_content
97160

98-
@linkables_cache = {}
99-
@linkables_raw = {}
100-
linkable_classes.each do |class_name|
101-
# class_name = "Character"
161+
@contributable_universe_ids ||= if user_signed_in?
162+
current_user.contributable_universe_ids + @current_user_content.fetch('Universe', []).map(&:id)
163+
else
164+
[]
165+
end
166+
end
102167

103-
@linkables_cache[class_name] = current_user
104-
.send("linkable_#{class_name.downcase.pluralize}")
105-
.in_universe(@universe_scope)
168+
def cache_linkable_content_for_each_content_type
169+
cache_contributable_universe_ids
170+
cache_current_user_content
171+
172+
linkable_classes = @activated_content_types
173+
linkable_classes += %w(Document Timeline)
106174

107-
if @content.present? && @content.persisted?
108-
@linkables_cache[class_name] = @linkables_cache[class_name]
109-
.in_universe(@content.universe)
110-
.reject { |content| content.class.name == class_name && content.id == @content.id }
175+
@linkables_cache = {} # Cache is list of [[page_name, page_id], [page_name, page_id], ...]
176+
@linkables_raw = {} # Raw is list of objects [#{page}, #{page}, ...]
177+
178+
@current_user_content.each do |page_type, content_list|
179+
# We already have our own list of content by the current user in @current_user_content,
180+
# so all we need to grab is additional pages in contributable universes
181+
@linkables_raw[page_type] = @current_user_content[page_type]
182+
183+
if !@universe_scope && @contributable_universe_ids.any?
184+
existing_page_ids = @linkables_raw[page_type].map(&:id)
185+
186+
pages_to_add = if page_type == Universe.name
187+
page_type.constantize.where(id: @contributable_universe_ids)
188+
.where.not(id: existing_page_ids)
189+
else
190+
page_type.constantize.where(universe_id: @contributable_universe_ids)
191+
.where.not(id: existing_page_ids)
192+
end
193+
194+
filtered_fields = ContentPage.polymorphic_content_fields.map(&:to_s)
195+
filtered_fields.push 'universe_id' unless page_type == Universe.name
196+
pages_to_add.each do |page_data|
197+
filtered_page_data = page_data.attributes.slice(*filtered_fields)
198+
@linkables_raw[page_type].push ContentPage.new(filtered_page_data)
199+
end
111200
end
112201

113-
@linkables_raw[class_name] = @linkables_cache[class_name]
114-
.sort_by { |p| p.name.downcase }
115-
.compact
202+
# We can't properly display or @-mention content without a name set, so we explicitly
203+
# reject it here. However, this is a bit of a code-smell: why is there content without
204+
# a name set?
205+
@linkables_raw[page_type].reject! { |page| page.name.nil? }
206+
207+
# Finally, we want to sort our linkables cache once so we don't have to sort it again
208+
@linkables_raw[page_type].sort_by! { |page| page.name.downcase }.compact!
116209

117-
@linkables_cache[class_name] = @linkables_cache[class_name]
118-
.sort_by { |p| p.name.downcase }
119-
.map { |c| [c.name, c.id] }
120-
.compact
210+
# Lastly, build our name/id cache as well
211+
@linkables_cache[page_type] = @linkables_raw[page_type].map { |page| [page.name, page.id] }
121212
end
122213
end
123214
end

0 commit comments

Comments
 (0)