Skip to content
Merged
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
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ gem "jbuilder"
# HTML-aware ERB rendering via the Herb engine [https://reactionview.dev]
gem "reactionview"

# Admin dashboard for super admins [https://avohq.io]
gem "avo", "~> 3.2"

# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
gem "bcrypt", "~> 3.1.7"

Expand Down
44 changes: 44 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,29 @@ GEM
specs:
action_text-trix (2.1.19)
railties
active_link_to (1.0.5)
actionpack
addressable
addressable (2.9.0)
public_suffix (>= 2.0.2, < 8.0)
ast (2.4.3)
avo (3.32.1)
actionview (>= 6.1)
active_link_to
activerecord (>= 6.1)
activesupport (>= 6.1)
addressable
avo-icons (>= 0.1.2)
docile
meta-tags
pagy (>= 7.0.0, < 43)
prop_initializer (>= 0.3.0)
turbo-rails (>= 2.0.0)
turbo_power (>= 0.6.0)
view_component (>= 3.7.0)
zeitwerk (>= 2.6.12)
avo-icons (0.1.6)
inline_svg
base64 (0.3.0)
bcrypt (3.1.22)
bcrypt_pbkdf (1.1.2)
Expand Down Expand Up @@ -176,6 +196,9 @@ GEM
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
inline_svg (1.10.0)
activesupport (>= 3.0)
nokogiri (>= 1.6)
io-console (0.8.2)
irb (1.18.0)
pp (>= 0.6.0)
Expand Down Expand Up @@ -217,6 +240,8 @@ GEM
net-smtp
marcel (1.2.1)
matrix (0.4.3)
meta-tags (2.23.0)
actionpack (>= 6.0.0)
mini_magick (5.3.1)
logger
mini_mime (1.1.5)
Expand Down Expand Up @@ -254,6 +279,7 @@ GEM
nokogiri (1.19.4-x86_64-linux-musl)
racc (~> 1.4)
ostruct (0.6.3)
pagy (9.4.0)
parallel (2.1.0)
parser (3.3.11.1)
ast (~> 2.4.1)
Expand All @@ -267,6 +293,8 @@ GEM
prettyprint
prettyprint (0.2.0)
prism (1.9.0)
prop_initializer (0.4.0)
zeitwerk (>= 2.6.18)
propshaft (1.3.2)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
Expand Down Expand Up @@ -405,13 +433,19 @@ GEM
turbo-rails (2.0.23)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
turbo_power (0.7.0)
turbo-rails (>= 1.3.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.2.0)
uri (1.1.1)
useragent (0.16.11)
view_component (4.12.0)
actionview (>= 7.1.0)
activesupport (>= 7.1.0)
concurrent-ruby (~> 1)
web-console (4.3.0)
actionview (>= 8.0.0)
bindex (>= 0.4.0)
Expand All @@ -437,6 +471,7 @@ PLATFORMS
x86_64-linux-musl

