Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow visitors to view public models without logging in #2607

Merged
merged 23 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7fc774d
use default pagination settings if there is no current user
Floppy Sep 3, 2024
4253f51
handle logged-out state in scope resolve
Floppy Sep 3, 2024
fd319c7
use default tag list settings if logged out
Floppy Sep 3, 2024
8ec2e20
use default renderer settings if logged out
Floppy Sep 3, 2024
ab9d189
use default file list settings if logged out
Floppy Sep 3, 2024
f344d7d
use default problem settings if logged out
Floppy Sep 3, 2024
7d51ccd
fix error with logged out follow button
Floppy Sep 3, 2024
c42741f
delegate model file policy to model policy (mostly edit permission)
Floppy Sep 3, 2024
da95ed7
enable show buttons on models
Floppy Sep 3, 2024
34b5e1f
fix following policy
Floppy Sep 3, 2024
21bbd88
fix policy check for 3mf conversion
Floppy Sep 3, 2024
f9cf16b
fix problem with default settings when logged out
Floppy Sep 3, 2024
541376e
lint
Floppy Sep 3, 2024
420921c
hide unpermitted buttons
Floppy Sep 3, 2024
d278a00
hide unusable buttons
Floppy Sep 3, 2024
76c63e6
add a "no results" info message
Floppy Sep 3, 2024
a4a904c
auto show/hide follow button based on permissions
Floppy Sep 3, 2024
53acb2f
set policy scopes on model counts in creators and collections
Floppy Sep 3, 2024
ad63e04
don't show private things in activity feed
Floppy Sep 3, 2024
a656080
don't show counts in tag cloud if logged out
Floppy Sep 3, 2024
651fca4
get follow button tests working with policies
Floppy Sep 3, 2024
af57166
remove requirement for authenticated access on every action
Floppy Sep 3, 2024
461912c
use existing user in FollowButtonComponent test
Floppy Sep 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/components/follow_button_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class FollowButtonComponent < ViewComponent::Base
def initialize(follower:, target:, name: nil)
@target = target
@following = follower.following? target
@following = follower&.following? target
@name = name
end

Expand All @@ -14,7 +14,7 @@ def before_render
end

def render?
SiteSettings.multiuser_enabled? || SiteSettings.federation_enabled?
(SiteSettings.multiuser_enabled? || SiteSettings.federation_enabled?) && helpers.policy(Federails::Following).create?
end

erb_template <<-ERB
Expand Down
2 changes: 1 addition & 1 deletion app/components/model_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<span style="float: right"><%= helpers.status_badges(@model) %></span>
</div>
<div class='mt-2'>
<%= link_to t(".open_button.text"), @model, {class: "btn btn-primary btn-sm", "aria-label": translate(".open_button.label", name: @model.name)} if @can_show %>
<%= link_to t(".open_button.text"), @model, {class: "btn btn-primary btn-sm", "aria-label": translate(".open_button.label", name: @model.name)} %>
<%= link_to helpers.icon("pencil-fill", t(".edit_button.text")), edit_model_path(@model), {class: "btn btn-outline-secondary btn-sm", "aria-label": translate(".edit_button.label", name: @model.name)} if @can_edit %>
<%= link_to helpers.icon("trash", t(".delete_button.text")), model_path(@model), {method: :delete, class: "btn btn-outline-danger btn-sm", "aria-label": translate(".delete_button.label", name: @model.name), data: {confirm: translate("models.destroy.confirm")}} if @can_destroy %>
</div>
Expand Down
3 changes: 1 addition & 2 deletions app/components/model_component.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# frozen_string_literal: true

class ModelComponent < ViewComponent::Base
def initialize(model:, can_show: false, can_edit: false, can_destroy: false)
def initialize(model:, can_edit: false, can_destroy: false)
@model = model
@can_destroy = can_destroy
@can_show = can_show
@can_edit = can_edit
end
end
1 change: 0 additions & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ class ApplicationController < ActionController::Base
after_action :verify_policy_scoped, only: :index, unless: :active_admin_controller?
after_action :set_content_security_policy_header, if: -> { request.format.html? }

before_action :authenticate_user!
around_action :switch_locale
before_action :check_for_first_use
before_action :show_security_alerts
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/collections_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def index
@collections.order(name: :asc)
end

