Git Product home page Git Product logo

Comments (10)

javierjulio avatar javierjulio commented on May 25, 2024

@vc-jl thank you. Sorry, this is unnecessary because build_resource and also resource already does this for all member actions.

https://github.com/activeadmin/activeadmin/blob/master/lib/active_admin/resource_controller/data_access.rb#L78-L97

from activeadmin.

vc-jl avatar vc-jl commented on May 25, 2024

@javierjulio The code you are referencing is only called before assigning attributes in update. I can assign values that lead to the resource being saved into other authorization realms. For create, it is also done after assignment, which I would also expect from update.

from activeadmin.

javierjulio avatar javierjulio commented on May 25, 2024

Yes and I see from InheritedResources that there probably wouldn't be much way around it so it. Can you please show how you can update a value a user shouldn't have access too based on a policy?

from activeadmin.

vc-jl avatar vc-jl commented on May 25, 2024

@javierjulio My suggestion would be to modify update_resource like this:

 def update_resource(object, attributes) 
   object = assign_attributes(object, attributes) 
   authorize_resource! object 
  
   run_update_callbacks object do 
     save_resource(object) 
   end 
 end

This would make the most sense from my point of view. But I still may be misunderstanding how authorization is supposed to work and what workflow this may break. Any comments? Thanks a lot!

from activeadmin.

javierjulio avatar javierjulio commented on May 25, 2024

So you don’t know if this is an issue you are running into? That’s why I asked about how you are using it to bypass authorization on a policy for an update? I’m interested in seeing the actual issue being triggered with something you encountered, not a suggestion or idea. You could try our bug report template script to reproduce. You should be able to implement the fix yourself to vet it, at the least. Thanks!

from activeadmin.

vc-jl avatar vc-jl commented on May 25, 2024

@javierjulio I'm sorry, I misread your question. It is certainly an issue I am experiencing, but I still don't know if there is a bug or my assumptions on how authorization should work is inaccurate. Please find my failing test case below.

My scenario is that I am allowed to manage posts with author_ids 1 and 2. I cannot create, see or edit posts with another ID. What I can do, is update a post to have a different author_id.

Thanks again!

Expected behavior

I think I should not be able to set the author_id in my test case to something I am not authorized to.

Actual behavior

I am able to update a resource such that I am not authorized to use it anymore.

How to reproduce

# frozen_string_literal: true
require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  # Use local changes or ActiveAdmin master.
  if ENV["ACTIVE_ADMIN_PATH"]
    gem "activeadmin", path: ENV["ACTIVE_ADMIN_PATH"], require: false
  else
    gem "activeadmin", github: "activeadmin/activeadmin", require: false
  end

  # Change Rails version if necessary.
  gem "rails", "~> 7.0.0"

  gem "sprockets", "~> 3.7"
  gem "sassc-rails"
  gem "sqlite3", platform: :mri
  gem "activerecord-jdbcsqlite3-adapter", platform: :jruby

  # Fixes an issue on CI with default gems when using inline bundle with default
  # gems that are already activated
  # Ref: rubygems/rubygems#6386
  if ENV["CI"]
    require "net/protocol"
    require "timeout"

    gem "net-protocol", Net::Protocol::VERSION
    gem "timeout", Timeout::VERSION
  end
end

require "active_record"

ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :active_admin_comments, force: true do |_t|
  end

  create_table :users, force: true do |t|
    t.string :full_name
  end

  create_table :posts, force: true do |t|
    t.integer :author_id
    t.string :name
  end
end

require "action_controller/railtie"
require "action_view/railtie"
require "active_admin"

class TestApp < Rails::Application
  config.root = __dir__
  config.session_store :cookie_store, key: "cookie_store_key"
  secrets.secret_token = "secret_token"
  secrets.secret_key_base = "secret_key_base"

  config.eager_load = false
  config.logger = Logger.new($stdout)

  config.hosts = "www.example.com"
end

module ApplicationHelper
  def destroy_admin_user_session_path
    ""
  end
end

class ApplicationController < ActionController::Base
  include Rails.application.routes.url_helpers

  def current_user
    User.new(id: 1)
  end

end

class ApplicationRecord < ActiveRecord::Base
  primary_abstract_class

  def self.ransackable_attributes(auth_object = nil)
    authorizable_ransackable_attributes
  end

  def self.ransackable_associations(auth_object = nil)
    authorizable_ransackable_associations
  end
end

class User < ApplicationRecord
  def author_ids
    [1, 2]
  end
end

class Post < ApplicationRecord
end

class AdminAuthorization < ActiveAdmin::AuthorizationAdapter

  def authorized?(action, subject = nil)
    case subject
    when normalized(Post)
      # Only let the author update and delete posts
      if subject.is_a?(Post)
        user.author_ids.include?(subject.author_id)
      else
        true
      end
    else
      true
    end
  end

end

ActiveAdmin.setup do |config|
  # Authentication disabled by default. Override if necessary.
  config.authentication_method = false
  config.current_user_method = :current_user
  config.authorization_adapter = "AdminAuthorization"
end

Rails.application.initialize!

ActiveAdmin.register_page "Dashboard" do
  menu priority: 1, label: proc { I18n.t("active_admin.dashboard") }
  content do
    "Test Me"
  end
end

ActiveAdmin.register User do
end

ActiveAdmin.register Post do
  permit_params do
    [:author_id, :name]
  end
end

Rails.application.routes.draw do
  ActiveAdmin.routes(self)
end

require "minitest/autorun"
require "rack/test"
require "rails/test_help"

# Replace this with the code necessary to make your test fail.
class BugTest < ActionDispatch::IntegrationTest

  def test_admin_posts
    # we should be able to create a post with one of our author_ids
    post admin_posts_url, params: { post: {author_id: 1, name: "My Post"} }
    assert_equal 1, Post.count

    # we should see the post
    get admin_posts_url
    assert_match "My Post", response.body
    assert_response :success

    # and be able to edit it
    get edit_admin_post_url(1)
    assert_response :success

    # we shoould not be able to create a post with a foreign author_id
    post admin_posts_url, params: { post: {author_id: 666, name: "Not my other Post"} }
    assert_equal 1, Post.count

    # we should not be allowed to change the author_id of the first post to something we are not supposed to    
    patch admin_post_url(1), params: { post: {author_id: 666, name: "Not my Post anymore"} }

    # the post should still be one of ours
    get edit_admin_post_url(1)
    assert_response :success
  end

  private

  def app
    Rails.application
  end
end

from activeadmin.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.