DEPENDENCIES
avo (~> 3.2)
bcrypt (~> 3.1.7)
bootsnap
brakeman
Expand Down Expand Up @@ -477,13 +512,16 @@ CHECKSUMS
actionpack (8.1.3)
actiontext (8.1.3)
actionview (8.1.3)
active_link_to (1.0.5) sha256=4830847b3d14589df1e9fc62038ceec015257fce975ec1c2a77836c461b139ba
activejob (8.1.3)
activemodel (8.1.3)
activerecord (8.1.3)
activestorage (8.1.3)
activesupport (8.1.3)
addressable (2.9.0) sha256=7fdf6ac3660f7f4e867a0838be3f6cf722ace541dd97767fa42bc6cfa980c7af
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
avo (3.32.1) sha256=0cbc80204734585769fdc68c2721c749b754cd3f8139d4da0667b4c4b22fe849
avo-icons (0.1.6) sha256=6f1c985aca238d81446e517cee4924752e7ada1604971f6bb59913472e123f4c
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
bcrypt (3.1.22) sha256=1f0072e88c2d705d94aff7f2c5cb02eb3f1ec4b8368671e19112527489f29032
bcrypt_pbkdf (1.1.2) sha256=c2414c23ce66869b3eb9f643d6a3374d8322dfb5078125c82792304c10b94cf6
Expand Down Expand Up @@ -528,6 +566,7 @@ CHECKSUMS
i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5
image_processing (1.14.0) sha256=754cc169c9c262980889bec6bfd325ed1dafad34f85242b5a07b60af004742fb
importmap-rails (2.2.3) sha256=7101be2a4dc97cf1558fb8f573a718404c5f6bcfe94f304bf1f39e444feeb16a
inline_svg (1.10.0) sha256=5b652934236fd9f8adc61f3fd6e208b7ca3282698b19f28659971da84bf9a10f
io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
jbuilder (2.15.1) sha256=2430bec28fb0cebacb5875b1009cf9d8bc3c303ccb810c4c8b062a4b51457637
Expand All @@ -542,6 +581,7 @@ CHECKSUMS
mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941
marcel (1.2.1) sha256=1678e9360e32f9eafa917c80029e2f6d10b2715c66a4b87b6d0da9b9cd1f859f
matrix (0.4.3) sha256=a0d5ab7ddcc1973ff690ab361b67f359acbb16958d1dc072b8b956a286564c5b
meta-tags (2.23.0) sha256=ffe78b5bee398de4ff5ac3316f5a786049538a651643b8476def06c3acc762c1
mini_magick (5.3.1) sha256=29395dfd76badcabb6403ee5aff6f681e867074f8f28ce08d78661e9e4a351c4
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
Expand All @@ -562,13 +602,15 @@ CHECKSUMS
nokogiri (1.19.4-x86_64-linux-gnu) sha256=379fae440b28915e3f19d752ce2dcf8465ed2b2fbefd2a7ca0dd497bc981a06a
nokogiri (1.19.4-x86_64-linux-musl) sha256=17dfb7c1fa194ae02fbf7c51a7afc8d278045ab3fdacfd86f91d02d7b274470b
ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
pagy (9.4.0) sha256=db3f2e043f684155f18f78be62a81e8d033e39b9f97b1e1a8d12ad38d7bce738
parallel (2.1.0) sha256=b35258865c2e31134c5ecb708beaaf6772adf9d5efae28e93e99260877b09356
parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54
postmark (1.25.1) sha256=2ac110fa1b4f85a62996fdc63167922eea1c4284a9a7ceb9e007f2758d9e17be
postmark-rails (0.22.1) sha256=fcea27dda4f7418123d7723622ec5447df4dacacc10a20a40add0f6789135d8f
pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
prop_initializer (0.4.0) sha256=487d31d44a58ec7654a7db9eb23cad30030a5bbf16e6a53c71e3cbb88be9e1d8
propshaft (1.3.2) sha256=1d56a3e56a92c21bfc29caf07406b5386b00d4c47ddf357cf989a5a234b1389e
psych (5.4.0) sha256=14f72d69a611af663d7d70e4a7b67d9eb1f3ae9f8d916b478961d5a0075ba5b7
public_suffix (7.0.5) sha256=1a8bb08f1bbea19228d3bed6e5ed908d1cb4f7c2726d18bd9cadf60bc676f623
Expand Down Expand Up @@ -631,11 +673,13 @@ CHECKSUMS
timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb
tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
turbo-rails (2.0.23) sha256=ee0d90733aafff056cf51ff11e803d65e43cae258cc55f6492020ec1f9f9315f
turbo_power (0.7.0) sha256=ad95d147e0fa761d0023ad9ca00528c7b7ddf6bba8ca2e23755d5b21b290d967
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
useragent (0.16.11) sha256=700e6413ad4bb954bb63547fa098dddf7b0ebe75b40cc6f93b8d54255b173844
view_component (4.12.0) sha256=b9a5979d1c43eba2aa21a06a86f661aab3990104855f2909ef7c3779acdcdcb4
web-console (4.3.0) sha256=e13b71301cdfc2093f155b5aa3a622db80b4672d1f2f713119cc7ec7ac6a6da4
websocket (1.2.11) sha256=b7e7a74e2410b5e85c25858b26b3322f29161e300935f70a0e0d3c35e0462737
websocket-driver (0.8.1) sha256=5ab238238ce230e5d4b262d2be39624c867914eab99171dc4952b58b577c2d96
Expand Down
17 changes: 17 additions & 0 deletions app/avo/resources/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Avo::Resources::User < Avo::BaseResource
self.title = :email_address

def fields
field :id, as: :id
field :email_address, as: :text, readonly: true
field :name, as: :text, readonly: true

field :super_admin, as: :boolean

field :confirmed_at, as: :date_time, readonly: true
field :created_at, as: :date_time, readonly: true, only_on: :show
field :updated_at, as: :date_time, readonly: true, only_on: :show

field :organizations, as: :has_many, through: :organization_memberships
end
end
4 changes: 4 additions & 0 deletions app/controllers/avo/users_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This controller has been generated to enable Rails' resource routes.
# More information on https://docs.avohq.io/3.0/controllers.html
class Avo::UsersController < Avo::ResourcesController
end
2 changes: 1 addition & 1 deletion app/controllers/concerns/authentication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def resume_session
end

def find_session_by_cookie
Session.find_by(id: cookies.signed[:session_id]) if cookies.signed[:session_id]
Session.find_by_cookie(cookies)
end

def request_authentication
Expand Down
4 changes: 4 additions & 0 deletions app/models/session.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
class Session < ApplicationRecord
belongs_to :user

def self.find_by_cookie(cookies)
find_by(id: cookies.signed[:session_id]) if cookies.signed[:session_id]
end
end
172 changes: 172 additions & 0 deletions config/initializers/avo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# For more information regarding these settings check out our docs https://docs.avohq.io
# The values disaplayed here are the default ones. Uncomment and change them to fit your needs.
Avo.configure do |config|
## == Routing ==
config.root_path = "/avo"
# used only when you have custom `map` configuration in your config.ru
# config.prefix_path = "/internal"