if current_user.pagination_settings["collections"]
if helpers.pagination_settings["collections"]
page = params[:page] || 1
@collections = @collections.page(page).per(current_user.pagination_settings["per_page"])
@collections = @collections.page(page).per(helpers.pagination_settings["per_page"])
end
# Eager load
@collections = @collections.includes :collections, :collection, :links, models: [:preview_file, :library]
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/concerns/tag_listable.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module TagListable
def generate_tag_list(models = nil, filter_tags = nil)
# All tags bigger than threshold
tags = all_tags = ActsAsTaggableOn::Tag.where(taggings_count: current_user.tag_cloud_settings["threshold"]..)
tags = all_tags = ActsAsTaggableOn::Tag.where(taggings_count: helpers.tag_cloud_settings["threshold"]..)
# Ignore any tags that have been applied as filters
tags = all_tags = tags.where.not(id: filter_tags) if filter_tags
# Generate a list of tags shared by the list of models
tags = tags.includes(:taggings).where("taggings.taggable": models.map(&:id)) if models
# Apply tag sorting
tags = case current_user.tag_cloud_settings["sorting"]
tags = case helpers.tag_cloud_settings["sorting"]
when "alphabetical"
tags.order(name: :asc)
else
Expand All @@ -23,7 +23,7 @@ def generate_tag_list(models = nil, filter_tags = nil)

def split_key_value_tags(tags)
# Split into plain tags and key-value tags
if current_user.tag_cloud_settings["keypair"]
if helpers.tag_cloud_settings["keypair"]
plain_tags = tags.where.not("name LIKE '%:%'")
kv_tags = tags.where("name LIKE '%:%'")
else
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/creators_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def index
@creators.order(name: :asc)
end

if current_user.pagination_settings["creators"]
if helpers.pagination_settings["creators"]
page = params[:page] || 1
@creators = @creators.page(page).per(current_user.pagination_settings["per_page"])
@creators = @creators.page(page).per(helpers.pagination_settings["per_page"])
end
# Eager load data
@creators = @creators.includes(:links, :models)
Expand Down
2 changes: 0 additions & 2 deletions app/controllers/health_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# frozen_string_literal: true

class HealthController < ApplicationController
skip_before_action :authenticate_user!

after_action :verify_policy_scoped, except: :index

def index
Expand Down
7 changes: 3 additions & 4 deletions app/controllers/models_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class ModelsController < ApplicationController

def index
# Work out policies for showing buttons up front
@can_show = policy(Model).show?
@can_destroy = policy(Model).destroy?
@can_edit = policy(Model).edit?

Expand All @@ -24,9 +23,9 @@ def index
@models.order(name: :asc)
end

if current_user.pagination_settings["models"]
if helpers.pagination_settings["models"]
page = params[:page] || 1
@models = @models.page(page).per(current_user.pagination_settings["per_page"])
@models = @models.page(page).per(helpers.pagination_settings["per_page"])
end

@tags, @unrelated_tag_count = generate_tag_list(@filters.empty? ? nil : @models, @filter_tags)
Expand All @@ -42,7 +41,7 @@ def show
files = @model.model_files
@images = files.select(&:is_image?)
@images.unshift(@model.preview_file) if @images.delete(@model.preview_file)
if current_user.file_list_settings["hide_presupported_versions"]
if helpers.file_list_settings["hide_presupported_versions"]
hidden_ids = files.select(:presupported_version_id).where.not(presupported_version_id: nil)
files = files.where.not(id: hidden_ids)
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/problems_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def index
# What object types are we showing?
query = query.where(problematic_type: params[:type].map(&:classify)) if params[:type]
# Don't show types ignored in user settings
query = query.visible(current_user.problem_settings)
query = query.visible(helpers.problem_settings)
query = query.includes([:problematic])
@problems = query.page(page).per(50).order([:category, :problematic_type])
# Do we have any filters at all?
Expand Down
20 changes: 20 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,24 @@ def translate_with_locale_wrapper(key, **options)
end
end
alias_method :t, :translate_with_locale_wrapper

def pagination_settings
current_user&.pagination_settings || SiteSettings::UserDefaults::PAGINATION
end

def tag_cloud_settings
current_user&.tag_cloud_settings || SiteSettings::UserDefaults::TAG_CLOUD.merge(heatmap: false)
end

def renderer_settings
current_user&.renderer_settings || SiteSettings::UserDefaults::RENDERER
end

def file_list_settings
current_user&.file_list_settings || SiteSettings::UserDefaults::FILE_LIST
end

def problem_settings
current_user&.problem_settings || Problem::DEFAULT_SEVERITIES
end
end
2 changes: 1 addition & 1 deletion app/helpers/models_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def group(files)
def status_badges(model)
badges = []
badges << content_tag(:span, icon("bi bi-stars", t("general.new")), class: "text-warning align-middle") if model.new?
badges << problem_icon_tag(model.problems_including_files.visible(current_user.problem_settings)) if policy(Problem).show?
badges << problem_icon_tag(model.problems_including_files.visible(problem_settings)) if policy(Problem).show?
content_tag :span, safe_join(badges, " "), class: "status-badges"
end

Expand Down
4 changes: 2 additions & 2 deletions app/models/problem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Problem < ApplicationRecord
:danger
]

