Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion .github/workflows/linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ jobs:
reviewdog:
name: Reviewdog
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write

steps:
- name: Checkout repository
Expand All @@ -19,7 +22,7 @@ jobs:
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
ruby-version: '3.2'
bundler-cache: true

- name: Set up Reviewdog
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

strategy:
matrix:
ruby: ['3.0', '3.1', '3.2', '3.3', '3.4', '4.0']
ruby: ['3.2', '3.3', '3.4', '4.0']

steps:
- name: Checkout repository
Expand Down
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ AllCops:
- vendor/**/*
NewCops: enable
SuggestExtensions: false
TargetRubyVersion: 3.0
TargetRubyVersion: 3.2

Lint/MissingSuper:
Exclude:
Expand Down
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
lint:
bin/rubocop
specs:
RUBYOPT='-rbundler/setup -rrbs/test/setup' RBS_TEST_TARGET='TinyAdmin::*' bin/rspec

test:
bin/rspec
server:
cd spec/dummy_rails/ && bin/rails s

test_rbs:
RUBYOPT='-rbundler/setup -rrbs/test/setup' RBS_TEST_TARGET='TinyAdmin::*' bin/rspec
seed:
cd spec/dummy_rails/ && bin/rails db:migrate && bin/rails db:seed
8 changes: 5 additions & 3 deletions lib/tiny_admin/basic_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ class BasicApp < Roda
include Utils

class << self
include Utils

def authentication_plugin
plugin = TinyAdmin.settings.authentication&.dig(:plugin)
plugin_class = plugin.is_a?(String) ? Object.const_get(plugin) : plugin
plugin_class = to_class(plugin) if plugin
plugin_class || TinyAdmin::Plugins::NoAuth
end
end

plugin :flash
plugin :not_found
plugin :render, engine: 'html'
plugin :sessions, secret: SecureRandom.hex(64)
plugin :render, engine: "html"
plugin :sessions, secret: ENV.fetch("TINY_ADMIN_SECRET") { SecureRandom.hex(64) }

plugin authentication_plugin, TinyAdmin.settings.authentication

Expand Down
3 changes: 1 addition & 2 deletions lib/tiny_admin/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ module TinyAdmin
:repository,
:request,
:router,
:slug,
keyword_init: true
:slug
)
end
9 changes: 5 additions & 4 deletions lib/tiny_admin/field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ def initialize(name:, title:, type:, options: {})
end

def apply_call_option(target)
messages = (options[:call] || '').split(',').map(&:strip)
messages = (options[:call] || "").split(",").map(&:strip)
messages.inject(target) { |result, msg| result&.send(msg) } if messages.any?
end

def translate_value(value)
if options && options[:method]
method, *args = options[:method].split(',').map(&:strip)
method, *args = options[:method].split(",").map(&:strip)
if options[:converter]
Object.const_get(options[:converter]).send(method, value, options: args || [])
else
Expand All @@ -30,10 +30,11 @@ def translate_value(value)
end

class << self
include Utils

def create_field(name:, title: nil, type: nil, options: {})
field_name = name.to_s
field_title = field_name.respond_to?(:humanize) ? field_name.humanize : field_name.tr('_', ' ').capitalize
new(name: field_name, title: title || field_title, type: type || :string, options: options || {})
new(name: field_name, title: title || humanize(field_name), type: type || :string, options: options || {})
end
end
end
Expand Down
38 changes: 18 additions & 20 deletions lib/tiny_admin/router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Router < BasicApp
route do |r|
TinyAdmin.settings.load_settings

r.on 'auth' do
r.on "auth" do
r.run Authentication
end

Expand All @@ -25,7 +25,7 @@ class Router < BasicApp
# :nocov:
end

r.post '' do
r.post "" do
r.redirect TinyAdmin.settings.root_path
end

Expand All @@ -48,32 +48,28 @@ def store