# Where should the user be redirected when visiting the `/avo` url
# config.home_path = nil

## == Licensing ==
# config.license_key = ENV['AVO_LICENSE_KEY']

## == Set the context ==
config.set_context do
# Return a context object that gets evaluated within Avo::ApplicationController
end

## == Authentication ==
# This app has no `current_user` helper — sessions are resolved into Current.user.
config.current_user_method do
Current.user
end

# Avo's controllers don't run the app's Authentication/SetCurrentOrganization
# concerns, so Current is empty here. Resume the session from the signed cookie
# (same lookup as Authentication#resume_session), then allow only super_admins.
# Everyone else is sent back to the app's home page via main_app.
config.authenticate_with do
Current.session ||= Session.find_by_cookie(cookies)

redirect_to main_app.root_path unless Current.user&.super_admin?
end

## == Authorization ==
# config.is_admin_method = :is_admin
# config.is_developer_method = :is_developer
# config.authorization_methods = {
# index: 'index?',
# show: 'show?',
# edit: 'edit?',
# new: 'new?',
# update: 'update?',
# create: 'create?',
# destroy: 'destroy?',
# search: 'search?',
# }
# config.raise_error_on_missing_policy = false
config.authorization_client = nil
config.explicit_authorization = true

## == Localization ==
# config.locale = 'en-US'

## == Resource options ==
# config.resource_row_controls_config = {
# placement: :right,
# float: false,
# show_on_hover: false
# }.freeze
# config.model_resource_mapping = {}
# config.default_view_type = :table
# config.per_page = 24
# config.per_page_steps = [12, 24, 48, 72]
# config.via_per_page = 8
# config.id_links_to_resource = false
# config.pagination = -> do
# {
# type: :default,
# size: 9, # `[1, 2, 2, 1]` for pagy < 9.0
# }
# end

## == Response messages dismiss time ==
# config.alert_dismiss_time = 5000


## == Number of search results to display ==
# config.search_results_count = 8

## == Associations lookup list limit ==
# config.associations_lookup_list_limit = 1000

## == Cache options ==
## Provide a lambda to customize the cache store used by Avo.
## We compute the cache store by default, this is NOT the default, just an example.
# config.cache_store = -> {
# ActiveSupport::Cache.lookup_store(:solid_cache_store)
# }
# config.cache_resources_on_index_view = true

## == Turbo options ==
# config.turbo = -> do
# {
# instant_click: true
# }
# end

## == Logger ==
# config.logger = -> {
# file_logger = ActiveSupport::Logger.new(Rails.root.join("log", "avo.log"))
#
# file_logger.datetime_format = "%Y-%m-%d %H:%M:%S"
# file_logger.formatter = proc do |severity, time, progname, msg|
# "[Avo] #{time}: #{msg}\n".tap do |i|
# puts i
# end
# end
#
# file_logger
# }

## == Customization ==
config.click_row_to_view_record = true
# config.app_name = 'Avocadelicious'
# config.timezone = 'UTC'
# config.currency = 'USD'
# config.hide_layout_when_printing = false
# config.full_width_container = false
# config.full_width_index_view = false
# config.search_debounce = 300
# config.view_component_path = "app/components"
# config.display_license_request_timeout_error = true
# config.disabled_features = []
# config.buttons_on_form_footers = true
# config.field_wrapper_layout = true
# config.resource_parent_controller = "Avo::ResourcesController"
# config.first_sorting_option = :desc # :desc or :asc
# config.exclude_from_status = []
# config.model_generator_hook = true

## == Branding ==
# config.branding = {
# colors: {
# background: "248 246 242",
# 100 => "#CEE7F8",
# 400 => "#399EE5",
# 500 => "#0886DE",
# 600 => "#066BB2",
# },
# chart_colors: ["#0B8AE2", "#34C683", "#2AB1EE", "#34C6A8"],
# logo: "/avo-assets/logo.png",
# logomark: "/avo-assets/logomark.png",
# placeholder: "/avo-assets/placeholder.svg",
# favicon: "/avo-assets/favicon.ico"
# }

## == Breadcrumbs ==
# config.display_breadcrumbs = true
# config.set_initial_breadcrumbs do
# add_breadcrumb "Home", '/avo'
# end

## == Menus ==
# config.main_menu = -> {
# section "Dashboards", icon: "avo/dashboards" do
# all_dashboards
# end

# section "Resources", icon: "avo/resources" do
# all_resources
# end

# section "Tools", icon: "avo/tools" do
# all_tools
# end
# }
# config.profile_menu = -> {
# link "Profile", path: "/avo/profile", icon: "heroicons/outline/user-circle"
# }
end
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Rails.application.routes.draw do
mount_avo

# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
resource :home
resource :dashboard, only: :show
Expand Down
Loading
Loading