munificent-admin 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/LICENCE +2 -0
  3. data/README.md +83 -0
  4. data/Rakefile +12 -0
  5. data/app/abilities/munificent/admin/ability.rb +51 -0
  6. data/app/abilities/munificent/admin/application_ability.rb +37 -0
  7. data/app/assets/config/munificent_admin_manifest.js +4 -0
  8. data/app/assets/javascripts/munificent_admin/application.js +6 -0
  9. data/app/assets/stylesheets/munificent/admin/application.scss +2 -0
  10. data/app/assets/stylesheets/munificent/admin/layout.scss +64 -0
  11. data/app/assets/stylesheets/munificent/admin/records.scss +7 -0
  12. data/app/controllers/munificent/admin/application_controller.rb +61 -0
  13. data/app/controllers/munificent/admin/bundle_tiers_controller.rb +12 -0
  14. data/app/controllers/munificent/admin/bundles_controller.rb +86 -0
  15. data/app/controllers/munificent/admin/charities_controller.rb +60 -0
  16. data/app/controllers/munificent/admin/dashboard_controller.rb +9 -0
  17. data/app/controllers/munificent/admin/donations_controller.rb +9 -0
  18. data/app/controllers/munificent/admin/donator_bundles_controller.rb +9 -0
  19. data/app/controllers/munificent/admin/donators_controller.rb +9 -0
  20. data/app/controllers/munificent/admin/fundraisers_controller.rb +68 -0
  21. data/app/controllers/munificent/admin/games_controller.rb +65 -0
  22. data/app/controllers/munificent/admin/otp_controller.rb +57 -0
  23. data/app/controllers/munificent/admin/user_sessions_controller.rb +44 -0
  24. data/app/controllers/munificent/admin/users_controller.rb +77 -0
  25. data/app/form_builders/munificent/admin/form_builder.rb +112 -0
  26. data/app/helpers/munificent/admin/application_helper.rb +6 -0
  27. data/app/helpers/munificent/admin/form_helper.rb +9 -0
  28. data/app/helpers/munificent/admin/layout_helper.rb +11 -0
  29. data/app/helpers/munificent/admin/state_machine_helper.rb +49 -0
  30. data/app/mailers/munificent/admin/application_mailer.rb +8 -0
  31. data/app/mailers/munificent/admin/panic_mailer.rb +19 -0
  32. data/app/models/concerns/authenticable.rb +9 -0
  33. data/app/models/munificent/admin/application_record.rb +7 -0
  34. data/app/models/munificent/admin/user.rb +54 -0
  35. data/app/models/munificent/admin/user_session.rb +19 -0
  36. data/app/presenters/munificent/admin/application_presenter.rb +29 -0
  37. data/app/presenters/munificent/admin/user_presenter.rb +24 -0
  38. data/app/presenters/munificent/bundle_presenter.rb +27 -0
  39. data/app/presenters/munificent/bundle_tier_presenter.rb +20 -0
  40. data/app/presenters/munificent/charity_presenter.rb +14 -0
  41. data/app/presenters/munificent/donation_presenter.rb +39 -0
  42. data/app/presenters/munificent/donator_bundle_presenter.rb +12 -0
  43. data/app/presenters/munificent/donator_presenter.rb +12 -0
  44. data/app/presenters/munificent/fundraiser_presenter.rb +41 -0
  45. data/app/presenters/munificent/game_presenter.rb +20 -0
  46. data/app/views/layouts/munificent/admin/application.html.erb +87 -0
  47. data/app/views/munificent/admin/bundles/_form.html.erb +15 -0
  48. data/app/views/munificent/admin/bundles/_tier_form.html.erb +13 -0
  49. data/app/views/munificent/admin/bundles/edit.html.erb +12 -0
  50. data/app/views/munificent/admin/bundles/index.html.erb +15 -0
  51. data/app/views/munificent/admin/bundles/new.html.erb +9 -0
  52. data/app/views/munificent/admin/bundles/show.html.erb +44 -0
  53. data/app/views/munificent/admin/charities/_form.html.erb +11 -0
  54. data/app/views/munificent/admin/charities/edit.html.erb +3 -0
  55. data/app/views/munificent/admin/charities/index.html.erb +11 -0
  56. data/app/views/munificent/admin/charities/new.html.erb +3 -0
  57. data/app/views/munificent/admin/charities/show.html.erb +23 -0
  58. data/app/views/munificent/admin/common/_record.html.erb +18 -0
  59. data/app/views/munificent/admin/common/_records.html.erb +38 -0
  60. data/app/views/munificent/admin/dashboard/index.html.erb +3 -0
  61. data/app/views/munificent/admin/donations/index.html.erb +15 -0
  62. data/app/views/munificent/admin/donator_bundles/index.html.erb +10 -0
  63. data/app/views/munificent/admin/donators/index.html.erb +11 -0
  64. data/app/views/munificent/admin/fundraisers/_form.html.erb +16 -0
  65. data/app/views/munificent/admin/fundraisers/edit.html.erb +3 -0
  66. data/app/views/munificent/admin/fundraisers/index.html.erb +17 -0
  67. data/app/views/munificent/admin/fundraisers/new.html.erb +3 -0
  68. data/app/views/munificent/admin/fundraisers/show.html.erb +41 -0
  69. data/app/views/munificent/admin/games/_form.html.erb +16 -0
  70. data/app/views/munificent/admin/games/csv_upload.html.erb +10 -0
  71. data/app/views/munificent/admin/games/edit.html.erb +3 -0
  72. data/app/views/munificent/admin/games/index.html.erb +15 -0
  73. data/app/views/munificent/admin/games/new.html.erb +3 -0
  74. data/app/views/munificent/admin/games/show.html.erb +25 -0
  75. data/app/views/munificent/admin/otp/_input_form.html.erb +6 -0
  76. data/app/views/munificent/admin/otp/input.html.erb +3 -0
  77. data/app/views/munificent/admin/otp/setup.html.erb +7 -0
  78. data/app/views/munificent/admin/panic_mailer/missing_key.html.erb +6 -0
  79. data/app/views/munificent/admin/panic_mailer/missing_key.text.erb +4 -0
  80. data/app/views/munificent/admin/user_sessions/new.html.erb +9 -0
  81. data/app/views/munificent/admin/users/_form.html.erb +29 -0
  82. data/app/views/munificent/admin/users/edit.html.erb +3 -0
  83. data/app/views/munificent/admin/users/index.html.erb +15 -0
  84. data/app/views/munificent/admin/users/new.html.erb +3 -0
  85. data/app/views/munificent/admin/users/show.html.erb +20 -0
  86. data/config/cucumber.yml +9 -0
  87. data/config/importmap.rb +4 -0
  88. data/config/initializers/inflections.rb +24 -0
  89. data/config/locales/en.yml +4 -0
  90. data/config/routes.rb +40 -0
  91. data/db/migrate/20220524130247_create_munificent_admin_user.rb +50 -0
  92. data/lib/munificent/admin/engine.rb +32 -0
  93. data/lib/munificent/admin/seeds.rb +19 -0
  94. data/lib/munificent/admin/version.rb +5 -0
  95. data/lib/munificent/admin.rb +7 -0
  96. data/lib/tasks/munificent/admin_tasks.rake +4 -0
  97. data/lib/tasks/munificent/cucumber.rake +75 -0
  98. data/lib/tasks/munificent/default.rake +32 -0
  99. metadata +354 -0