def render_page(page)
if page.respond_to?(:messages=)
page.messages = { notices: flash['notices'], warnings: flash['warnings'], errors: flash['errors'] }
page.messages = { notices: flash["notices"], warnings: flash["warnings"], errors: flash["errors"] }
end
render(inline: page.call)
end

def root_route(req)
if authorization.allowed?(current_user, :root)
authorize!(:root) do
if TinyAdmin.settings.root[:redirect]
req.redirect route_for(TinyAdmin.settings.root[:redirect])
else
page_class = to_class(TinyAdmin.settings.root[:page])
attributes = TinyAdmin.settings.root.slice(:content, :title, :widgets)
render_page prepare_page(page_class, attributes: attributes, params: request.params)
end
else
render_page prepare_page(TinyAdmin.settings.page_not_allowed)
end
end

def setup_page_route(req, slug, page_data)
req.get slug do
if authorization.allowed?(current_user, :page, slug)
authorize!(:page, slug) do
attributes = page_data.slice(:content, :title, :widgets)
render_page prepare_page(page_data[:class], slug: slug, attributes: attributes, params: request.params)
else
render_page prepare_page(TinyAdmin.settings.page_not_allowed)
end
end
end
Expand All @@ -99,9 +95,9 @@ def setup_collection_routes(req, slug, options:)
)

# Index
if options[:only].include?(:index) || options[:only].include?('index')
if options[:only].include?(:index) || options[:only].include?("index")
req.is do
if authorization.allowed?(current_user, :resource_index, slug)
authorize!(:resource_index, slug) do
context = Context.new(
actions: custom_actions,
repository: repository,
Expand All @@ -111,8 +107,6 @@ def setup_collection_routes(req, slug, options:)
)
index_action = TinyAdmin::Actions::Index.new
render_page index_action.call(app: self, context: context, options: action_options)
else
render_page prepare_page(TinyAdmin.settings.page_not_allowed)
end
end
end
Expand All @@ -134,9 +128,9 @@ def setup_member_routes(req, slug, options:)
)

