- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 API 模式下使用 Rails,使用 Devise 和 Devise JWT(用于 API)和 ActiveAdmin。我一切正常,但我一直在构建 API Controller ,现在 ActiveAdmin 身份验证已损坏,我无法弄清楚发生了什么。
所以我尝试直接转到 /admin/login
并且它有效。我输入我的用户名和密码,当我点击登录时,出现以下错误:
NoMethodError in ActiveAdmin::Devise::SessionsController#create
private method `redirect_to' called for #<ActiveAdmin::Devise::SessionsController:0x0000000001d420>
我不太确定为什么它会被破坏,因为它主要使用默认设置。
我的路线文件:
Rails.application.routes.draw do
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
...
我没有在 ActiveAdmin::Devise
中更改任何内容,我什至没有在我的代码库中显示这些文件。
在我的 Devise 配置中:
config.authentication_method = :authenticate_admin_user!
config.current_user_method = :current_admin_user
我的非 activeadmin session Controller 看起来像:
# frozen_string_literal: true
module Users
class SessionsController < Devise::SessionsController
respond_to :json
private
def respond_with(resource, _opts = {})
render json: {
status: { code: 200, message: 'Logged in sucessfully.' },
data: UserSerializer.new(resource).serializable_hash
}, status: :ok
end
def respond_to_on_destroy
if current_user
render json: {
status: 200,
message: 'logged out successfully'
}, status: :ok
else
render json: {
status: 401,
message: 'Couldn\'t find an active session.'
}, status: :unauthorized
end
end
end
end
这是我的管理员用户模型:
# frozen_string_literal: true
class AdminUser < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :validatable
end
当我忽略重定向错误时,我不相信登录实际上有效。我尝试转到任何页面,但收到相同的消息 You need to sign in or sign up before continue.
这是我的应用程序配置:
config.load_defaults 7.0
config.api_only = true
config.session_store :cookie_store, key: '_interslice_session'
# Required for all session management (regardless of session_store)
config.middleware.use ActionDispatch::Cookies
config.middleware.use Rack::MethodOverride
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Session::CookieStore
config.middleware.use config.session_store, config.session_options
我做错了什么?
更新代码:
class ApplicationController < ActionController::API
# https://github.com/rails/rails/blob/v7.0.2.3/actionpack/lib/action_controller/api.rb#L104
# skip modules that we need to load last
ActionController::API.without_modules(:Instrumentation, :ParamsWrapper).each do |m|
include m
end
# include what's missing
include ActionController::ImplicitRender
include ActionController::Helpers
include ActionView::Layouts
include ActionController::Flash
include ActionController::MimeResponds
# include modules that have to be last
include ActionController::Instrumentation
include ActionController::ParamsWrapper
ActiveSupport.run_load_hooks(:action_controller_api, self)
ActiveSupport.run_load_hooks(:action_controller, self)
respond_to :json, :html
def redirect_to(options = {}, response_options = {})
super
end
module Users
class SessionsController < Devise::SessionsController
respond_to :html
Rails.application.routes.draw do
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
devise_for :users, defaults: { format: :json }, path: '', path_names: {
sign_in: 'login',
sign_out: 'logout',
registration: 'signup'
},
controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations'
应用配置:
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.0
config.api_only = true
config.session_store :cookie_store, key: '_interslice_session'
# Required for all session management (regardless of session_store)
config.middleware.use ActionDispatch::Cookies
config.middleware.use Rack::MethodOverride
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Session::CookieStore
config.middleware.use config.session_store, config.session_options
最佳答案
这是我正在使用的设置,希望它是不言自明的,这样我们就可以找到实际的错误。
# Gemfile
# ...
gem "sprockets-rails"
gem "sassc-rails"
gem 'activeadmin'
gem 'devise'
gem 'devise-jwt'
# config/application.rb
require_relative "boot"
require "rails/all"
require "action_controller/railtie"
require "action_view/railtie"
require "sprockets/railtie"
Bundler.require(*Rails.groups)
module Rails7api
class Application < Rails::Application
config.load_defaults 7.0
config.api_only = true
config.session_store :cookie_store, key: '_interslice_session'
config.middleware.use ActionDispatch::Cookies
config.middleware.use Rack::MethodOverride
config.middleware.use ActionDispatch::Flash
config.middleware.use config.session_store, config.session_options
end
end
# config/routes.rb
Rails.application.routes.draw do
# Admin
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
# Api (api_users, name is just for clarity)
devise_for :api_users, defaults: { format: :json }
namespace :api, defaults: { format: :json } do
resources :users
end
end
# config/initializers/devise.rb
Devise.setup do |config|
# ...
config.jwt do |jwt|
# jwt.secret = ENV['DEVISE_JWT_SECRET_KEY']
jwt.secret = Rails.application.credentials.devise_jwt_secret_key!
end
end
# db/migrate/20220424045738_create_authentication.rb
class CreateAuthentication < ActiveRecord::Migration[7.0]
def change
create_table :admin_users do |t|
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
t.timestamps null: false
end
add_index :admin_users, :email, unique: true
create_table :api_users do |t|
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
t.timestamps null: false
end
add_index :api_users, :email, unique: true
create_table :jwt_denylist do |t|
t.string :jti, null: false
t.datetime :exp, null: false
end
add_index :jwt_denylist, :jti
end
end
# app/models/admin_user.rb
class AdminUser < ApplicationRecord
devise :database_authenticatable
end
# app/models/api_user.rb
class ApiUser < ApplicationRecord
devise :database_authenticatable, :jwt_authenticatable, jwt_revocation_strategy: JwtDenylist
self.skip_session_storage = [:http_auth, :params_auth] # https://github.com/waiting-for-dev/devise-jwt#session-storage-caveat
end
# app/models/jwt_denylist.rb
class JwtDenylist < ApplicationRecord
include Devise::JWT::RevocationStrategies::Denylist
self.table_name = 'jwt_denylist'
end
# app/application_controller.rb
class ApplicationController < ActionController::Base # for devise and active admin
respond_to :json, :html
end
# app/api/application_controller.rb
module Api
class ApplicationController < ActionController::API # for api
before_action :authenticate_api_user!
end
end
# app/api/users_controller.rb
module Api
class UsersController < ApplicationController
def index
render json: User.all
end
end
end
人们有几种不同的方式得到这个错误,但它们似乎是同一个问题的变体。我只能找到一种私有(private) redirect_to
方法,它甚至在文档中
https://api.rubyonrails.org/classes/ActionController/Flash.html#method-i-redirect_to
active_admin
和devise
都继承自ApplicationController
# ActiveAdmin::Devise::SessionsController < Devise::SessionsController < DeviseController < Devise.parent_controller.constantize # <= @@parent_controller = "ApplicationController"
# ActiveAdmin::BaseController < ::InheritedResources::Base < ::ApplicationController
当 ApplicationController
继承自 ActionController::API
时,事件管理因缺少依赖项而中断。所以我们必须一一包含它们,直到 rails boots 和 controller 看起来像这样
class ApplicationController < ActionController::API
include ActionController::Helpers # FIXES undefined method `helper' for ActiveAdmin::Devise::SessionsController:Class (NoMethodError)
include ActionView::Layouts # FIXES undefined method `layout' for ActiveAdmin::Devise::SessionsController:Class (NoMethodError)
include ActionController::Flash # FIXES undefined method `flash' for #<ActiveAdmin::Devise::SessionsController:0x0000000000d840>):
respond_to :json, :html # FIXES ActionController::UnknownFormat (ActionController::UnknownFormat):
end
这一直有效,直到您尝试登录并收到 private method 'redirect_to'
错误。一点调试和回溯指向 responders
gem,它用 html 响应,这没问题,即使我们的 Controller 是 api 并调用 redirect_to 但点击 Flash#redirect_to
而不是 Redirecting#redirect_to
#0 ActionController::Flash#redirect_to(options="/admin", response_options_and_flash={}) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2.3/lib/action_controller/metal/flash.rb:52
#1 ActionController::Responder#redirect_to at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:147
#2 ActionController::Responder#navigation_behavior(error=#<ActionView::MissingTemplate: Missing t...) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:207
#3 ActionController::Responder#to_html at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:174
#4 ActionController::Responder#to_html at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:171
#5 ActionController::Responder#respond at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:165
#6 ActionController::Responder.call(args=[#<ActiveAdmin::Devise::SessionsControll...) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:158
#7 ActionController::RespondWith#respond_with(resources=[#<AdminUser id: 1, email: "admin@user.c..., block=nil) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/respond_with.rb:213
#8 Devise::SessionsController#create at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/devise-4.8.1/app/controllers/devise/sessions_controller.rb:23
因为 API
Controller 相当纤薄
https://github.com/rails/rails/blob/v7.0.2.3/actionpack/lib/action_controller/api.rb#L112
比 Base
Controller
https://github.com/rails/rails/blob/v7.0.2.3/actionpack/lib/action_controller/base.rb#L205
好像少了什么。因此,使用 Base
Controller 进行一些调试和回溯确实揭示了一个微小的差异。
#0 ActionController::Flash#redirect_to(options="/admin", response_options_and_flash={}) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2.3/lib/action_controller/metal/flash.rb:52
#1 block {|payload={:request=>#<ActionDispatch::Request POS...|} in redirect_to at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2.3/lib/action_controller/metal/instrumentation.rb:42
#2 block in instrument at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.3/lib/active_support/notifications.rb:206
#3 ActiveSupport::Notifications::Instrumenter#instrument(name="redirect_to.action_controller", payload={:request=>#<ActionDispatch::Request POS...) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.3/lib/active_support/notifications/instrumenter.rb:24
#4 ActiveSupport::Notifications.instrument(name="redirect_to.action_controller", payload={:request=>#<ActionDispatch::Request POS...) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.3/lib/active_support/notifications.rb:206
#5 ActionController::Instrumentation#redirect_to at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2.3/lib/action_controller/metal/instrumentation.rb:41
#6 ActionController::Responder#redirect_to at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:147
#7 ActionController::Responder#navigation_behavior(error=#<ActionView::MissingTemplate: Missing t...) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:207
#8 ActionController::Responder#to_html at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:174
#9 ActionController::Responder#to_html at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:171
#10 ActionController::Responder#respond at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:165
#11 ActionController::Responder.call(args=[#<ActiveAdmin::Devise::SessionsControll...) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/responder.rb:158
#12 ActionController::RespondWith#respond_with(resources=[#<AdminUser id: 1, email: "admin@user.c..., block=nil) at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/responders-3.0.1/lib/action_controller/respond_with.rb:213
#13 Devise::SessionsController#create at ~/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/devise-4.8.1/app/controllers/devise/sessions_controller.rb:23
我想我们应该先点击 Instrumentation#redirect_to
。需要注意的是,Instrumentation
需要比其他模块晚加载。在 Base
Controller 中,Flash
模块位于 Instrumentation
之前。但是我们最后包含了 Flash
并且把事情搞砸了。我不知道是否有更好的方法来更改这些模块的顺序:
class ApplicationController < ActionController::Metal
# https://github.com/rails/rails/blob/v7.0.2.3/actionpack/lib/action_controller/api.rb#L104
# skip modules that we need to load last
ActionController::API.without_modules(:Instrumentation, :ParamsWrapper).each do |m|
include m
end
# include what's missing
include ActionController::ImplicitRender
include ActionController::Helpers
include ActionView::Layouts
include ActionController::Flash
include ActionController::MimeResponds
# include modules that have to be last
include ActionController::Instrumentation
include ActionController::ParamsWrapper
ActiveSupport.run_load_hooks(:action_controller_api, self)
ActiveSupport.run_load_hooks(:action_controller, self)
respond_to :json, :html
end
它修复了错误。但我觉得 ApplicationController
应该继承自 Base
,它使事情变得更简单,因为它被设计和事件管理员使用,使用 API
和为事件管理员添加模块似乎在原地打转。
@brcebn 解决方法确实有效。就像所有酷 child 一样,使用那种私有(private)方法。 https://github.com/heartcombo/responders/issues/222#issue-661963658
def redirect_to(options = {}, response_options = {})
super
end
这也有点麻烦,所以我不得不写一些测试。这些仅在 ApplicationController
继承自 Base
时有效。
# spec/requests/authentication_spec.rb
require 'rails_helper'
RSpec.describe 'Authentication', type: :request do
describe 'Edge case for Devise + JWT + RailsAPI + ActiveAdmin configuration' do
# This set up will raise private method error
#
# class ApplicationController < ActionController::API
# include ActionController::Helpers
# include ActionView::Layouts
# include ActionController::Flash # <= has private.respond_to
#
# respond_to :json, :html # when responding with html in an api controller
# end
#
before { AdminUser.create!(params) }
let(:params) { { email: 'admin@user.com', password: '123456' } }
it do
RSpec::Expectations.configuration.on_potential_false_positives = :nothing
expect{
post(admin_user_session_path, params: { admin_user: params })
}.to_not raise_error(NoMethodError)
end
it do
expect{
post(admin_user_session_path, params: { admin_user: params })
}.to_not raise_error
end
end
describe 'POST /api/users/sign_in' do
before { ApiUser.create!(params) }
before { post api_user_session_path, params: { api_user: params } }
let(:params) { { email: 'api@user.com', password: '123456' } }
it { expect(response).to have_http_status(:created) }
it { expect(headers['Authorization']).to include 'Bearer' }
it 'should not have admin access' do
get admin_dashboard_path
expect(response).to have_http_status(:redirect)
follow_redirect!
expect(request.path).to eq '/admin/login'
end
end
describe 'GET /api/users' do
context 'when signed out' do
before { get api_users_path }
it { expect(response.body).to include 'You need to sign in or sign up before continuing.' }
end
context 'when signed in' do
before { ApiUser.create!(params) }
before { post api_user_session_path, params: { api_user: params } }
let(:params) { { email: 'api@user.com', password: '123456' } }
it 'should not authorize without Authorization header' do
get api_users_path
expect(response.body).to include 'You need to sign in or sign up before continuing.'
end
it 'should authorize with Authorization header' do
get api_users_path, headers: { 'Authorization': headers['Authorization'] }
expect(response.body).to_not include 'You need to sign in or sign up before continuing.'
end
end
end
describe 'GET /admin' do
it do
get admin_root_path
expect(response).to have_http_status(:redirect)
end
context 'when api_user is authorized' do
before { ApiUser.create!(params) }
before { post api_user_session_path, params: { api_user: params } }
let(:params) { { email: 'api@user.com', password: '123456' } }
it 'should redirect without raising' do
get admin_root_path
expect(response).to have_http_status(:redirect)
end
end
end
describe 'POST /admin/login' do
before { AdminUser.create!(params) }
before { post admin_user_session_path, params: { admin_user: params } }
let(:params) { { email: 'admin@user.com', password: '123456' } }
it do
expect(response).to have_http_status(:redirect)
follow_redirect!
expect(response.body).to include 'Signed in successfully.'
end
end
describe 'DELETE /admin/logout' do
before { AdminUser.create!(params) }
before { post admin_user_session_path, params: { admin_user: params } }
let(:params) { { email: 'admin@user.com', password: '123456' } }
it 'should sign out' do
delete destroy_admin_user_session_path
expect(response).to have_http_status(:redirect)
follow_redirect!
expect(request.path).to eq '/unauthenticated' # <= what?
follow_redirect!
expect(response.body).to include 'Signed out successfully.'
expect(request.path).to eq '/admin/login'
end
end
end
$ rspec spec/requests/authentication_spec.rb
...........
Finished in 0.48745 seconds (files took 0.83 seconds to load)
11 examples, 0 failures
更新
上面的 ActionController::API.without_modules
解决方案似乎有很多问题,或者不是正确的方法,或者 ActiveSupport
Hook 不应该在内部运行应用程序 Controller
。
我发现的唯一其他方法是定义完整的自定义 Controller 并从中继承。继承部分似乎很重要(如果您知道为什么,请发表评论)。
# app/controllers/base_controller.rb
class BaseController < ActionController::Metal
abstract!
# Order of modules is important
# See: https://github.com/rails/rails/blob/v7.0.2.3/actionpack/lib/action_controller/base.rb#L205
MODULES = [
AbstractController::Rendering,
# Extra modules #################
ActionController::Helpers,
ActionView::Layouts,
ActionController::MimeResponds,
ActionController::Flash,
#################################
ActionController::UrlFor,
ActionController::Redirecting,
ActionController::ApiRendering,
ActionController::Renderers::All,
ActionController::ConditionalGet,
ActionController::BasicImplicitRender,
ActionController::StrongParameters,
ActionController::DataStreaming,
ActionController::DefaultHeaders,
ActionController::Logging,
# Before callbacks should also be executed as early as possible, so
# also include them at the bottom.
AbstractController::Callbacks,
# Append rescue at the bottom to wrap as much as possible.
ActionController::Rescue,
# Add instrumentations hooks at the bottom, to ensure they instrument
# all the methods properly.
ActionController::Instrumentation,
# Params wrapper should come before instrumentation so they are
# properly showed in logs
ActionController::ParamsWrapper
]
MODULES.each do |mod|
include mod
end
ActiveSupport.run_load_hooks(:action_controller_api, self)
ActiveSupport.run_load_hooks(:action_controller, self)
end
# app/application_controller.rb
class ApplicationController < BaseController # use for everything
respond_to :json, :html
end
# app/api/users_controller.rb
module Api
class UsersController < ApplicationController
before_action :authenticate_api_user!
def index
render json: User.all
end
end
end
已测试!
12 examples, 0 failures
关于ruby-on-rails - Active Admin 登录不起作用(Devise + ActiveAdmin + Devise JWT),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71904776/
我只是希望我所有的管理页面都在 /admin 下. 我的主页在 /admin但是当我单击侧栏中的用户时,它会将路径更改为 /users而不是 /admin/users . 我正在使用 rea
我在端口 8011 上设置了一个 Django 服务器,并在端口 80 上有一个 nginx 作为子目录服务。 静态文件,不错。 页面,很好。 但是当我访问/subdirectory/admin/时,
我正在尝试使用 Flask 和 Flask-SuperAdmin 自定义我的 Admin View ,但是,索引 View 和 subview 显然没有使用相同的 is_accessible 方法:
我正在尝试配置我的 .htaccess,以便当有人导航到路径 /wp-admin/admin.php?page=something 时,路径 /wp-admin/something显示在浏览器中,内容
有没有办法整体禁用分页?我希望我的所有记录都显示在一个长列表中,而不是分成几页。我现在正在使用 ListGuesser,我已经尝试过 List 和 ListGuesser,但我无法禁用分页。实际上 r
在本地部署时,我的 RA 项目呈现良好,但是,当我将构建目录复制到 S3 存储桶进行部署时,它呈现的一切都一团糟。有时它有效,但大多数时候它呈现如下图所示。它在带有 AOR 的两种环境中都能正常工作。
我试图在 Datagrid 中显示Field这是多对多关系(中间表)。 我有这些表: 组 - group_subject - 主题 一个小组可以有多个科目 一个主题可以连接多个群组 group_sub
在用于显示用户列表的 Django 管理屏幕中(带有标题,选择要更改的用户),有用户名/电子邮件等字段和员工状态。我想将用户的事件状态添加到该显示中。 尽管大多数 django-admin 自定义问题
无论如何要检查所有 firebase 事务是否在 firebase-admin nodejs 脚本中完成,并正确断开与 firebase 的连接并退出 nodejs 脚本? 目前,即使在所有事务完成后
我正在尝试使用 react-admin 将数据发送到我的自定义 API。我想发送文件,我可以看到有,我想将该数据作为多部分表单数据发送。我遇到过the base64 encoding help pag
我正在尝试在admin部分中实现带有子表单的表单。 form = Fighter() subform = FighterFightHistory() //All of his fights 我的问题如
我在编辑表单中获取记录的“更新”值时遇到了很大的麻烦。我总是得到初始记录值,即使我有一个链接到正确记录源的输入,它应该更新它。 有没有其他方法来获取 SimpleForm 的值? 我有一个简单的编辑表
开发一个不需要翻译的管理员。有没有办法完全关闭它们。就像现在一样,对于诸如通知之类的事情,它们会显示,但我也会收到有关缺少翻译键的控制台警告。 最佳答案 除了 Frederik 的回答之外,以下是禁用
开发一个不需要翻译的管理员。有没有办法完全关闭它们。就像现在一样,对于诸如通知之类的事情,它们会显示,但我也会收到有关缺少翻译键的控制台警告。 最佳答案 除了 Frederik 的回答之外,以下是禁用
我有这样的模型: class User(db.Model): __tablename__ = 'users' __table_args__ = {'mysql_engine' : 'I
我已经使用 Media 类自定义了我的内联模型。 我想自定义内联字段集以实现两件事: 为每一行添加一个按钮 按下“添加新行”时从 javascript 代码运行 我试过覆盖 tabular.html
我的所有管理员/任何 url 正在呈现管理文件,但是当我尝试只点击管理员时,它显示 404 不在这条路线上。我可以为 url/admin 创建单独的路由,但这是他们的任何其他选项。这样我只能通过单一路
虽然我使用了许多图表,如 HighCharts、Charts.js、C3、D3,但是否有人尝试过或是否有一些关于如何将任何图表框架包含在 React-admin 中的文档?我看了一些,但看起来我们必须
react-admin 文档将资源的默认路由解释为: /posts/:id 映射到 PostEdit /posts/:id/show 映射到 PostShow 我希望我的应用程序默认为查看,并且仅当用
我正在使用 react-admin 前端框架,想知道是否有办法从路由中删除“#”。我正在使用 customRoutes 属性为我们的系统提供路由集合。 ``` 最佳答案 您可以创建自己的历
我是一名优秀的程序员,十分优秀!