From 7a3b65fe50b19039e5eaf5e4d516ba8c9bb034f1 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Sun, 28 Feb 2021 21:36:46 +0100 Subject: [PATCH] Authorisation management using CanCanCan added --- Gemfile | 3 + Gemfile.lock | 2 + app/controllers/admin_controller.rb | 50 ++++++------ app/controllers/application_controller.rb | 2 +- app/controllers/moderate_controller.rb | 41 +++++----- app/controllers/packages_controller.rb | 80 +++++-------------- app/helpers/packages_helper.rb | 44 +--------- app/models/ability.rb | 56 +++++++++++++ app/models/package.rb | 4 +- app/models/screenshot.rb | 43 +--------- app/models/user.rb | 37 +++++---- app/views/layouts/_footer.slim | 3 - app/views/moderate/index.slim | 6 -- app/views/my/_menu.slim | 10 +-- app/views/my/profile.slim | 10 +-- app/views/my/uploads.slim | 4 +- app/views/packages/_admin_buttons.slim | 36 ++++----- app/views/packages/_report_dropdown.slim | 12 --- app/views/packages/details.slim | 15 +--- ...4424_drop_deprecated_screenshots_fields.rb | 10 +++ .../20210228100636_add_roles_to_users.rb | 14 ++++ ...0210228191717_add_pseudo_column_to_user.rb | 8 ++ db/schema.rb | 12 +-- test/fixtures/screenshots.yml | 4 - 24 files changed, 211 insertions(+), 295 deletions(-) create mode 100644 app/models/ability.rb delete mode 100644 app/views/packages/_report_dropdown.slim create mode 100644 db/migrate/20210228014424_drop_deprecated_screenshots_fields.rb create mode 100644 db/migrate/20210228100636_add_roles_to_users.rb create mode 100644 db/migrate/20210228191717_add_pseudo_column_to_user.rb diff --git a/Gemfile b/Gemfile index 0bea526..f6f0ec3 100644 --- a/Gemfile +++ b/Gemfile @@ -143,3 +143,6 @@ gem 'omniauth_openid_connect' # Mitigate CVE-2015-9284 # https://github.com/cookpad/omniauth-rails_csrf_protection gem 'omniauth-rails_csrf_protection' + +# Role-based access +gem 'cancancan' diff --git a/Gemfile.lock b/Gemfile.lock index 1c08ce0..6eb4312 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,6 +90,7 @@ GEM msgpack (~> 1.0) builder (3.2.4) byebug (11.1.3) + cancancan (3.2.1) capybara (3.35.3) addressable mini_mime (>= 0.1.3) @@ -430,6 +431,7 @@ DEPENDENCIES bootsnap byebug bzip2-ruby! + cancancan capybara cookies_eu devise diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 726b31c..daca6c4 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -1,38 +1,38 @@ class AdminController < ApplicationController - before_action :authenticate_user! - before_action :admin_only + # before_action :authenticate_user! + # before_action :admin_only - def status - end + # def status + # end - def screenshots - end + # def screenshots + # end - def integration - end + # def integration + # end - def moderate_list - end + # def moderate_list + # end - def logs - logs = Log + # def logs + # logs = Log - if params[:search].present? - logger.debug "Searching for #{params[:search]}" - logs = logs.where("message ilike ?", "%#{params[:search]}%") - end + # if params[:search].present? + # logger.debug "Searching for #{params[:search]}" + # logs = logs.where("message ilike ?", "%#{params[:search]}%") + # end - @logs = logs.paginate(page: params[:page], per_page: 20) - end + # @logs = logs.paginate(page: params[:page], per_page: 20) + # end - private + # private - def admin_only - unless current_user.is_admin? - head :forbidden - # redirect_to :back, :alert => "Access denied." - end - end + # def admin_only + # unless current_user.is_admin? + # head :forbidden + # # redirect_to :back, :alert => "Access denied." + # end + # end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a22cade..5d87056 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -22,7 +22,7 @@ class ApplicationController < ActionController::Base # the navigation bar that contains a paginator of packages that contain # screenshots that require moderation. def moderate_packages - if user_signed_in? and current_user.is_admin? and Package.need_moderation.any? + if can? :approve, Screenshot and Package.need_moderation.any? @moderate_packages = Package.need_moderation end end diff --git a/app/controllers/moderate_controller.rb b/app/controllers/moderate_controller.rb index 07a6305..d78cef8 100644 --- a/app/controllers/moderate_controller.rb +++ b/app/controllers/moderate_controller.rb @@ -1,27 +1,22 @@ -class ModerateController < ApplicationController +# class ModerateController < ApplicationController - before_action :authenticate_user! +# before_action :authenticate_user! - def index - # First package with pending screenshots - @package = Package.joins(:screenshots).where('screenshots.approved=false or screenshots.markedfordelete=true').distinct(:name).first +# def index +# # First package with pending screenshots +# @package = Package.joins(:screenshots).where('screenshots.approved=false').distinct(:name).first - # # List of screenshots that were reported (to be removed) - # @reported_screenshots = Screenshot.where(markedfordelete: true) - # # First package with reported screenshots - # @reported_package = Package.joins(:screenshots).where('screenshots.markedfordelete=true').distinct(:name).first +# if @package +# # List of screenshots to be moderated +# @pending_screenshots = @package.screenshots_pending +# # Number of screenshots that were already moderated (during this session) +# session[:already_moderated] ||= 0 +# @moderated_screenshots = session[:already_moderated] - if @package - # List of screenshots to be moderated - @pending_screenshots = @package.screenshots_pending - # Number of screenshots that were already moderated (during this session) - session[:already_moderated] ||= 0 - @moderated_screenshots = session[:already_moderated] - - # BUG: calculation is wrong when pending and reported screenshots are in the queue - # Percentage of already moderated screenshots - @percent_moderated = 100 * (@moderated_screenshots+1) / (@moderated_screenshots + @pending_screenshots.count) - # @percent_moderated = 100 * (@moderated_screenshots+1) / (@moderated_screenshots + @pending_screenshots.count + @reported_screenshots.count) - end - end -end +# # BUG: calculation is wrong when pending and reported screenshots are in the queue +# # Percentage of already moderated screenshots +# @percent_moderated = 100 * (@moderated_screenshots+1) / (@moderated_screenshots + @pending_screenshots.count) +# # @percent_moderated = 100 * (@moderated_screenshots+1) / (@moderated_screenshots + @pending_screenshots.count + @reported_screenshots.count) +# end +# end +# end diff --git a/app/controllers/packages_controller.rb b/app/controllers/packages_controller.rb index 3677eb7..85d60c4 100644 --- a/app/controllers/packages_controller.rb +++ b/app/controllers/packages_controller.rb @@ -37,10 +37,6 @@ class PackagesController < ApplicationController # This action saves the screenshots already if they are valid. The user is # then given the chance to comment on and delete the screenshots again. def upload_receive - # Create a pseudo user account for the user. - # The user won't know that an account is created. - # But this makes it easier to track who screenshots belong to. - # User.create_pseudo_user unless user_signed_in? @package = Package.find_by!(name: params[:name]) @valid_images = [] @invalid_images = [] @@ -65,7 +61,7 @@ class PackagesController < ApplicationController # Check if the image was valid if new_screenshot.valid? - new_screenshot.uploaderhash = session.id.to_s + # new_screenshot.uploaderhash = session.id.to_s new_screenshot.uploaderip = request.remote_ip new_screenshot.version = @package.version # ActiveStorage does not yet create a file checksum automatically. @@ -77,19 +73,25 @@ class PackagesController < ApplicationController Log.log "Duplicate image with fingerprint #{new_screenshot.image_fingerprint} found. Rejecting." all_errors << "Your file #{img.original_filename} is a duplicate. Sorry." else - # Can the upload get approved automatically? - if user_signed_in? - new_screenshot.user = current_user - new_screenshot.approve! if auto_approve? - end + # TODO: Can the upload get approved automatically? + # Create a pseudo user account for the user. + # The user won't know that an account is created. + # But this makes it easier to track who screenshots belong to. + unless user_signed_in? + sign_in User.create_pseudo_user + end + new_screenshot.user = current_user + new_screenshot.approve! if can?(:approve, new_screenshot) + + # Pre-render screenshot in different sizes new_screenshot.simage_derivatives! Log.log "Derivatives created" new_screenshot.save! Log.log "Screenshot #{new_screenshot.id} uploaded successfully. " + \ "ip=#{new_screenshot.uploaderip}. "+ \ - "user-hash=#{new_screenshot.uploaderhash}. "+ \ + #"user-hash=#{new_screenshot.uploaderhash}. "+ \ "user-name=#{current_user} "+ \ "image-fingerprint=#{new_screenshot.image_fingerprint} "+ \ "image-path=#{img.path}" @@ -174,7 +176,7 @@ class PackagesController < ApplicationController # Check if the user is allowed to change this screenshot # - Is this the user's own screenshot? (anonymous) - if @screenshot.user == current_user or current_user.is_admin? + if (@screenshot.user == current_user) || (can? :detroy, @screenshot) logger.debug "User #{current_user} deletes screenshot #{@screenshot}" @screenshot.destroy flash['notice'] = "Screenshot deleted." @@ -185,8 +187,9 @@ class PackagesController < ApplicationController end def approve_screenshot - if current_user && current_user.is_admin? - @screenshot = Screenshot.find(params[:id]) + @screenshot = Screenshot.find(params[:id]) + + if can? :approve, @screenshot @screenshot.approve! flash['notice'] = "Screenshot approved." redirect_back(fallback_location: package_path(name: @screenshot.package.name)) @@ -263,23 +266,6 @@ class PackagesController < ApplicationController redirect_back(fallback_location: package_path(name: @screenshot.package.name)) end - # Receive an anonymous report from a user to have a screenshot removed. - # def report_screenshot - # @screenshot = Screenshot.find(params[:id]) - # # if verify_recaptcha - # @screenshot.delete_reason = params[:delete_reason] - # @screenshot.markedfordelete = true - # if @screenshot.valid? - # @screenshot.save! - # flash['notice'] = "Screenshot reported. The moderators will deal with it." - # else - # errors = @screenshot.errors.to_a.join(' and ') - # flash['alert'] = "Sorry. #{errors}" - # end - # # end - # redirect_back(fallback_location: package_path) - # end - # Show an HTML partial with reviews of this package from the Ubuntu API # def reviews # expires_in 1.day, public: true @@ -350,37 +336,7 @@ class PackagesController < ApplicationController params.require(:screenshot).permit(:description) end - # Do uploads from this user get approved automatically? - def auto_approve? - # Anonymous users need to go through moderation - return false unless user_signed_in? - - # Admins do not need moderation - return true if current_user.is_admin? - - # Debian developers do not need moderation - return true if current_user.provider == 'debian-sso' - - # After one successfully approved screenshot users do not need moderation - # return true if current_user.approved_screenshots.count > 0 - - # Any other user's upload must be moderated - return false - end - def screenshots_visible_to_user(package) - if user_signed_in? and current_user.is_admin? - # User is an admin and can view all screenshots - package.screenshots - # TODO: User logins and assigned screenshots will come in a later version - # elsif user_signed_in? - # package.screenshots.where(id: (current_user.screenshots.select(:id))) | \ - # package.screenshots.where(approved: true).order('created_at DESC') - else - package.screenshots.where(uploaderhash: session.id.to_s).or( - package.screenshots.where(approved: true) - ) - .order('created_at DESC') - end + package.screenshots.accessible_by(current_ability, :view).order('created_at DESC') end end diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb index 40a8de8..0148bd1 100644 --- a/app/helpers/packages_helper.rb +++ b/app/helpers/packages_helper.rb @@ -1,45 +1,5 @@ module PackagesHelper - # Return a query of all screenshots that the current user may see - # Consists of: - # - approved (public) screenshots - # - screenshots uploaded by the user - # - all screenshots if the user is an admin - # def screenshots_visible_to_user(package) - # if user_signed_in? and current_user.is_admin? - # # User is an admin and can view all screenshots - # package.screenshots - # # TODO: User logins and assigned screenshots will come in a later version - # # elsif user_signed_in? - # # package.screenshots.where(id: (current_user.screenshots.select(:id))) | \ - # # package.screenshots.where(approved: true).order('created_at DESC') - # else - # package.screenshots.where(uploaderhash: session.id.to_s) | \ - # package.screenshots.where(approved: true).order('created_at DESC') - # end - # end - - def screenshots_visible_to_user(package, user_session) - # Show all screenshots to admins - if current_user && current_user.is_admin? - package.screenshots - - # Show screenshots belonging to the user or public/approved - else - package.screenshots.where( - uploaderhash: user_session.id.to_s - ).or( - package.screenshots.where( - approved: true - ) - ) - end - end - - def screenshot_uploaded_by_current_user?(screenshot) - screenshot.uploaderhash == session.id.to_s - end - # Return the description and/or the version of the package def screenshot_caption(screenshot) str = [] @@ -78,9 +38,7 @@ module PackagesHelper def status_text(screenshot) # TODO: markedfordelete/reporting will be removed - if screenshot.markedfordelete - "Removal requested > #{screenshot.delete_reason}" - elsif screenshot.approved + if screenshot.approved fa_icon('check-square') + ' Public' else fa_icon('hourglass') + ' Waiting for approval' diff --git a/app/models/ability.rb b/app/models/ability.rb new file mode 100644 index 0000000..c2ef366 --- /dev/null +++ b/app/models/ability.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +class Ability + include CanCan::Ability + + def initialize(user) + + # Define abilities for the passed in user here. For example: + # + # user ||= User.new # guest user (not logged in) + # if user.admin? + # can :manage, :all + # else + # can :read, :all + # end + # + # The first argument to `can` is the action you are giving the user + # permission to do. + # If you pass :manage it will apply to every action. Other common actions + # here are :read, :create, :update and :destroy. + # + # The second argument is the resource the user can perform the action on. + # If you pass :all it will apply to every resource. Otherwise pass a Ruby + # class of the resource. + # + # The third argument is an optional hash of conditions to further filter the + # objects. + # For example, here the user can only update published articles. + # + # can :update, Article, :published => true + # + # See the wiki for details: + # https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities + + if user.present? # Logged-in users + if user.admin_role? + can :approve, Screenshot + can :destroy, Screenshot + can :destroy, User + can :view, Screenshot + can :destroy, Package + end + if user.moderator_role? + can :approve, Screenshot + can :view, Screenshot + can :destroy, Screenshot + end + if user.pseudo? + # Allow to view all public/approved screenshots + can :view, Screenshot, approved: true + # Allow to view any own uploads (even not-yet-approved) + can :view, Screenshot, user_id: user.id + end + end + end +end diff --git a/app/models/package.rb b/app/models/package.rb index 2daafd3..47b96cf 100644 --- a/app/models/package.rb +++ b/app/models/package.rb @@ -53,7 +53,7 @@ class Package < ApplicationRecord # Return a list of packages that have screenshots to be moderated def self.need_moderation - Package.joins(:screenshots).where('screenshots.approved=false or screenshots.markedfordelete=true').distinct(:name) + Package.joins(:screenshots).where('screenshots.approved=false').distinct(:name) end @@ -71,7 +71,7 @@ class Package < ApplicationRecord # Return a query of all approved/public screenshots of this package def screenshots_pending - self.screenshots.where('approved=false or markedfordelete=true') + self.screenshots.where('approved=false') end # Return a list of packages that have unapproved screenshots diff --git a/app/models/screenshot.rb b/app/models/screenshot.rb index 4a3b10f..3f57272 100644 --- a/app/models/screenshot.rb +++ b/app/models/screenshot.rb @@ -10,11 +10,6 @@ class Screenshot < ApplicationRecord # Shrine include ImageUploader::Attachment(:simage) # adds an `simage` virtual attribute - # Calculate how many days ago this screenshot has been uploaded - def age - time_ago_in_words(self.created_at) - end - # Return caption for full-screen screenshots. # Takes the description of a screenshot if available. # Otherwise it falls back to the general description of its package. @@ -54,19 +49,16 @@ class Screenshot < ApplicationRecord # Brief text describing the status of this screenshots (for admins) def adminstatus - if self.markedfordelete - "Removal requested > #{self.delete_reason}" - elsif self.approved + if self.approved 'Public' else - fa_icon('hourglass') + 'Waiting for approval' + #fa_icon('hourglass') + 'Waiting for approval' + 'Waiting for approval' end end # Publish a screenshot from the moderation queue def approve! - self.delete_reason = nil - self.markedfordelete = false self.approved = true self.save! end @@ -76,35 +68,6 @@ class Screenshot < ApplicationRecord self.order(created_at: :desc).where(approved: true).first end - # Returns true if the current user has administrative permissions - # def can_admin? - # self.admin == 1 - # end - - # Returns true if the current user can upload screenshots without moderation - # def can_upload_without_moderation? - # # Admins can upload without moderation - # true if self.can_admin - - # # Authenticated users with at least one approved screenshot - # #true if self.screenshots.where(approved: true).count >= 1 - - # # Other visitors require moderation - # false - # end - - # Returns true if the current user can delete screenshots - # def can_delete? - # # Admins can delete screenshots - # true if self.can_admin - - # # Authenticated users with at least one approved screenshot - # #true if self.screenshots.where(approved: true).count >= 1 - - # # Other visitors require moderation - # false - # end - # Return the part of the version up to the first - or + def upstream_version self.version.split(/[\-\+]/).first diff --git a/app/models/user.rb b/app/models/user.rb index b01ceb9..a2475c5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -40,10 +40,6 @@ class User < ApplicationRecord end end - def is_admin? - self.admin == 1 - end - # Check if a user has been created on-the-fly and is just an # anonymous user who uploaded a screenshot. They can turn this # user record into a registered account though. @@ -59,6 +55,11 @@ class User < ApplicationRecord user.name = auth.info.name # Set a random password user.password = Devise.friendly_token[0,20] + + # Users coming through salsa.debian.net/OpenID-Connect will get moderator role + if user.email.end_with?('@debian.org') && user.provider=='salsa' + user.moderator_role = true + end end end @@ -66,20 +67,18 @@ class User < ApplicationRecord self.screenshots.where(approved: true) end - # Seamlessly create a user account for the current client. + # Seamlessly create a user account for the current visitor. # It helps track uploads because uploaded screenshots get assigned - # to this user record. The user can later decide to use a real - # account and get their screenshots transferred to that. - # def self.create_pseudo_user - # generated_password = Devise.friendly_token.first(8) - # new_user = User.create( - # name: 'Anonymous', - # password: generated_password) - # Log.log "New pseudo user for anonymous upload created: #{new_user}" - # sign_in new_user - # end - # - # Currently the approach is different: do not create an account - # for a user. Instead store the IDs of the uploaded screenshots - # and transfer them if the user decides to do a real login using SSO. + # to this user record. + # TODO: The user can later decide to use a real account and get their screenshots transferred to that. + def self.create_pseudo_user + generated_password = Devise.friendly_token.first(8) + new_user = User.create( + name: 'Anonymous', + password: generated_password, + pseudo: true + ) + Log.log "New pseudo user for anonymous upload created: #{new_user}" + return new_user + end end diff --git a/app/views/layouts/_footer.slim b/app/views/layouts/_footer.slim index fdc1075..82e825e 100644 --- a/app/views/layouts/_footer.slim +++ b/app/views/layouts/_footer.slim @@ -15,6 +15,3 @@ / ' | Cookie is #{session[:token]} = render 'cookies_eu/consent_banner', link: '/about#cookies' - -/ = current_user.is_admin? -/ = session.id diff --git a/app/views/moderate/index.slim b/app/views/moderate/index.slim index 4b45b92..37fc4b4 100644 --- a/app/views/moderate/index.slim +++ b/app/views/moderate/index.slim @@ -31,12 +31,6 @@ a.button.alert.round href=delete_screenshot_path(screenshot) onclick="return confirm('Really delete the screenshot?');" Reject a.button.success.round href=approve_screenshot_path(screenshot) Approve - / Existing screenshots that was requested for removal - - if screenshot.markedfordelete==true - .button-group - a.button.alert.round href=delete_screenshot_path(screenshot) onclick="return confirm('Really delete the screenshot?');" Remove as requested - a.button.success.round href=approve_screenshot_path(screenshot) Keep the screenshot - .small-6.cell p Existing screenshots: diff --git a/app/views/my/_menu.slim b/app/views/my/_menu.slim index 5eb9c1e..885e5ce 100644 --- a/app/views/my/_menu.slim +++ b/app/views/my/_menu.slim @@ -7,11 +7,11 @@ = link_to moderate_list_path = fa_icon 'check 2x', text: 'Moderate' // Add link if user has uploaded screenshots - - if @current_users_screenshots and @current_users_screenshots.any? - li class=('active' if controller_name=='my' and action_name=='uploads') - = link_to my_uploads_path - = fa_icon 'image 2x', text: 'My uploads' - ' My uploads + / - if @current_users_screenshots and @current_users_screenshots.any? + / li class=('active' if controller_name=='my' and action_name=='uploads') + / = link_to my_uploads_path + / = fa_icon 'image 2x', text: 'My uploads' + / ' My uploads li = link_to destroy_user_session_path, method: :delete diff --git a/app/views/my/profile.slim b/app/views/my/profile.slim index 77fcf81..47ff369 100644 --- a/app/views/my/profile.slim +++ b/app/views/my/profile.slim @@ -27,8 +27,8 @@ h2 Number of screenshots you uploaded p = current_user.screenshots.count - - if current_user.is_admin? - h2 Admin - p Apparently you are an administrator. Be careful with that thing! - - tt = current_user.inspect + / - if current_user.is_admin? + / h2 Admin + / p Apparently you are an administrator. Be careful with that thing! + / - you can moderate + / - you can … \ No newline at end of file diff --git a/app/views/my/uploads.slim b/app/views/my/uploads.slim index f54d875..081a452 100644 --- a/app/views/my/uploads.slim +++ b/app/views/my/uploads.slim @@ -16,8 +16,8 @@ - @current_users_screenshots.each do |screenshot| .column / TODO: old Paperclip style - a.black.fancybox href=screenshot.image.variant(resize_to_limit: [800,600], timestamp: false) + a.black.fancybox href=screenshot.simage_url(:large) div.grid-thumbnail - = image_tag(screenshot.image.variant(resize_to_limit: [160,120]), alt: screenshot.caption, class: 'thumbnail') + = image_tag(screenshot.simage_url(:medium), alt: screenshot.caption, class: 'thumbnail') div = screenshot.description diff --git a/app/views/packages/_admin_buttons.slim b/app/views/packages/_admin_buttons.slim index da64279..f85f7eb 100644 --- a/app/views/packages/_admin_buttons.slim +++ b/app/views/packages/_admin_buttons.slim @@ -1,7 +1,13 @@ // Button that reveals a dropdown/modal for moderation/reporting + +- if can?(:destroy, screenshot) || can?(:approve, screenshot) + .text + span.label.secondary + = status_text(screenshot) + .button-group.small.align-center - - if (screenshot_uploaded_by_current_user?(screenshot) || (current_user && current_user.is_admin?)) + - if can?(:destroy, screenshot) a.button.small.bordered.radius.alert[ href=delete_screenshot_path(screenshot.id) onclick="return confirm('Really delete the screenshot?');" @@ -15,29 +21,15 @@ / href='#' / ] #{fa_icon 'star'} Make primary - - if not screenshot.approved - - if current_user && current_user.is_admin? + - unless screenshot.approved + - if can?(:approve, screenshot) a.button.small.success[ href=approve_screenshot_path(screenshot.id) method='post' - ] Approve - - / - elsif screenshot.markedfordelete - / a.button.small.success[ - / href=approve_screenshot_path(screenshot.id) - / method='post' - / ] Keep - + ] #{fa_icon 'check'} Approve / Display additional information to admins - p Status: #{screenshot.adminstatus} - p Uploader IP=#{screenshot.uploaderip} - p Uploader Token=#{session[:token]} - p Uploaded #{screenshot.age} ago (#{screenshot.created_at}) - - / TODO: Move reporting screenshots to an extra page with a form and captcha - / - else - / / Allow anonymous users to report inappropriate screenshots - / = form_tag(report_screenshot_path(screenshot.id)) - / = text_area_tag 'delete_reason', nil, class: 'input-group-field', maxlength: 100, rows: 3, cols: 50 - / = submit_tag 'Request removal', class: 'button alert' + / p Status: #{screenshot.adminstatus} + / p Uploader IP=#{screenshot.uploaderip} + / p Uploader Token=#{session[:token]} + / p Uploaded #{time_ago_in_words(screenshot.created_at)} ago (#{screenshot.created_at}) diff --git a/app/views/packages/_report_dropdown.slim b/app/views/packages/_report_dropdown.slim deleted file mode 100644 index 69dad7a..0000000 --- a/app/views/packages/_report_dropdown.slim +++ /dev/null @@ -1,12 +0,0 @@ -// Button that reveals a dropdown/modal for users (for their own screenshots) -.text-right - button.small.dropdown.warning.button type="button" data-toggle="admin-info-#{screenshot.id}" - 'Request removal -.dropdown-pane data-dropdown=true id="admin-info-#{screenshot.id}" - p If you think this screenshot does not meet the guidelines - or is misleading or not useful then please report it so that - the moderators can review it. Just let us know why you think - the screenshot should get removed: - = form_tag(report_screenshot_path(screenshot.id)) - = text_area_tag 'delete_reason', nil, class: 'input-group-field', maxlength: 100, rows: 3, cols: 50 - = submit_tag 'Request removal', class: 'button alert' diff --git a/app/views/packages/details.slim b/app/views/packages/details.slim index fd35d44..711371b 100644 --- a/app/views/packages/details.slim +++ b/app/views/packages/details.slim @@ -25,24 +25,13 @@ .text = screenshot.caption // Has the unmoderated screenshot been uploaded by the current user? - - if screenshot_uploaded_by_current_user?(screenshot) + - if current_user.screenshots.include?(screenshot) .text span.label.secondary ' Uploaded by you - unless screenshot.approved ' (needs to be approved) - = render(partial: 'admin_buttons', locals: {screenshot: screenshot}) - // Is the user an admin? - // or does the screenshot belong to the user (determined by session cookie) - - if current_user && current_user.is_admin? - hr - .text - span.label.secondary - = status_text(screenshot) - - = render(partial: 'admin_buttons', locals: {screenshot: screenshot}) - / - elsif user_signed_in? and screenshot.user == current_user - / = render(partial: 'user_dropdown', locals: {screenshot: screenshot}) + = render(partial: 'admin_buttons', locals: {screenshot: screenshot}) // Second paginator at the bottom so the user does not have to scroll up again diff --git a/db/migrate/20210228014424_drop_deprecated_screenshots_fields.rb b/db/migrate/20210228014424_drop_deprecated_screenshots_fields.rb new file mode 100644 index 0000000..8bad63b --- /dev/null +++ b/db/migrate/20210228014424_drop_deprecated_screenshots_fields.rb @@ -0,0 +1,10 @@ +class DropDeprecatedScreenshotsFields < ActiveRecord::Migration[6.1] + def change + remove_column :screenshots, :markedfordelete + remove_column :screenshots, :delete_reason + remove_column :screenshots, :image_file_name + remove_column :screenshots, :image_content_type + remove_column :screenshots, :image_file_size + remove_column :screenshots, :image_updated_at + end +end diff --git a/db/migrate/20210228100636_add_roles_to_users.rb b/db/migrate/20210228100636_add_roles_to_users.rb new file mode 100644 index 0000000..e54adfa --- /dev/null +++ b/db/migrate/20210228100636_add_roles_to_users.rb @@ -0,0 +1,14 @@ +# Rename the :admin field to :admin_role and change integer to boolean +class AddRolesToUsers < ActiveRecord::Migration[6.1] + def change + add_column :users, :admin_role, :boolean, default: false + + User.find_each do |user| + user.admin_role=true if user.admin>0 + user.save! + end + + remove_column :users, :admin + add_column :users, :moderator_role, :boolean, default: false + end +end diff --git a/db/migrate/20210228191717_add_pseudo_column_to_user.rb b/db/migrate/20210228191717_add_pseudo_column_to_user.rb new file mode 100644 index 0000000..a5431ca --- /dev/null +++ b/db/migrate/20210228191717_add_pseudo_column_to_user.rb @@ -0,0 +1,8 @@ +# Create a pseudo flag for accounts that get automatically created. +# If an anonymous visitor uploads a screenshot he will get a +# pseudo account to assign the screenshots to. +class AddPseudoColumnToUser < ActiveRecord::Migration[6.1] + def change + add_column :users, :pseudo, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index ca21ee9..e9c0a10 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: 2021_02_22_102719) do +ActiveRecord::Schema.define(version: 2021_02_28_191717) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -88,14 +88,8 @@ ActiveRecord::Schema.define(version: 2021_02_22_102719) do t.datetime "created_at" t.string "uploaderhash", limit: 72 t.boolean "approved", default: false, null: false - t.boolean "markedfordelete" - t.string "delete_reason", limit: 100 t.text "description" t.datetime "updated_at" - t.string "image_file_name" - t.string "image_content_type" - t.integer "image_file_size" - t.datetime "image_updated_at" t.string "image_fingerprint" t.integer "user_id", default: 0 t.text "simage_data" @@ -120,7 +114,9 @@ ActiveRecord::Schema.define(version: 2021_02_22_102719) do t.datetime "locked_at" t.string "provider" t.string "uid" - t.integer "admin", default: 0 + t.boolean "admin_role", default: false + t.boolean "moderator_role", default: false + t.boolean "pseudo", default: false t.index ["email", "provider"], name: "index_users_on_email_and_provider", unique: true end diff --git a/test/fixtures/screenshots.yml b/test/fixtures/screenshots.yml index 2dd0d92..866dbc4 100644 --- a/test/fixtures/screenshots.yml +++ b/test/fixtures/screenshots.yml @@ -6,8 +6,6 @@ # uploaderhash: MyString # uploaderip: MyString # approved: -# markedfordelete: -# delete_reason: MyString # description: MyString # two: @@ -16,6 +14,4 @@ # uploaderhash: MyString # uploaderip: MyString # approved: -# markedfordelete: -# delete_reason: MyString # description: MyString