Comments (10)
@vc-jl thank you. Sorry, this is unnecessary because build_resource
and also resource
already does this for all member actions.
from activeadmin.
@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.
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.
@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.
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.
@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.
Hi @javierjulio, do you have any hints on what I could do to further clarify my issue? Should I provide the test case differently? Or is it clear enough, and you still think this is not an issue? Thanks again!
from activeadmin.
You're welcome. This is not an issue with the admin. It is a responsibility of the app at the model level to not change the author of a post. You should be guarding that with a validation. I've had to deal with something similar before but not with the admin. That to me makes sense. Thanks!
from activeadmin.
Alright, will do :) Thanks again.
One last question though: Do you know why there is this check authorize_resource!
in the build_resource
-method?
activeadmin/lib/active_admin/resource_controller/data_access.rb
Lines 115 to 125 in ccdf0d7
from activeadmin.
You're welcome. I don't know. It's been there since the project was created by its original author.
from activeadmin.
Related Issues (20)
- undefined method `to_ary` for Enumerator (Rails 7.1.1 & Activeadmin 3.1.0) HOT 4
- index columns / show rows
- `contains` filter no longer working HOT 1
- uninitialized constant InheritedResources::Base (NameError) HOT 1
- Filtering on associations does not use the foreign_key when defined HOT 3
- Uninitialized constant `Devise::SessionsController` when extending controller HOT 1
- Rails 7.1.2 compatibility HOT 1
- InvalidAuthenticityToken Can't verify CSRF with rails 7.1.2.
- v4 beta 3: Kaminari translation override may affect the host application HOT 2
- v4 beta 3: External CDNs do not play well with CSP and may be a problem for intranet apps HOT 2
- Defining Actions in Index as a Table (4.0.0.beta3) HOT 3
- after_save called even if validation fails HOT 5
- 4.0.0.beta4 nesting in menus HOT 6
- Indentation broken for nested lists HOT 1
- No access to routes helpers from ActiveAdmin views [v4.0.0.beta5] HOT 8
- Fix DateRange Filter last day confusion regression
- Importmap is optional, but raise error if it is not installed. HOT 1
- v4: add accessible names for buttons HOT 5
- v4: on large screens, the sidebar navigation has `aria-hidden="true"` even if it is not hidden
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from activeadmin.