@@ -0,0 +1,29 @@
1
+ <%= form_for record do |f| %>
2
+ <fieldset class="record">
3
+ <%= f.field(:text_field, :name) %>
4
+ <%= f.field(:text_field, :email_address) %>
5
+ <%= f.field(:password_field, :password) %>
6
+ <%= f.field(:password_field, :password_confirmation) %>
7
+ </fieldset>
8
+
9
+ <fieldset class="permissions">
10
+ <legend>Permissions</legend>
11
+
12
+ <%= f.check_box(:support) %>
13
+ <%= f.check_box(:data_entry) %>
14
+ <%= f.check_box(:manages_users) %>
15
+ <%= f.check_box(:full_access) %>
16
+ </fieldset>
17
+
18
+ <fieldset class="states">
19
+ <legend>States</legend>
20
+
21
+ <%= f.check_box(:active) %>
22
+ <%= f.check_box(:confirmed) %>
23
+ <%= f.check_box(:approved) %>
24
+ </fieldset>
25
+
26
+ <button class="btn btn-primary">Save</button>
27
+
28
+ <%= link_to "Cancel", record.persisted? ? user_path(record) : users_path %>
29
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <h1>Edit user</h1>
2
+
3
+ <%= render "form", record: @user %>
@@ -0,0 +1,15 @@
1
+ <h1>Users</h1>
2
+
3
+ <%= render "munificent/admin/common/records",
4
+ records: @users,
5
+ fields: %i[
6
+ id
7
+ name
8
+ email_address
9
+ current_login_at
10
+ login_count
11
+ permissions
12
+ states
13
+ ] %>
14
+
15
+ <%= link_to "New user", new_user_path %>
@@ -0,0 +1,3 @@
1
+ <h1>New user</h1>
2
+
3
+ <%= render "form", record: @user %>
@@ -0,0 +1,20 @@
1
+ <h1>
2
+ <%= @user.name %>
3
+ </h1>
4
+
5
+ <% if can?(:manage, @user) %>
6
+ <ul class="actions list-unstyled">
7
+ <li><%= link_to "Edit", edit_user_path(@user) %></li>
8
+ <li>
9
+ <%= button_to "Delete", user_path(@user), method: :delete, data: { confirm: "Are you sure? This cannot be undone." } %>
10
+ </li>
11
+ </ul>
12
+ <% end %>
13
+
14
+ <%= render("munificent/admin/common/record",
15
+ record: @user,
16
+ attributes: %i[
17
+ name
18
+ email_address
19
+ ],
20
+ ) %>
@@ -0,0 +1,9 @@
1
+ <%
2
+ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
+ rerun = rerun.strip.gsub /\s/, ' '
4
+ rerun_opts = rerun.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
5
+ std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags 'not @wip'"
6
+ %>
7
+ default: <%= std_opts %> --publish-quiet features
8
+ wip: --tags @wip:3 --wip features
9
+ rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags 'not @wip'
@@ -0,0 +1,4 @@
1
+ pin "munificent_admin/application", preload: true
2
+ pin "@rails/ujs", to: "https://ga.jspm.io/npm:@rails/ujs@7.0.3/lib/assets/compiled/rails-ujs.js"
3
+ pin "@rails/activestorage", to: "https://ga.jspm.io/npm:@rails/activestorage@7.0.3/app/assets/javascripts/activestorage.esm.js"
4
+ pin "jquery-ujs", to: "https://ga.jspm.io/npm:jquery-ujs@1.2.3/src/rails.js"
@@ -0,0 +1,24 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new inflection rules using the following format. Inflections
4
+ # are locale specific, and you may define rules for as many different
5
+ # locales as you wish. All of these examples are active by default:
6
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
7
+ # inflect.plural /^(ox)$/i, "\\1en"
8
+ # inflect.singular /^(ox)en/i, "\\1"
9
+ # inflect.irregular "person", "people"
10
+ # inflect.uncountable %w( fish sheep )
11
+ # end
12
+
13
+ # These inflection rules are supported but not enabled by default:
14
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
15
+ # inflect.acronym "RESTful"
16
+ # end
17
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
18
+ %w[
19
+ 2SV
20
+ OTP
21
+ ].each do |acronym|
22
+ inflect.acronym(acronym)
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ en:
2
+ common:
3
+ abstract:
4
+ anonymous: "Anonymous"
data/config/routes.rb ADDED
@@ -0,0 +1,40 @@
1
+ module Munificent
2
+ module Admin
3
+ Engine.routes.draw do
4
+ # Non-resource stuff
5
+ resource :dashboard
6
+
7
+ # Resources
8
+ resources :bundles do
9
+ StateMachineHelper.define_routes(self, Bundle)
10
+ end
11
+ resources :bundle_tiers, only: [:destroy]
12
+ resources :charities
13
+ resources :donations
14
+ resources :donator_bundles
15
+ resources :donators
16
+ resources :fundraisers do
17
+ StateMachineHelper.define_routes(self, Fundraiser)
18
+ end
19
+ resources :games do
20
+ member do
21
+ get "csv_upload"
22
+ post "upload_csv"
23
+ end
24
+ end
25
+ resources :users
26
+
27
+ # Authentication
28
+ resource :user_session, only: [:create, :destroy]
29
+
30
+ get "/login" => "user_sessions#new", as: :new_user_session
31
+
32
+ get "/2sv/setup", to: "otp#setup", as: "otp_setup"
33
+ get "/2sv/verify", to: "otp#input", as: "otp_input"
34
+ post "/2sv/verify", to: "otp#verify", as: "otp_verify"
35
+
36
+ # Root
37
+ root to: "dashboard#index"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,50 @@
1
+ class CreateMunificentAdminUser < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :munificent_admin_users do |t|
4
+ t.string :email_address, null: false, index: { unique: true }
5
+ t.string :name
6
+
7
+ # Permissions
8
+ t.boolean :data_entry, default: false, null: false
9
+ t.boolean :full_access, default: false, null: false
10
+ t.boolean :manages_users, default: false, null: false
11
+ t.boolean :support, default: false, null: false
12
+
13
+ # 2FA
14
+ t.datetime :last_otp_at
15
+ t.string :otp_secret
16
+
17
+ # Authlogic::ActsAsAuthentic::Password
18
+ t.string :crypted_password
19
+ t.string :password_salt
20
+
21
+ # Authlogic::ActsAsAuthentic::PersistenceToken
22
+ t.string :persistence_token
23
+ t.index :persistence_token, unique: true
24
+
25
+ # Authlogic::ActsAsAuthentic::SingleAccessToken
26
+ t.string :single_access_token
27
+ t.index :single_access_token, unique: true
28
+
29
+ # Authlogic::ActsAsAuthentic::PerishableToken
30
+ t.string :perishable_token
31
+ t.index :perishable_token, unique: true
32
+
33
+ # See "Magic Columns" in Authlogic::Session::Base
34
+ t.integer :login_count, default: 0, null: false
35
+ t.integer :failed_login_count, default: 0, null: false
36
+ t.datetime :last_request_at
37
+ t.datetime :current_login_at
38
+ t.datetime :last_login_at
39
+ t.string :current_login_ip
40
+ t.string :last_login_ip
41
+
42
+ # See "Magic States" in Authlogic::Session::Base
43
+ t.boolean :active, default: false
44
+ t.boolean :approved, default: false
45
+ t.boolean :confirmed, default: false
46
+
47
+ t.timestamps
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,32 @@
1
+ require "munificent"
2
+
3
+ require "authlogic" # This activates AuthLogic's controller code
4
+ require "cancan" # This activates CanCan's controller code
5
+ require "dartsass-rails"
6
+
7
+ module Munificent
8
+ module Admin
9
+ class Engine < ::Rails::Engine
10
+ isolate_namespace Munificent::Admin
11
+
12
+ initializer "munificent-admin.importmap", before: "importmap" do |app|
13
+ app.config.importmap.paths << Engine.root.join("config/importmap.rb")
14
+ app.config.importmap.cache_sweepers << root.join("app/assets/javascripts")
15
+ end
16
+
17
+ initializer "munificent-admin.dartsass" do |app|
18
+ app.config.dartsass.builds["munificent-admin.scss"] = "munificent-admin.css"
19
+ end
20
+
21
+ initializer "munificent-admin.assets" do |app|
22
+ app.config.assets.precompile += %w[munificent_admin_manifest]
23
+ end
24
+
25
+ config.generators do |g|
26
+ g.test_framework :rspec
27
+ g.fixture_replacement :factory_bot
28
+ g.factory_bot dir: "test/factories"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ module Munificent
2
+ module Admin
3
+ class Seeds
4
+ def self.run
5
+ puts "Creating admin user admin@example.com" # rubocop:disable Rails/Output
6
+ Munificent::Admin::User.create!(
7
+ name: "Test User",
8
+ email_address: "admin@example.com",
9
+ password: "password123",
10
+ password_confirmation: "password123",
11
+ full_access: true,
12
+ # otpauth://totp/Jingle%20Jam%20%28Staging%29:admin%40example.com?secret=EEKMC5VPZQDAD2XT27DRKIWXAJTHDKVC&issuer=Jingle%20Jam%20%28Staging%29
13
+ otp_secret: "EEKMC5VPZQDAD2XT27DRKIWXAJTHDKVC",
14
+ last_otp_at: Time.zone.now,
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Munificent
2
+ module Admin
3
+ VERSION = "1.0.1".freeze
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require "munificent/admin/version"
2
+ require "munificent/admin/engine"
3
+
4
+ module Munificent
5
+ module Admin
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :munificent_admin do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,75 @@
1
+ # IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
2
+ # It is recommended to regenerate this file in the future when you upgrade to a
3
+ # newer version of cucumber-rails. Consider adding your own code to a new file
4
+ # instead of editing this one. Cucumber will automatically load all features/**/*.rb
5
+ # files.
6
+
7
+
8
+ unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
9
+
10
+ vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
11
+ $LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
12
+
13
+ begin
14
+ require 'cucumber/rake/task'
15
+
16
+ namespace :cucumber do
17
+ Cucumber::Rake::Task.new({ok: 'test:prepare'}, 'Run features that should pass') do |t|
18
+ t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
19
+ t.fork = true # You may get faster startup if you set this to false
20
+ t.profile = 'default'
21
+ t.cucumber_opts = "--tags 'not @real_payment_providers'"
22
+ end
23
+
24
+ Cucumber::Rake::Task.new({wip: 'test:prepare'}, 'Run features that are being worked on') do |t|
25
+ t.binary = vendored_cucumber_bin
26
+ t.fork = true # You may get faster startup if you set this to false
27
+ t.profile = 'wip'
28
+ end
29
+
30
+ Cucumber::Rake::Task.new({rerun: 'test:prepare'}, 'Record failing features and run only them if any exist') do |t|
31
+ t.binary = vendored_cucumber_bin
32
+ t.fork = true # You may get faster startup if you set this to false
33
+ t.profile = 'rerun'
34
+ end
35
+
36
+ desc 'Run all features'
37
+ task all: [:ok, :wip]
38
+
39
+ task :statsetup do
40
+ require 'rails/code_statistics'
41
+ ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
42
+ ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features')
43
+ end
44
+
45
+ task :annotations_setup do
46
+ Rails.application.configure do
47
+ if config.respond_to?(:annotations)
48
+ config.annotations.directories << 'features'
49
+ config.annotations.register_extensions('feature') { |tag| /#\s*(#{tag}):?\s*(.*)$/ }
50
+ end
51
+ end
52
+ end
53
+ end
54
+ desc 'Alias for cucumber:ok'
55
+ task cucumber: 'cucumber:ok'
56
+
57
+ task features: :cucumber do
58
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
59
+ end
60
+
61
+ # In case we don't have the generic Rails test:prepare hook, append a no-op task that we can depend upon.
62
+ task 'test:prepare' do
63
+ end
64
+
65
+ task stats: 'cucumber:statsetup'
66
+
67
+ task notes: 'cucumber:annotations_setup'
68
+ rescue LoadError
69
+ desc 'cucumber rake task not available (cucumber not installed)'
70
+ task :cucumber do
71
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,32 @@
1
+ begin
2
+ require "rspec/core/rake_task"
3
+ require "rubocop/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new
7
+ rescue LoadError => exception
8
+ puts "Library not available: #{exception.message}"
9
+ end
10
+
11
+ desc "Build, lint, and test"
12
+ task :build_and_test do
13
+ Rake::Task["lint"].invoke
14
+ Rake::Task["test"].invoke
15
+ Rake::Task["build"].invoke unless ENV["CI"]
16
+ end
17
+
18
+ desc "Lint"
19
+ task lint: :rubocop
20
+
21
+ desc "Test"
22
+ task :test do
23
+ Rake::Task["spec"].invoke
24
+ Rake::Task["cucumber"].invoke
25
+ end
26
+
27
+ desc "Build"
28
+ task :build do
29
+ # no-op
30
+ end
31
+
32
+ task default: :build_and_test