DEFAULT_SEVERITIES = {
DEFAULT_SEVERITIES = ActiveSupport::HashWithIndifferentAccess.new(
missing: :danger,
empty: :info,
nesting: :warning,
Expand All @@ -41,7 +41,7 @@ class Problem < ApplicationRecord
no_3d_model: :silent,
non_manifold: :warning,
inside_out: :warning
}
)

def self.create_or_clear(problematic, cat, present, options = {})
if present
Expand Down
16 changes: 8 additions & 8 deletions app/models/site_settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,32 @@ def self.ignored_file?(pathname)
end

module UserDefaults
RENDERER = {
RENDERER = ActiveSupport::HashWithIndifferentAccess.new(
grid_width: 200,
grid_depth: 200,
show_grid: true,
enable_pan_zoom: false,
background_colour: "#000000",
object_colour: "#cccccc",
render_style: "normals"
}
)

PAGINATION = {
PAGINATION = ActiveSupport::HashWithIndifferentAccess.new(
models: true,
creators: true,
collections: true,
per_page: 12
}
)

TAG_CLOUD = {
TAG_CLOUD = ActiveSupport::HashWithIndifferentAccess.new(
threshold: 2,
heatmap: true,
keypair: true,
sorting: "frequency"
}
)

FILE_LIST = {
FILE_LIST = ActiveSupport::HashWithIndifferentAccess.new(
hide_presupported_versions: true
}
)
end
end
2 changes: 1 addition & 1 deletion app/policies/application_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def initialize(user, scope)
end

def resolve
return scope.all if user.is_moderator? || !scope.respond_to?(:granted_to)
return scope.all if user&.is_moderator? || !scope.respond_to?(:granted_to)