# Show
if options[:only].include?(:show) || options[:only].include?('show')
if options[:only].include?(:show) || options[:only].include?("show")
req.is do
if authorization.allowed?(current_user, :resource_show, slug)
authorize!(:resource_show, slug) do
context = Context.new(
actions: custom_actions,
reference: reference,
Expand All @@ -147,8 +141,6 @@ def setup_member_routes(req, slug, options:)
)
show_action = TinyAdmin::Actions::Show.new
render_page show_action.call(app: self, context: context, options: action_options)
else
render_page prepare_page(TinyAdmin.settings.page_not_allowed)
end
end
end
Expand All @@ -161,7 +153,7 @@ def setup_custom_actions(req, custom_actions = nil, options:, repository:, slug:
action_class = to_class(action)

req.get action_slug.to_s do
if authorization.allowed?(current_user, :custom_action, action_slug.to_s)
authorize!(:custom_action, action_slug.to_s) do
context = Context.new(
actions: {},
reference: reference,
Expand All @@ -172,8 +164,6 @@ def setup_custom_actions(req, custom_actions = nil, options:, repository:, slug:
)
custom_action = action_class.new
render_page custom_action.call(app: self, context: context, options: options)
else
render_page prepare_page(TinyAdmin.settings.page_not_allowed)
end
end

Expand All @@ -184,5 +174,13 @@ def setup_custom_actions(req, custom_actions = nil, options:, repository:, slug:
def authorization
TinyAdmin.settings.authorization_class
end

def authorize!(action, param = nil)
if authorization.allowed?(current_user, action, param)
yield
else
render_page prepare_page(TinyAdmin.settings.page_not_allowed)
end
end
end
end
15 changes: 10 additions & 5 deletions lib/tiny_admin/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class Settings
%i[page_not_found] => Views::Pages::PageNotFound,
%i[record_not_found] => Views::Pages::RecordNotFound,
%i[repository] => Plugins::ActiveRecordRepository,
%i[root_path] => '/admin',
%i[root_path] => "/admin",
%i[root page] => Views::Pages::Root,
%i[root title] => 'TinyAdmin',
%i[root title] => "TinyAdmin",
%i[sections] => []
}.freeze

Expand Down Expand Up @@ -67,6 +67,8 @@ def []=(*path, value)
end

def load_settings
return if @loaded

# default values
DEFAULTS.each do |(option, param), default|
if param
Expand All @@ -78,17 +80,20 @@ def load_settings
end

@store ||= TinyAdmin::Store.new(self)
self.root_path = '/' if root_path == ''
self.root_path = "/" if root_path == ""

if authentication[:plugin] <= Plugins::SimpleAuth
if authentication[:plugin].is_a?(Module) && authentication[:plugin] <= Plugins::SimpleAuth
logout_path = "#{root_path}/auth/logout"
authentication[:logout] ||= TinyAdmin::Section.new(name: 'logout', slug: 'logout', path: logout_path)
authentication[:logout] ||= TinyAdmin::Section.new(name: "logout", slug: "logout", path: logout_path)
end
store.prepare_sections(sections, logout: authentication[:logout])
@loaded = true
end

def reset!
@options = {}
@store = nil
@loaded = false
end

private
Expand Down
19 changes: 8 additions & 11 deletions lib/tiny_admin/store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@ def prepare_sections(sections, logout:)
end

slug = section[:slug].to_s
case section[:type]&.to_sym
when :content
list << add_content_section(slug, section)
when :page
list << add_page_section(slug, section)
when :resource
list << add_resource_section(slug, section)
when :url
list << add_url_section(slug, section)
end
item = case section[:type]&.to_sym
when :content then add_content_section(slug, section)
when :page then add_page_section(slug, section)
when :resource then add_resource_section(slug, section)
when :url then add_url_section(slug, section)
end
list << item if item
end
navbar << logout if logout
end
Expand All @@ -56,7 +53,7 @@ def add_resource_section(slug, section)
repository: to_class(section[:repository] || settings.repository)
)

hidden = section[:options] && (section[:options].include?(:hidden) || section[:options].include?('hidden'))
hidden = section[:options] && (section[:options].include?(:hidden) || section[:options].include?("hidden"))
TinyAdmin::Section.new(name: section[:name], slug: slug) unless hidden
end

Expand Down
6 changes: 4 additions & 2 deletions lib/tiny_admin/support.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ def round(value, options: [])
end

def strftime(value, options: [])
value&.strftime(options&.first || '%Y-%m-%d %H:%M')
value&.strftime(options&.first || "%Y-%m-%d %H:%M")
end

def to_date(value, options: [])
value.to_date.to_s if value
value&.to_date&.to_s
rescue NoMethodError, ArgumentError
value&.to_s
end

def upcase(value, options: [])
Expand Down
12 changes: 7 additions & 5 deletions lib/tiny_admin/utils.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
# frozen_string_literal: true

require "cgi"

module TinyAdmin
module Utils
def params_to_s(params)
list = params.each_with_object([]) do |(param, value), result|
if value.is_a?(Hash)
values = value.map { |key, val| "#{param}[#{key}]=#{val}" }
values = value.map { |key, val| "#{CGI.escape(param.to_s)}[#{CGI.escape(key.to_s)}]=#{CGI.escape(val.to_s)}" }
result.concat(values)
else
result.push(["#{param}=#{value}"])
result.push("#{CGI.escape(param.to_s)}=#{CGI.escape(value.to_s)}")
end
end
list.join('&')
list.join("&")
end

def prepare_page(page_class, slug: nil, attributes: nil, options: nil, params: nil)
Expand Down Expand Up @@ -40,9 +42,9 @@ def to_class(klass)
end

def humanize(string)
return '' unless string
return "" unless string

string.respond_to?(:humanize) ? string.humanize : string.tr('_', ' ').capitalize
string.respond_to?(:humanize) ? string.humanize : string.tr("_", " ").capitalize
end
end
end
Loading
Loading