result = scope.granted_to(["view", "edit", "own"], [user, nil])
result = result.or(scope.granted_to(["view", "edit", "own"], user.roles)) if user
Expand Down
14 changes: 7 additions & 7 deletions app/policies/federails/following_policy.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
class Federails::FollowingPolicy < ApplicationPolicy
def create?
any_of(
SiteSettings.multiuser_enabled?,
SiteSettings.federation_enabled?
all_of(
one_of(
SiteSettings.multiuser_enabled?,
SiteSettings.federation_enabled?
),
@user
)
end

def destroy?
any_of(
SiteSettings.multiuser_enabled?,
SiteSettings.federation_enabled?
)
create?
end

class Scope < ApplicationPolicy::Scope
Expand Down
20 changes: 18 additions & 2 deletions app/policies/model_file_policy.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
class ModelFilePolicy < ApplicationPolicy
def show?
ModelPolicy.new(@user, @record.model).show?
end

def create?
ModelPolicy.new(@user, @record.model).edit?
end

def update?
create?
end

def delete?
create?
end

def bulk_edit?
user&.is_moderator?
bulk_update?
end

def bulk_update?
user&.is_moderator?
create?
end
end
6 changes: 2 additions & 4 deletions app/views/activities/_create_actor.html.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
<%- subject = activity&.actor %>
<%- object = activity&.entity %>
<%- thing = object&.entity %>
<% if thing %>
<% if thing && !thing.is_a?(User) && (thing.grants_permission_to?(["view", "edit", "own"], current_user) || thing.grants_permission_to?(["view", "edit", "own"], current_user&.roles)) %>
<div class="card border-0 border-bottom">
<div class="card-body py-2">
<div class="row">
<div class="col col-auto">
<%= icon icon_for(thing.class), thing.class.model_name.human %>
</div>
<div class="col">
<%- if thing.is_a?(User) %>
<%= object.name %>
<%- elsif object.local? %>
<%- if object.local? %>
<%= link_to thing.name, thing %>
<%- elsif object.profile_url %>
<%= link_to object.name, object.profile_url %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/activities/_update_actor.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%- subject = activity&.actor %>
<%- object = activity&.entity %>
<%- thing = object&.entity %>
<% if thing && !thing.is_a?(User) %>
<% if thing && !thing.is_a?(User) && (thing.grants_permission_to?(["view", "edit", "own"], current_user) || thing.grants_permission_to?(["view", "edit", "own"], current_user&.roles)) %>
<div class="card border-0 border-bottom">
<div class="card-body py-2">
<div class="row">
Expand Down
2 changes: 1 addition & 1 deletion app/views/application/_navbar.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
<% end %>
</li>
<%- if current_user %>
<% if policy(Problem).index? && Problem.visible(current_user.problem_settings).count > 0 %>
<% if policy(Problem).index? && Problem.visible(problem_settings).count > 0 %>
<li class="nav-item">
<% severity = max_problem_severity %>
<%= nav_link problem_icon(severity),
Expand Down
16 changes: 8 additions & 8 deletions app/views/application/_object_preview.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
data-worker-url="<%= javascript_path "offscreen_renderer.js" %>"
data-format="<%= file.extension %>"
data-y-up="<%= file.y_up %>"
data-grid-size-x="<%= current_user.renderer_settings["grid_width"] %>"
data-grid-size-z="<%= current_user.renderer_settings["grid_depth"] %>"
data-show-grid="<%= current_user.renderer_settings["show_grid"] %>"
data-enable-pan-zoom="<%= current_user.renderer_settings["enable_pan_zoom"] %>"
data-background-colour="<%= current_user.renderer_settings["background_colour"] %>"
data-object-colour="<%= current_user.renderer_settings["object_colour"] %>"
data-render-style="<%= current_user.renderer_settings["render_style"] %>"
data-auto-load="<%= ((file.size || 9_999_999.megabytes) < ((current_user.renderer_settings["auto_load_max_size"] || 9_999_999).megabytes)) ? "true" : "false" %>">
data-grid-size-x="<%= renderer_settings["grid_width"] %>"
data-grid-size-z="<%= renderer_settings["grid_depth"] %>"
data-show-grid="<%= renderer_settings["show_grid"] %>"
data-enable-pan-zoom="<%= renderer_settings["enable_pan_zoom"] %>"
data-background-colour="<%= renderer_settings["background_colour"] %>"
data-object-colour="<%= renderer_settings["object_colour"] %>"
data-render-style="<%= renderer_settings["render_style"] %>"
data-auto-load="<%= ((file.size || 9_999_999.megabytes) < ((renderer_settings["auto_load_max_size"] || 9_999_999).megabytes)) ? "true" : "false" %>">
</canvas>
<div class="p-0 btn btn-secondary load-progress object-preview-progress position-absolute top-50 start-50 translate-middle" role="presentation">
<div class="progress-bar bg-info progress-bar-animated progress-bar-striped" aria-label="Loading progress" role="progressbar" style="width: 0%; height: 100%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
Expand Down
2 changes: 1 addition & 1 deletion app/views/application/_tag_list.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
end %>
<% end %>
<%- tag_html_opts = {data: {bulk_item_tags: defined?(model_id) ? model_id&.to_s : nil}} %>
<%- heatmap = defined?(show_count) ? heatmap : current_user.tag_cloud_settings["heatmap"] %>
<%- heatmap = defined?(show_count) ? heatmap : tag_cloud_settings["heatmap"] %>
<%= safe_join(tags.map { |tag| render TagComponent.new(tag: tag, filters: @filters, html_options: tag_html_opts, show_count: heatmap) }, " ") if tags %>
<% if defined?(kv_tags) && kv_tags %>
<ul class="list-unstyled">
Expand Down
4 changes: 2 additions & 2 deletions app/views/collections/_collection.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<% model = collection.models.first %>
<% model = policy_scope(Model).where(collection: collection).first %>
<div class="col mb-4">
<div class="card preview-card">

Expand Down Expand Up @@ -34,7 +34,7 @@
</ul>
</div>
<div>
<%= link_to "#{collection.models.count} #{Model.model_name.human count: collection.models.count}", {controller: "models", collection: collection.id}, class: "btn btn-primary", "aria-label": translate(".models_button.label", name: collection.name) if policy(collection).show? %>
<%= link_to "#{policy_scope(Model).where(collection: collection).count} #{Model.model_name.human count: policy_scope(Model).where(collection: collection).count}", {controller: "models", collection: collection.id}, class: "btn btn-primary", "aria-label": translate(".models_button.label", name: collection.name) if policy(collection).show? %>
<%= link_to "#{collection.collections.count} #{Collection.model_name.human count: collection.collections.count}", (@filters || {}).merge(controller: "collections", collection: collection.id), class: "btn btn-primary", "aria-label": translate(".collections_button.label", name: collection.name) if collection.collections.count > 0 && policy(collection).show? %>
<%= link_to icon("pencil-fill", t(".edit_button.text")), edit_collection_path(collection), {class: "btn btn-outline-secondary", "aria-label": translate(".edit_button.label", name: collection.name)} if policy(collection).edit? %>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/views/collections/_unassigned.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="card-body">
<div class="card-title"><%= t(".name") %></div>
<h6 class="card-subtitle mb-2 text-muted"><%= t(".caption") %></h6>
<%= link_to "#{Model.where(collection: nil).count} #{Model.model_name.human count: Model.where(collection: nil).count}", models_path(collection: ""), {class: "btn btn-primary"} %>
<%= link_to "#{policy_scope(Model).where(collection: nil).count} #{Model.model_name.human count: policy_scope(Model).where(collection: nil).count}", models_path(collection: ""), {class: "btn btn-primary"} %>
</div>
</div>
</div>
Loading
Loading