initial project setup with rails, devise, activeadmin, webpacker, docker, stimulusjs, bulma.

This commit is contained in:
ZippyDev 2020-03-21 11:53:34 -06:00
commit dad7d1ad9f
100 changed files with 10471 additions and 0 deletions

1
.browserslistrc Normal file
View File

@ -0,0 +1 @@
defaults

12
.env.docker Normal file
View File

@ -0,0 +1,12 @@
COMPOSE_PROJECT_NAME=app
DATABASE_URL=postgres://user:password@postgres:5432
NODE_ENV=development
POSTGRES_USER=user
POSTGRES_PASSWORD=password
RAILS_ENV=development
REDIS_URL=redis://redis:6379/0
SMTP_HOST=mailcatcher
SMTP_PORT=1025
WEBPACKER_DEV_PUBLIC=webpacker:3035
WEBPACKER_DEV_SERVER_HOST=webpacker
WEBPACKER_DEV_SERVER_ASSET_HOST=webpacker:8080

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
/db/*.sqlite3-*
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
/public/assets
.byebug_history
# Ignore master key for decrypting credentials and more.
/config/master.key
/public/packs
/public/packs-test
/node_modules
/yarn-error.log
yarn-debug.log*
.yarn-integrity

31
.rubocop.yml Normal file
View File

@ -0,0 +1,31 @@
require: rubocop-rails
Rails:
Enabled: true
AllCops:
TargetRubyVersion: 2.6
Exclude:
- '**/*.jbuilder'
- 'node_modules/**/*'
Documentation:
Enabled: false
LineLength:
Max: 120
Style/RaiseArgs:
EnforcedStyle: compact
Metrics/AbcSize:
Enabled: false
Metrics/MethodLength:
Max: 25
Exclude:
- 'spec/**/*.rb'
Metrics/BlockLength:
Exclude:
- 'spec/**/*.rb'

1
.ruby-version Normal file
View File

@ -0,0 +1 @@
2.6.5

34
Dockerfile Normal file
View File

@ -0,0 +1,34 @@
# https://pkgs.alpinelinux.org/packages?name=ruby&branch=v3.11
FROM ruby:2.6.5-alpine3.11
ENV BUNDLER_VERSION=2.0.2
# Minimal requirements to run a Rails app
RUN apk add --no-cache --update build-base \
linux-headers \
postgresql-dev \
nodejs \
tzdata \
git \
less \
chromium \
chromium-chromedriver \
yarn
WORKDIR /app
COPY Gemfile* ./
# Bundler workaround
# https://stackoverflow.com/a/58102398
RUN gem update --system
RUN gem install bundler -v $BUNDLER_VERSION
RUN bundle install --jobs 5 --retry 5
# Copy the application into the container
COPY . .
# Precompile Rails assets
# RUN bundle exec rake assets:clean assets:precompile
# Start puma
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]

53
Gemfile Normal file
View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
source 'https://rubygems.org'
ruby '2.6.5'
gem 'bootsnap', '>= 1.4', require: false
gem 'jbuilder', '~> 2.9'
gem 'lograge', '~> 0.11'
gem 'multi_json', '~> 1.14'
gem 'paranoia', '~> 2.4'
gem 'pg', '~> 1.2'
gem 'puma', '~> 4.2'
gem 'rails', '~> 6.0'
gem 'redis-rails', '~> 5.0'
gem 'responders', '~> 3.0'
gem 'sidekiq', '~> 6.0'
gem 'validates_email_format_of', '~> 1.6'
gem 'webpacker', '~> 4.2'
# auth
gem 'activeadmin', '~> 2.6'
gem 'arctic_admin'
gem 'devise', '~> 4.7'
# styles
gem 'bulma-rails', '~> 0.8.0'
gem 'foundation_emails', '~> 2.2'
group :development, :test do
gem 'factory_bot_rails', '~> 5.1'
gem 'faker', '~> 2.10'
gem 'pry-rails'
gem 'rspec-rails', '~> 3.9'
gem 'rubocop'
gem 'rubocop-rails'
end
group :development do
gem 'listen', '~> 3.2'
gem 'spring' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring-watcher-listen', '~> 2.0'
end
group :test do
gem 'database_cleaner', '~> 1.7'
gem 'json_spec', '~> 1.1'
gem 'mock_redis', '~> 0.17'
gem 'rspec-sidekiq', '~> 3.0'
gem 'shoulda-callback-matchers', '~> 1.1'
gem 'shoulda-matchers', '~> 3.1'
gem 'simplecov', '~> 0.16'
end

383
Gemfile.lock Normal file
View File

@ -0,0 +1,383 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (6.0.2.2)
actionpack (= 6.0.2.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.0.2.2)
actionpack (= 6.0.2.2)
activejob (= 6.0.2.2)
activerecord (= 6.0.2.2)
activestorage (= 6.0.2.2)
activesupport (= 6.0.2.2)
mail (>= 2.7.1)
actionmailer (6.0.2.2)
actionpack (= 6.0.2.2)
actionview (= 6.0.2.2)
activejob (= 6.0.2.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.0.2.2)
actionview (= 6.0.2.2)
activesupport (= 6.0.2.2)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.2.2)
actionpack (= 6.0.2.2)
activerecord (= 6.0.2.2)
activestorage (= 6.0.2.2)
activesupport (= 6.0.2.2)
nokogiri (>= 1.8.5)
actionview (6.0.2.2)
activesupport (= 6.0.2.2)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activeadmin (2.6.1)
arbre (~> 1.2, >= 1.2.1)
formtastic (~> 3.1)
formtastic_i18n (~> 0.4)
inherited_resources (~> 1.7)
jquery-rails (~> 4.2)
kaminari (~> 1.0, >= 1.0.1)
railties (>= 5.2, < 6.1)
ransack (~> 2.1, >= 2.1.1)
sassc-rails (~> 2.1)
sprockets (>= 3.0, < 4.1)
activejob (6.0.2.2)
activesupport (= 6.0.2.2)
globalid (>= 0.3.6)
activemodel (6.0.2.2)
activesupport (= 6.0.2.2)
activerecord (6.0.2.2)
activemodel (= 6.0.2.2)
activesupport (= 6.0.2.2)
activestorage (6.0.2.2)
actionpack (= 6.0.2.2)
activejob (= 6.0.2.2)
activerecord (= 6.0.2.2)
marcel (~> 0.3.1)
activesupport (6.0.2.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2)
arbre (1.2.1)
activesupport (>= 3.0.0)
arctic_admin (3.1.1)
activeadmin (>= 1.1.0, < 3.0)
font-awesome-sass (~> 5.0)
jquery-rails
ast (2.4.0)
bcrypt (3.1.13)
bootsnap (1.4.6)
msgpack (~> 1.0)
builder (3.2.4)
bulma-rails (0.8.0)
sassc (~> 2.0)
coderay (1.1.2)
concurrent-ruby (1.1.6)
connection_pool (2.2.2)
crass (1.0.6)
database_cleaner (1.8.3)
devise (4.7.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
diff-lcs (1.3)
docile (1.3.2)
erubi (1.9.0)
factory_bot (5.1.1)
activesupport (>= 4.2.0)
factory_bot_rails (5.1.1)
factory_bot (~> 5.1.0)
railties (>= 4.2.0)
faker (2.10.2)
i18n (>= 1.6, < 2)
ffi (1.12.2)
font-awesome-sass (5.12.0)
sassc (>= 1.11)
formtastic (3.1.5)
actionpack (>= 3.2.13)
formtastic_i18n (0.6.0)
foundation_emails (2.2.1.0)
globalid (0.4.2)
activesupport (>= 4.2.0)
has_scope (0.7.2)
actionpack (>= 4.1)
activesupport (>= 4.1)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
inherited_resources (1.11.0)
actionpack (>= 5.0, < 6.1)
has_scope (~> 0.6)
railties (>= 5.0, < 6.1)
responders (>= 2, < 4)
jaro_winkler (1.5.4)
jbuilder (2.10.0)
activesupport (>= 5.0.0)
jquery-rails (4.3.5)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json_spec (1.1.5)
multi_json (~> 1.0)
rspec (>= 2.0, < 4.0)
kaminari (1.2.0)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.0)
kaminari-activerecord (= 1.2.0)
kaminari-core (= 1.2.0)
kaminari-actionview (1.2.0)
actionview
kaminari-core (= 1.2.0)
kaminari-activerecord (1.2.0)
activerecord
kaminari-core (= 1.2.0)
kaminari-core (1.2.0)
listen (3.2.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
lograge (0.11.2)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
loofah (2.4.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
method_source (0.9.2)
mimemagic (0.3.4)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.14.0)
mock_redis (0.22.0)
msgpack (1.3.3)
multi_json (1.14.1)
nio4r (2.5.2)
nokogiri (1.10.9)
mini_portile2 (~> 2.4.0)
orm_adapter (0.5.0)
parallel (1.19.1)
paranoia (2.4.2)
activerecord (>= 4.0, < 6.1)
parser (2.7.0.4)
ast (~> 2.4.0)
pg (1.2.3)
polyamorous (2.3.2)
activerecord (>= 5.2.1)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
puma (4.3.3)
nio4r (~> 2.0)
rack (2.2.2)
rack-protection (2.0.8.1)
rack
rack-proxy (0.6.5)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (6.0.2.2)
actioncable (= 6.0.2.2)
actionmailbox (= 6.0.2.2)
actionmailer (= 6.0.2.2)
actionpack (= 6.0.2.2)
actiontext (= 6.0.2.2)
actionview (= 6.0.2.2)
activejob (= 6.0.2.2)
activemodel (= 6.0.2.2)
activerecord (= 6.0.2.2)
activestorage (= 6.0.2.2)
activesupport (= 6.0.2.2)
bundler (>= 1.3.0)
railties (= 6.0.2.2)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
railties (6.0.2.2)
actionpack (= 6.0.2.2)
activesupport (= 6.0.2.2)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
rake (13.0.1)
ransack (2.3.2)
activerecord (>= 5.2.1)
activesupport (>= 5.2.1)
i18n
polyamorous (= 2.3.2)
rb-fsevent (0.10.3)
rb-inotify (0.10.1)
ffi (~> 1.0)
redis (4.1.3)
redis-actionpack (5.2.0)
actionpack (>= 5, < 7)
redis-rack (>= 2.1.0, < 3)
redis-store (>= 1.1.0, < 2)
redis-activesupport (5.2.0)
activesupport (>= 3, < 7)
redis-store (>= 1.3, < 2)
redis-rack (2.1.2)
rack (>= 2.0.8, < 3)
redis-store (>= 1.2, < 2)
redis-rails (5.0.2)
redis-actionpack (>= 5.0, < 6)
redis-activesupport (>= 5.0, < 6)
redis-store (>= 1.2, < 2)
redis-store (1.8.2)
redis (>= 4, < 5)
request_store (1.5.0)
rack (>= 1.4)
responders (3.0.0)
actionpack (>= 5.0)
railties (>= 5.0)
rexml (3.2.4)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.1)
rspec-support (~> 3.9.1)
rspec-expectations (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-rails (3.9.1)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-support (~> 3.9.0)
rspec-sidekiq (3.0.3)
rspec-core (~> 3.0, >= 3.0.0)
sidekiq (>= 2.4.0)
rspec-support (3.9.2)
rubocop (0.80.1)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.7.0.1)
rainbow (>= 2.2.2, < 4.0)
rexml
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
rubocop-rails (2.4.2)
rack (>= 1.1)
rubocop (>= 0.72.0)
ruby-progressbar (1.10.1)
sassc (2.2.1)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
shoulda-callback-matchers (1.1.4)
activesupport (>= 3)
shoulda-matchers (3.1.3)
activesupport (>= 4.0.0)
sidekiq (6.0.5)
connection_pool (>= 2.2.2)
rack (~> 2.0)
rack-protection (>= 2.0.0)
redis (>= 4.1.0)
simplecov (0.18.5)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov-html (0.12.2)
spring (2.1.0)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
sprockets (4.0.0)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
thor (1.0.1)
thread_safe (0.3.6)
tilt (2.0.10)
tzinfo (1.2.6)
thread_safe (~> 0.1)
unicode-display_width (1.6.1)
validates_email_format_of (1.6.3)
i18n
warden (1.2.8)
rack (>= 2.0.6)
webpacker (4.2.2)
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.4)
zeitwerk (2.3.0)
PLATFORMS
ruby
DEPENDENCIES
activeadmin (~> 2.6)
arctic_admin
bootsnap (>= 1.4)
bulma-rails (~> 0.8.0)
database_cleaner (~> 1.7)
devise (~> 4.7)
factory_bot_rails (~> 5.1)
faker (~> 2.10)
foundation_emails (~> 2.2)
jbuilder (~> 2.9)
json_spec (~> 1.1)
listen (~> 3.2)
lograge (~> 0.11)
mock_redis (~> 0.17)
multi_json (~> 1.14)
paranoia (~> 2.4)
pg (~> 1.2)
pry-rails
puma (~> 4.2)
rails (~> 6.0)
redis-rails (~> 5.0)
responders (~> 3.0)
rspec-rails (~> 3.9)
rspec-sidekiq (~> 3.0)
rubocop
rubocop-rails
shoulda-callback-matchers (~> 1.1)
shoulda-matchers (~> 3.1)
sidekiq (~> 6.0)
simplecov (~> 0.16)
spring
spring-watcher-listen (~> 2.0)
validates_email_format_of (~> 1.6)
webpacker (~> 4.2)
RUBY VERSION
ruby 2.6.5p114
BUNDLED WITH
2.0.2

60
README.md Normal file
View File

@ -0,0 +1,60 @@
# Rails 6 template
This repo is a designed to be a Dockerized Rails 6 template:
- [Docker](https://docs.docker.com/mac/started/)
- [Rails 6](https://rubyonrails.org/)
- [StimulusJS](https://github.com/stimulusjs/stimulus)
- [Bulma](https://bulma.io/documentation)
- [ActiveAdmin](https://activeadmin.info/)
- [Devise](https://github.com/heartcombo/devise)
### Dependencies
This service has dependencies on the following services.
1. Ruby 2.6.5
1. Rails 6.x
1. Postgres
1. Redis
1. Webpacker
1. Yarn
1. [Stimulus](https://stimulusjs.org/handbook/installing#using-webpack)
### Docker
Follow the Docker [Getting Started](https://docs.docker.com/mac/started/) guide to get `docker`, `docker-machine` and `docker-compose`. This project contains helper scripts to build, test, & push images to dockerhub.
~~1. Build image: `$ script/build`~~
1. Run the test suite: `$ script/test`
### Docker Compose
Docker compose is used for Jenkins and local development. Use the information below to configure each environment.
##### Local development
To start the application using docker compose locally:
1. Start the services: `$ docker-compose up --build`
1. Access via browser: `$ open http://localhost:3000`
### Environment Variables
| Variable | Description | Default |
| ---------------|:---------------|:-----------------------:|
| `APP_NAME` | App name | TODO
| `APP_TITLE` | App title | TODO
| `DATABASE_URL` | Database URL | postgres://localhost:5432/app_development
| `DB_CONNECT_TIMEOUT` | Db connect timeout | 10
| `DB_MAX_CONNECTIONS` | Db Max Connections | 16
| `DB_MIN_CONNECTIONS` | Db Minimum Connections | 5
| `DB_SOCKET_TIMEOUT` | Db socket timeout | 5
| `DB_WAIT_QUEUE_TIMEOUT` | Db Wait queue timeout | 5
| `LOG_LEVEL` | Log level | warn
| `REDIS_URL` | Redis Url | redis://localhost:6379/0
| `SMTP_HOST` | Smpt address | `localhost`
| `SMTP_PORT` | Smpt port | 1025
| `WEBPACKER_HOST` | Webpacker host | `localhost`
| `WEBPACKER_DEV_SERVER_HOST` | Webpacker dev host | `0.0.0.0`
### TODO
- [ ] Heroku Procfile

8
Rakefile Normal file
View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require_relative 'config/application'
Rails.application.load_tasks

33
app/admin/admin_users.rb Normal file
View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
ActiveAdmin.register User do
permit_params :email, :password, :password_confirmation
index do
selectable_column
id_column
column :email
column :username
column :current_sign_in_at
column :sign_in_count
column :created_at
column :admin
actions
end
filter :email
filter :current_sign_in_at
filter :sign_in_count
filter :created_at
form do |f|
f.inputs do
f.input :email
f.input :password
f.input :password_confirmation
f.input :admin
end
f.actions
end
end

32
app/admin/dashboard.rb Normal file
View File

@ -0,0 +1,32 @@
ActiveAdmin.register_page "Dashboard" do
menu priority: 1, label: proc { I18n.t("active_admin.dashboard") }
content title: proc { I18n.t("active_admin.dashboard") } do
div class: "blank_slate_container", id: "dashboard_default_message" do
span class: "blank_slate" do
span I18n.t("active_admin.dashboard_welcome.welcome")
small I18n.t("active_admin.dashboard_welcome.call_to_action")
end
end
# Here is an example of a simple dashboard with columns and panels.
#
# columns do
# column do
# panel "Recent Posts" do
# ul do
# Post.recent(5).map do |post|
# li link_to(post.title, admin_post_path(post))
# end
# end
# end
# end
# column do
# panel "Info" do
# para "Welcome to ActiveAdmin."
# end
# end
# end
end # content
end

View File

@ -0,0 +1,2 @@
//= link_tree ../images
//= link_directory ../stylesheets .css

0
app/assets/images/.keep Normal file
View File

View File

@ -0,0 +1 @@
//= require arctic_admin/base

View File

@ -0,0 +1,17 @@
// SASS variable overrides must be declared before loading up Active Admin's styles.
//
// To view the variables that Active Admin provides, take a look at
// `app/assets/stylesheets/active_admin/mixins/_variables.scss` in the
// Active Admin source.
//
// For example, to change the sidebar width:
// $sidebar-width: 242px;
// Active Admin's got SASS!
@import "active_admin/mixins";
@import "arctic_admin/base";
// Overriding any non-variable SASS must be done after the fact.
// For example, to change the default status-tag color:
//
// .status_tag { background: #6090DB; }

View File

@ -0,0 +1,15 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*/
@import "bulma"; // https://bulma.io/documentation/

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
module ApplicationCable
class Connection < ActionCable::Connection::Base
end
end

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class ApplicationController < ActionController::Base
protect_from_forgery prepend: true
before_action :configure_permitted_parameters, if: :devise_controller?
def authenticate_admin_user!
authenticate_user!
return if current_user.admin?
redirect_to root_path, flash: { alert: 'You are not allowed to do that.' }
end
protected
def configure_permitted_parameters
added_keys = %i[username email password password_confirmation remember_me]
devise_parameter_sanitizer.permit(:sign_up, keys: added_keys)
devise_parameter_sanitizer.permit(:sign_in, keys: added_keys)
end
end

View File

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class HomeController < ApplicationController
def index; end
def privacy; end
def terms; end
end

View File

@ -0,0 +1,4 @@
# frozen_string_literal: true
module ApplicationHelper
end

View File

@ -0,0 +1,6 @@
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
import { createConsumer } from "@rails/actioncable"
export default createConsumer()

View File

@ -0,0 +1,5 @@
// Load all the channels within this directory and all subdirectories.
// Channel files must be named *_channel.js.
const channels = require.context('.', true, /_channel\.js$/)
channels.keys().forEach(channels)

View File

View File

View File

@ -0,0 +1,23 @@
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
require("@rails/ujs").start()
require("turbolinks").start()
require("channels")
// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)
// https://stimulusjs.org/handbook/installing#using-webpack
import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"
const application = Application.start()
const context = require.context("./controllers", true, /\.js$/)
application.load(definitionsFromContext(context))

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class ApplicationJob < ActiveJob::Base
# Automatically retry jobs that encountered a deadlock
# retry_on ActiveRecord::Deadlocked
# Most jobs are safe to ignore if the underlying records are no longer available
# discard_on ActiveJob::DeserializationError
end

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
class ApplicationMailer < ActionMailer::Base
default from: 'from@example.com'
layout 'mailer'
end

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end

View File

12
app/models/user.rb Normal file
View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
class User < ApplicationRecord
acts_as_paranoid
# Include default devise modules. Others available are:
# :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable,
:confirmable, :lockable, :timeoutable, :trackable
validates :email, presence: true, email_format: { message: 'format is not valid' }
end

View File

@ -0,0 +1,12 @@
<div id="home-index">
<section class="section">
<div class="container">
<h1 class="title">
Welcome to <%= App::Config::APP_TITLE %>!
</h1>
<p class="subtitle">
My first website with <strong>Bulma</strong>!
</p>
</div>
</section>
</div>

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<title><%= App::Config::APP_TITLE %></title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= stylesheet_link_tag 'application', media: 'all' %>
</head>
<body>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
<%= javascript_pack_tag 'application' %>
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
/* Email styles need to be inline */
</style>
</head>
<body>
<%= yield %>
</body>
</html>

View File

@ -0,0 +1 @@
<%= yield %>

72
babel.config.js Normal file
View File

@ -0,0 +1,72 @@
module.exports = function(api) {
var validEnv = ['development', 'test', 'production']
var currentEnv = api.env()
var isDevelopmentEnv = api.env('development')
var isProductionEnv = api.env('production')
var isTestEnv = api.env('test')
if (!validEnv.includes(currentEnv)) {
throw new Error(
'Please specify a valid `NODE_ENV` or ' +
'`BABEL_ENV` environment variables. Valid values are "development", ' +
'"test", and "production". Instead, received: ' +
JSON.stringify(currentEnv) +
'.'
)
}
return {
presets: [
isTestEnv && [
'@babel/preset-env',
{
targets: {
node: 'current'
}
}
],
(isProductionEnv || isDevelopmentEnv) && [
'@babel/preset-env',
{
forceAllTransforms: true,
useBuiltIns: 'entry',
corejs: 3,
modules: false,
exclude: ['transform-typeof-symbol']
}
]
].filter(Boolean),
plugins: [
'babel-plugin-macros',
'@babel/plugin-syntax-dynamic-import',
isTestEnv && 'babel-plugin-dynamic-import-node',
'@babel/plugin-transform-destructuring',
[
'@babel/plugin-proposal-class-properties',
{
loose: true
}
],
[
'@babel/plugin-proposal-object-rest-spread',
{
useBuiltIns: true
}
],
[
'@babel/plugin-transform-runtime',
{
helpers: false,
regenerator: true,
corejs: false
}
],
[
'@babel/plugin-transform-regenerator',
{
async: false
}
]
].filter(Boolean)
}
}

6
bin/rails Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'rails/commands'

6
bin/rake Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require_relative '../config/boot'
require 'rake'
Rake.application.run

38
bin/setup Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'fileutils'
# path to your application root.
APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end
FileUtils.chdir APP_ROOT do
# This script is a way to setup or update your development environment automatically.
# This script is idempotent, so that you can run it at anytime and get an expectable outcome.
# Add necessary setup steps to this file.
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
# Install JavaScript dependencies
# system('bin/yarn')
# puts "\n== Copying sample files =="
# unless File.exist?('config/database.yml')
# FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
# end
puts "\n== Preparing database =="
system! 'bin/rails db:prepare'
puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear'
puts "\n== Restarting application server =="
system! 'bin/rails restart'
end

19
bin/webpack Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development'
ENV['NODE_ENV'] ||= 'development'
require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
Pathname.new(__FILE__).realpath)
require 'bundler/setup'
require 'webpacker'
require 'webpacker/webpack_runner'
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::WebpackRunner.run(ARGV)
end

19
bin/webpack-dev-server Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development'
ENV['NODE_ENV'] ||= 'development'
require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
Pathname.new(__FILE__).realpath)
require 'bundler/setup'
require 'webpacker'
require 'webpacker/dev_server_runner'
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::DevServerRunner.run(ARGV)
end

11
bin/yarn Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
exec 'yarnpkg', *ARGV
rescue Errno::ENOENT
warn 'Yarn executable was not detected in the system.'
warn 'Download Yarn at https://yarnpkg.com/en/docs/install'
exit 1
end

7
config.ru Normal file
View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
# This file is used by Rack-based servers to start the application.
require_relative 'config/environment'
run Rails.application

65
config/application.rb Normal file
View File

@ -0,0 +1,65 @@
# frozen_string_literal: true
require_relative 'boot'
require 'rails'
# Pick the frameworks you want:
require 'active_model/railtie'
require 'active_job/railtie'
require 'active_record/railtie'
# require "active_storage/engine"
require 'action_controller/railtie'
require 'action_mailer/railtie'
# require "action_mailbox/engine"
# require "action_text/engine"
require 'action_view/railtie'
require 'action_cable/engine'
require 'sprockets/railtie'
# require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module App
module Config
APP_NAME = 'TODO: Update in config/application.rb'
APP_TITLE = 'TODO: Update in config/application.rb'
DATABASE_URL = ENV.fetch('DATABASE_URL') { "postgres://localhost:5432/#{APP_NAME}_#{Rails.env}" }
REDIS_URL = ENV.fetch('REDIS_URL') { 'redis://localhost:6379/0' }
SMTP_HOST = ENV.fetch('SMTP_HOST') { 'localhost' }
SMTP_PORT = ENV.fetch('SMTP_PORT') { 1025 }
end
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
# Don't generate system test files.
config.generators.system_tests = nil
# System-wide settings
# mail settings
config.action_mailer.default_url_options = { host: App::Config::SMTP_HOST }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { address: App::Config::SMTP_HOST, port: App::Config::SMTP_PORT }
# https://github.com/redis-store/redis-rails#rails-fragment-cache
config.cache_store = :redis_store, App::Config::REDIS_URL, { expires_in: 90.minutes }
# https://github.com/mperham/sidekiq/wiki/Active-Job#active-job-setup
config.active_job.queue_adapter = :sidekiq
# In order for logs to function properly,
# Docker expects your application or process to log to STDOUT
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.log_tags = %i[subdomain uuid]
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
end

6
config/boot.rb Normal file
View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' # Set up gems listed in the Gemfile.
require 'bootsnap/setup' # Speed up boot time by caching expensive operations.

10
config/cable.yml Normal file
View File

@ -0,0 +1,10 @@
development:
adapter: async
test:
adapter: test
production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: app_production

View File

@ -0,0 +1 @@
QEtBfijNVlIK4sRf6/Nees4Hl1NfmFREPi+KntL99zJU5SCc78H+3+/Kb4F6i9bNhnT7P7ziVq2Xt9Pqqm2k/AKL++jSPVbLE+9v9n9glIBAJUeyFVTyBQiZImwL+2L1oZwFnGRIGYaVYwmVyJv39qN2orX1ZR4dItnHskl9Eq52E9jFfeV4ISvzlDdec+07QC0UH7wA7w7sk5ABixirUwabFa1qH/Xp1eNAnDNafJfdChyGUTwz2zPDu688AecyLmkPOJos5TLow5tTIFVan0Eb2XWMONCOhLZmZm6kWUhNA8rwLGwoBADLw4VQucyOiEK4Kxf2hxSH6Xqco4arjbcF11AtHSA0Tp1YtqjoDZs0jZ5TjsbD7/63peiNNeS0hNcfo3y+4Nt7Mb1Bj3hghoJO6ylGOVnQnDmo--ZFIoUMO/9Bp2VlLr--QK+vtlFhV2a1oQPXDqyTyw==

19
config/database.yml Normal file
View File

@ -0,0 +1,19 @@
default: &default
reaping_frequency: <%= ENV.fetch('DATABASE_REAPING_FREQUENCY') { 10 } %>
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch('DATABASE_CONNECTION_POOL') { 20 } %>
url: <%= ENV.fetch('DATABASE_URL') { 'postgres://localhost:5432' } %>
database: <%= ENV.fetch('DATABASE_NAME') { "#{App::Config::APP_NAME}_#{Rails.env}" } %>
development:
<<: *default
test:
<<: *default
staging:
<<: *default
production:
<<: *default

7
config/environment.rb Normal file
View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
# Load the Rails application.
require_relative 'application'
# Initialize the Rails application.
Rails.application.initialize!

View File

@ -0,0 +1,61 @@
# frozen_string_literal: true
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports.
config.consider_all_requests_local = true
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true
config.action_controller.enable_fragment_cache_logging = true
config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_caching = false
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
# Suppress logger output for asset requests.
config.assets.quiet = true
# Raises error for missing translations.
# config.action_view.raise_on_missing_translations = true
# Use an evented file watcher to asynchronously detect changes in source code,
# routes, locales, etc. This feature depends on the listen gem.
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
end

View File

@ -0,0 +1,111 @@
# frozen_string_literal: true
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Compress CSS using a preprocessor.
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Mount Action Cable outside main process or domain.
# config.action_cable.mount_path = nil
# config.action_cable.url = 'wss://example.com/cable'
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :debug
# Prepend all log lines with the following tags.
config.log_tags = [:request_id]
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "app_production"
config.action_mailer.perform_caching = false
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Use a different logger for distributed setups.
# require 'syslog/logger'
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
if ENV['RAILS_LOG_TO_STDOUT'].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
# Inserts middleware to perform automatic connection switching.
# The `database_selector` hash is used to pass options to the DatabaseSelector
# middleware. The `delay` is used to determine how long to wait after a write
# to send a subsequent read to the primary.
#
# The `database_resolver` class is used by the middleware to determine which
# database is appropriate to use based on the time delay.
#
# The `database_resolver_context` class is used by the middleware to set
# timestamps for the last write to the primary. The resolver uses the context
# class timestamps to determine how long to wait before reading from the
# replica.
#
# By default Rails will store a last write timestamp in the session. The
# DatabaseSelector middleware is designed as such you can define your own
# strategy for connection switching and pass that into the middleware through
# these configuration options.
# config.active_record.database_selector = { delay: 2.seconds }
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
end

View File

@ -0,0 +1,47 @@
# frozen_string_literal: true
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
config.cache_classes = false
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{1.hour.to_i}"
}
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.cache_store = :null_store
# Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
config.action_mailer.perform_caching = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
# Raises error for missing translations.
# config.action_view.raise_on_missing_translations = true
end

View File

@ -0,0 +1,336 @@
# frozen_string_literal: true
ActiveAdmin.setup do |config|
# == Site Title
#
# Set the title that is displayed on the main layout
# for each of the active admin pages.
#
config.site_title = App::Config::APP_TITLE
##
# Arctic Admin
meta_tags_options = { viewport: 'width=device-width, initial-scale=1' }
config.meta_tags = meta_tags_options
config.meta_tags_for_logged_out_pages = meta_tags_options
# Set the link url for the title. For example, to take
# users to your main site. Defaults to no link.
#
# config.site_title_link = "/"
# Set an optional image to be displayed for the header
# instead of a string (overrides :site_title)
#
# Note: Aim for an image that's 21px high so it fits in the header.
#
# config.site_title_image = "logo.png"
# == Default Namespace
#
# Set the default namespace each administration resource
# will be added to.
#
# eg:
# config.default_namespace = :hello_world
#
# This will create resources in the HelloWorld module and
# will namespace routes to /hello_world/*
#
# To set no namespace by default, use:
# config.default_namespace = false
#
# Default:
# config.default_namespace = :admin
#
# You can customize the settings for each namespace by using
# a namespace block. For example, to change the site title
# within a namespace:
#
# config.namespace :admin do |admin|
# admin.site_title = "Custom Admin Title"
# end
#
# This will ONLY change the title for the admin section. Other
# namespaces will continue to use the main "site_title" configuration.
# == User Authentication
#
# Active Admin will automatically call an authentication
# method in a before filter of all controller actions to
# ensure that there is a currently logged in admin user.
#
# This setting changes the method which Active Admin calls
# within the application controller.
config.authentication_method = :authenticate_admin_user!
# == User Authorization
#
# Active Admin will automatically call an authorization
# method in a before filter of all controller actions to
# ensure that there is a user with proper rights. You can use
# CanCanAdapter or make your own. Please refer to documentation.
# config.authorization_adapter = ActiveAdmin::CanCanAdapter
# In case you prefer Pundit over other solutions you can here pass
# the name of default policy class. This policy will be used in every
# case when Pundit is unable to find suitable policy.
# config.pundit_default_policy = "MyDefaultPunditPolicy"
# If you wish to maintain a separate set of Pundit policies for admin
# resources, you may set a namespace here that Pundit will search
# within when looking for a resource's policy.
# config.pundit_policy_namespace = :admin
# You can customize your CanCan Ability class name here.
# config.cancan_ability_class = "Ability"
# You can specify a method to be called on unauthorized access.
# This is necessary in order to prevent a redirect loop which happens
# because, by default, user gets redirected to Dashboard. If user
# doesn't have access to Dashboard, he'll end up in a redirect loop.
# Method provided here should be defined in application_controller.rb.
# config.on_unauthorized_access = :access_denied
# == Current User
#
# Active Admin will associate actions with the current
# user performing them.
#
# This setting changes the method which Active Admin calls
# (within the application controller) to return the currently logged in user.
config.current_user_method = :current_user
# == Logging Out
#
# Active Admin displays a logout link on each screen. These
# settings configure the location and method used for the link.
#
# This setting changes the path where the link points to. If it's
# a string, the strings is used as the path. If it's a Symbol, we
# will call the method to return the path.
#
# Default:
config.logout_link_path = :destroy_user_session_path
# This setting changes the http method used when rendering the
# link. For example :get, :delete, :put, etc..
#
# Default:
# config.logout_link_method = :get
# == Root
#
# Set the action to call for the root path. You can set different
# roots for each namespace.
#
# Default:
# config.root_to = 'dashboard#index'
# == Admin Comments
#
# This allows your users to comment on any resource registered with Active Admin.
#
# You can completely disable comments:
# config.comments = false
#
# You can change the name under which comments are registered:
# config.comments_registration_name = 'AdminComment'
#
# You can change the order for the comments and you can change the column
# to be used for ordering:
# config.comments_order = 'created_at ASC'
#
# You can disable the menu item for the comments index page:
# config.comments_menu = false
#
# You can customize the comment menu:
# config.comments_menu = { parent: 'Admin', priority: 1 }
# == Batch Actions
#
# Enable and disable Batch Actions
#
config.batch_actions = true
# == Controller Filters
#
# You can add before, after and around filters to all of your
# Active Admin resources and pages from here.
#
# config.before_action :do_something_awesome
# == Attribute Filters
#
# You can exclude possibly sensitive model attributes from being displayed,
# added to forms, or exported by default by ActiveAdmin
#
config.filter_attributes = %i[encrypted_password password password_confirmation]
# == Localize Date/Time Format
#
# Set the localize format to display dates and times.
# To understand how to localize your app with I18n, read more at
# https://guides.rubyonrails.org/i18n.html
#
# You can run `bin/rails runner 'puts I18n.t("date.formats")'` to see the
# available formats in your application.
#
config.localize_format = :long
# == Setting a Favicon
#
# config.favicon = 'favicon.ico'
# == Meta Tags
#
# Add additional meta tags to the head element of active admin pages.
#
# Add tags to all pages logged in users see:
# config.meta_tags = { author: 'My Company' }
# By default, sign up/sign in/recover password pages are excluded
# from showing up in search engine results by adding a robots meta
# tag. You can reset the hash of meta tags included in logged out
# pages:
# config.meta_tags_for_logged_out_pages = {}
# == Removing Breadcrumbs
#
# Breadcrumbs are enabled by default. You can customize them for individual
# resources or you can disable them globally from here.
#
# config.breadcrumb = false
# == Create Another Checkbox
#
# Create another checkbox is disabled by default. You can customize it for individual
# resources or you can enable them globally from here.
#
# config.create_another = true
# == Register Stylesheets & Javascripts
#
# We recommend using the built in Active Admin layout and loading
# up your own stylesheets / javascripts to customize the look
# and feel.
#
# To load a stylesheet:
# config.register_stylesheet 'my_stylesheet.css'
#
# You can provide an options hash for more control, which is passed along to stylesheet_link_tag():
# config.register_stylesheet 'my_print_stylesheet.css', media: :print
#
# To load a javascript file:
# config.register_javascript 'my_javascript.js'
# == CSV options
#
# Set the CSV builder separator
# config.csv_options = { col_sep: ';' }
#
# Force the use of quotes
# config.csv_options = { force_quotes: true }
# == Menu System
#
# You can add a navigation menu to be used in your application, or configure a provided menu
#
# To change the default utility navigation to show a link to your website & a logout btn
#
# config.namespace :admin do |admin|
# admin.build_menu :utility_navigation do |menu|
# menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank }
# admin.add_logout_button_to_menu menu
# end
# end
#
# If you wanted to add a static menu item to the default menu provided:
#
# config.namespace :admin do |admin|
# admin.build_menu :default do |menu|
# menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank }
# end
# end
# == Download Links
#
# You can disable download links on resource listing pages,
# or customize the formats shown per namespace/globally
#
# To disable/customize for the :admin namespace:
#
# config.namespace :admin do |admin|
#
# # Disable the links entirely
# admin.download_links = false
#
# # Only show XML & PDF options
# admin.download_links = [:xml, :pdf]
#
# # Enable/disable the links based on block
# # (for example, with cancan)
# admin.download_links = proc { can?(:view_download_links) }
#
# end
# == Pagination
#
# Pagination is enabled by default for all resources.
# You can control the default per page count for all resources here.
#
# config.default_per_page = 30
#
# You can control the max per page count too.
#
# config.max_per_page = 10_000
# == Filters
#
# By default the index screen includes a "Filters" sidebar on the right
# hand side with a filter for each attribute of the registered model.
# You can enable or disable them for all resources here.
#
# config.filters = true
#
# By default the filters include associations in a select, which means
# that every record will be loaded for each association (up
# to the value of config.maximum_association_filter_arity).
# You can enabled or disable the inclusion
# of those filters by default here.
#
# config.include_default_association_filters = true
# config.maximum_association_filter_arity = 256 # default value of :unlimited will change to 256 in a future version
# config.filter_columns_for_large_association, [
# :display_name,
# :full_name,
# :name,
# :username,
# :login,
# :title,
# :email,
# ]
# config.filter_method_for_large_association, '_starts_with'
# == Head
#
# You can add your own content to the site head like analytics. Make sure
# you only pass content you trust.
#
# config.head = ''.html_safe
# == Footer
#
# By default, the footer shows the current Active Admin version. You can
# override the content of the footer here.
#
# config.footer = 'my custom footer text'
# == Sorting
#
# By default ActiveAdmin::OrderClause is used for sorting logic
# You can inherit it with own class and inject it for all resources
#
# config.order_clause = MyOrderClause
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# ActiveSupport::Reloader.to_prepare do
# ApplicationController.renderer.defaults.merge!(
# http_host: 'example.org',
# https: false
# )
# end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path
# Add Yarn node_modules folder to the asset load path.
Rails.application.config.assets.paths << Rails.root.join('node_modules')
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
# Rails.application.config.assets.precompile += %w( admin.js admin.css )

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Define an application-wide content security policy
# For further information see the following documentation
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
# Rails.application.config.content_security_policy do |policy|
# policy.default_src :self, :https
# policy.font_src :self, :https, :data
# policy.img_src :self, :https, :data
# policy.object_src :none
# policy.script_src :self, :https
# policy.style_src :self, :https
# # If you are using webpack-dev-server then specify webpack-dev-server host
# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
# # Specify URI for violation reports
# # policy.report_uri "/csp-violation-report-endpoint"
# end
# If you are using UJS then enable automatic nonce generation
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
# Set the nonce only to specific directives
# Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
# Report CSP violations to a specified URI
# For further information see the following documentation:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
# Rails.application.config.content_security_policy_report_only = true

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Specify a serializer for the signed and encrypted cookie jars.
# Valid options are :json, :marshal, and :hybrid.
Rails.application.config.action_dispatch.cookies_serializer = :json

View File

@ -0,0 +1,299 @@
# frozen_string_literal: true
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
# Devise will use the `secret_key_base` as its `secret_key`
# by default. You can change it below and use your own secret key.
# config.secret_key = '78548e84d8ad604ce476c7b76b95163932664c66c9b71303dd93148e1e6fb892cfb9cabd1dbbb77e9f4dd9baad32f06659bc936e0006dfd0f6d37320d4a2271f'
# ==> Controller configuration
# Configure the parent class to the devise controllers.
# config.parent_controller = 'DeviseController'
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
# Configure the parent class responsible to send e-mails.
# config.parent_mailer = 'ActionMailer::Base'
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default) and
# :mongoid (bson_ext recommended) by default. Other ORMs may be
# available as additional gems.
require 'devise/orm/active_record'
# ==> Configuration for any authentication mechanism
# Configure which keys are used when authenticating a user. The default is
# just :email. You can configure it to use [:username, :subdomain], so for
# authenticating a user, both parameters are required. Remember that those
# parameters are used only when authenticating and not when retrieving from
# session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
# config.authentication_keys = [:email]
# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
# find_for_authentication method and considered in your model lookup. For instance,
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
# The same considerations mentioned for authentication_keys also apply to request_keys.
# config.request_keys = []
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
config.case_insensitive_keys = %i[email username]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
config.strip_whitespace_keys = %i[email username]
# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
# given strategies, for example, `config.params_authenticatable = [:database]` will
# enable it only for database (email + password) authentication.
# config.params_authenticatable = true
# Tell if authentication through HTTP Auth is enabled. False by default.
# It can be set to an array that will enable http authentication only for the
# given strategies, for example, `config.http_authenticatable = [:database]` will
# enable it only for database authentication. The supported strategies are:
# :database = Support basic authentication with authentication key + password
# config.http_authenticatable = false
# If 401 status code should be returned for AJAX requests. True by default.
# config.http_authenticatable_on_xhr = true
# The realm used in Http Basic Authentication. 'Application' by default.
# config.http_authentication_realm = 'Application'
# It will change confirmation, password recovery and other workflows
# to behave the same regardless if the e-mail provided was right or wrong.
# Does not affect registerable.
# config.paranoid = true
# By default Devise will store the user in session. You can skip storage for
# particular strategies by setting this option.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing skip: :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth]
# By default, Devise cleans up the CSRF token on authentication to
# avoid CSRF token fixation attacks. This means that, when using AJAX
# requests for sign in and sign up, you need to get a new CSRF token
# from the server. You can disable this option at your own risk.
# config.clean_up_csrf_token_on_authentication = true
# When false, Devise will not attempt to reload routes on eager load.
# This can reduce the time taken to boot the app but if your application
# requires the Devise mappings to be loaded during boot time the application
# won't boot properly.
# config.reload_routes = true
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 11. If
# using other algorithms, it sets how many times you want the password to be hashed.
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments. Note that, for bcrypt (the default
# algorithm), the cost increases exponentially with the number of stretches (e.g.
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
config.stretches = Rails.env.test? ? 1 : 11
# Set up a pepper to generate the hashed password.
# config.pepper = '08a48f8f92c7214da166ef57278e817c13fe39fbca7344ae027571d5a58c8e23d68d074ba05415b681df88f3654f5715c8ec4bd1b168dad77b416ac9d4028a82'
# Send a notification to the original email when the user's email is changed.
# config.send_email_changed_notification = false
# Send a notification email when the user's password is changed.
# config.send_password_change_notification = false
# ==> Configuration for :confirmable
# A period that the user is allowed to access the website even without
# confirming their account. For instance, if set to 2.days, the user will be
# able to access the website for two days without confirming their account,
# access will be blocked just in the third day.
# You can also set it to nil, which will allow the user to access the website
# without confirming their account.
# Default is 0.days, meaning the user cannot access the website without
# confirming their account.
# config.allow_unconfirmed_access_for = 2.days
# A period that the user is allowed to confirm their account before their
# token becomes invalid. For example, if set to 3.days, the user can confirm
# their account within 3 days after the mail was sent, but on the fourth day
# their account can't be confirmed with the token any more.
# Default is nil, meaning there is no restriction on how long a user can take
# before confirming their account.
# config.confirm_within = 3.days
# If true, requires any email changes to be confirmed (exactly the same way as
# initial account confirmation) to be applied. Requires additional unconfirmed_email
# db field (see migrations). Until confirmed, new email is stored in
# unconfirmed_email column, and copied to email column on successful confirmation.
config.reconfirmable = true
# Defines which key will be used when confirming an account
# config.confirmation_keys = [:email]
# ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again.
# config.remember_for = 2.weeks
# Invalidates all the remember me tokens when the user signs out.
config.expire_all_remember_me_on_sign_out = true
# If true, extends the user's remember period when remembered via cookie.
# config.extend_remember_period = false
# Options to be passed to the created cookie. For instance, you can set
# secure: true in order to force SSL only cookies.
# config.rememberable_options = {}
# ==> Configuration for :validatable
# Range for password length.
config.password_length = 6..128
# Email regex used to validate email formats. It simply asserts that
# one (and only one) @ exists in the given string. This is mainly
# to give user feedback and not to assert the e-mail validity.
config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. Default is 30 minutes.
# config.timeout_in = 30.minutes
# ==> Configuration for :lockable
# Defines which strategy will be used to lock an account.
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
# :none = No lock strategy. You should handle locking by yourself.
# config.lock_strategy = :failed_attempts
# Defines which key will be used when locking and unlocking an account
# config.unlock_keys = [:email]
# Defines which strategy will be used to unlock an account.
# :email = Sends an unlock link to the user email
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
# :both = Enables both strategies
# :none = No unlock strategy. You should handle unlocking by yourself.
# config.unlock_strategy = :both
# Number of authentication tries before locking an account if lock_strategy
# is failed attempts.
# config.maximum_attempts = 20
# Time interval to unlock the account if :time is enabled as unlock_strategy.
# config.unlock_in = 1.hour
# Warn on the last attempt before the account is locked.
# config.last_attempt_warning = true
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
# config.reset_password_keys = [:email]
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
config.reset_password_within = 6.hours
# When set to false, does not sign a user in automatically after their password is
# reset. Defaults to true, so a user is signed in automatically after a reset.
# config.sign_in_after_reset_password = true
# ==> Configuration for :encryptable
# Allow you to use another hashing or encryption algorithm besides bcrypt (default).
# You can use :sha1, :sha512 or algorithms from others authentication tools as
# :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
# for default behavior) and :restful_authentication_sha1 (then you should set
# stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
#
# Require the `devise-encryptable` gem when using anything other than bcrypt
# config.encryptor = :sha512
# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = false
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
# config.default_scope = :user
# Set this configuration to false if you want /users/sign_out to sign out
# only the current scope. By default, Devise signs out all scopes.
# config.sign_out_all_scopes = true
# ==> Navigation configuration
# Lists the formats that should be treated as navigational. Formats like
# :html, should redirect to the sign in page when the user does not have
# access, but formats like :xml or :json, should return 401.
#
# If you have any extra navigational formats, like :iphone or :mobile, you
# should add them to the navigational formats lists.
#
# The "*/*" below is required to match Internet Explorer requests.
# config.navigational_formats = ['*/*', :html]
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or
# change the failure app, you can configure them inside the config.warden block.
#
# config.warden do |manager|
# manager.intercept_401 = false
# manager.default_strategies(scope: :user).unshift :some_external_strategy
# end
# ==> Mountable engine configurations
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
# is mountable, there are some extra configurations to be taken into account.
# The following options are available, assuming the engine is mounted as:
#
# mount MyEngine, at: '/my_engine'
#
# The router that invoked `devise_for`, in the example above, would be:
# config.router_name = :my_engine
#
# When using OmniAuth, Devise cannot automatically set OmniAuth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = '/my_engine/users/auth'
# ==> Turbolinks configuration
# If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly:
#
# ActiveSupport.on_load(:devise_failure_app) do
# include Turbolinks::Controller
# end
# ==> Configuration for :registerable
# When set to false, does not sign a user in automatically after their password is
# changed. Defaults to true, so a user is signed in automatically after changing a password.
# config.sign_in_after_change_password = true
end

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password]

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
# end

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json]
end
# To enable root element in JSON for ActiveRecord objects.
# ActiveSupport.on_load(:active_record) do
# self.include_root_in_json = true
# end

View File

@ -0,0 +1,65 @@
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en:
devise:
confirmations:
confirmed: "Your email address has been successfully confirmed."
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
failure:
already_authenticated: "You are already signed in."
inactive: "Your account is not activated yet."
invalid: "Invalid %{authentication_keys} or password."
locked: "Your account is locked."
last_attempt: "You have one more attempt before your account is locked."
not_found_in_database: "Invalid %{authentication_keys} or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
unconfirmed: "You have to confirm your email address before continuing."
mailer:
confirmation_instructions:
subject: "Confirmation instructions"
reset_password_instructions:
subject: "Reset password instructions"
unlock_instructions:
subject: "Unlock instructions"
email_changed:
subject: "Email Changed"
password_change:
subject: "Password Changed"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
passwords:
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
updated: "Your password has been changed successfully. You are now signed in."
updated_not_active: "Your password has been changed successfully."
registrations:
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
signed_up: "Welcome! You have signed up successfully."
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
updated: "Your account has been updated successfully."
updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again"
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
already_signed_out: "Signed out successfully."
unlocks:
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
errors:
messages:
already_confirmed: "was already confirmed, please try signing in"
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
expired: "has expired, please request a new one"
not_found: "not found"
not_locked: "was not locked"
not_saved:
one: "1 error prohibited this %{resource} from being saved:"
other: "%{count} errors prohibited this %{resource} from being saved:"

33
config/locales/en.yml Normal file
View File

@ -0,0 +1,33 @@
# Files in the config/locales directory are used for internationalization
# and are automatically loaded by Rails. If you want to use locales other
# than English, add the necessary files in this directory.
#
# To use the locales, use `I18n.t`:
#
# I18n.t 'hello'
#
# In views, this is aliased to just `t`:
#
# <%= t('hello') %>
#
# To use a different locale, set it with `I18n.locale`:
#
# I18n.locale = :es
#
# This would use the information in config/locales/es.yml.
#
# The following keys must be escaped otherwise they will not be retrieved by
# the default I18n backend:
#
# true, false, on, off, yes, no
#
# Instead, surround them with single quotes.
#
# en:
# 'true': 'foo'
#
# To learn more, please read the Rails Internationalization guide
# available at https://guides.rubyonrails.org/i18n.html.
en:
hello: "Hello world"

40
config/puma.rb Normal file
View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers: a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
max_threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }
min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
threads min_threads_count, max_threads_count
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch('PORT') { 3000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch('RAILS_ENV') { 'development' }
# Specifies the `pidfile` that Puma will use.
pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
#
# preload_app!
# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

15
config/routes.rb Normal file
View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
require 'sidekiq/web'
Rails.application.routes.draw do
ActiveAdmin.routes(self)
devise_for :users
authenticate :user, ->(u) { u.admin? } do
mount Sidekiq::Web => '/admin/sidekiq'
end
root 'home#index'
get '/privacy', to: 'home#privacy'
get '/terms', to: 'home#terms'
end

8
config/sidekiq.yml Normal file
View File

@ -0,0 +1,8 @@
---
:concurrency: <%= ENV.fetch('SIDEKIQ_CONCURRENCY') { 5 } %> # @see http://manuelvanrijn.nl/sidekiq-heroku-redis-calc/
:url: <%= ENV.fetch('REDIS_URL') { 'redis://localhost:6379/0' } %>
:queues:
- realtime
- high
- default
- low

8
config/spring.rb Normal file
View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
Spring.watch(
'.ruby-version',
'.rbenv-vars',
'tmp/restart.txt',
'tmp/caching-dev.txt'
)

View File

@ -0,0 +1,5 @@
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()

View File

@ -0,0 +1,3 @@
const { environment } = require('@rails/webpacker')
module.exports = environment

View File

@ -0,0 +1,5 @@
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()

5
config/webpack/test.js Normal file
View File

@ -0,0 +1,5 @@
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()

99
config/webpacker.yml Normal file
View File

@ -0,0 +1,99 @@
# Note: You must restart bin/webpack-dev-server for changes to take effect
default: &default
source_path: app/javascript
source_entry_path: packs
public_root_path: public
public_output_path: packs
cache_path: tmp/cache/webpacker
check_yarn_integrity: false
webpack_compile_output: true
# Additional paths webpack should lookup modules
# ['app/assets', 'engine/foo/app/assets']
resolved_paths: []
# Reload manifest.json on all requests so we reload latest compiled packs
cache_manifest: false
# Extract and emit a css file
extract_css: true
static_assets_extensions:
- .jpg
- .jpeg
- .png
- .gif
- .tiff
- .ico
- .svg
- .eot
- .otf
- .ttf
- .woff
- .woff2
extensions:
- .mjs
- .js
- .sass
- .scss
- .css
- .module.sass
- .module.scss
- .module.css
- .png
- .svg
- .gif
- .jpeg
- .jpg
development:
<<: *default
compile: true
# Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
# check_yarn_integrity: true
check_yarn_integrity: false
# Reference: https://webpack.js.org/configuration/dev-server/
dev_server:
https: false
# Non-docker: localhost
host: webpacker
port: 3035
# Non-docker: localhost:3035
public: webpacker:3035
hmr: false
# Inline should be set to true if using HMR
inline: true
overlay: true
compress: true
disable_host_check: true
use_local_ip: false
quiet: false
pretty: false
headers:
'Access-Control-Allow-Origin': '*'
watch_options:
ignored: '**/node_modules/**'
test:
<<: *default
compile: true
# Compile test packs to a separate directory
public_output_path: packs-test
production:
<<: *default
# Production depends on precompilation of packs prior to booting for performance.
compile: false
# Extract and emit a css file
extract_css: true
# Cache manifest.json for performance
cache_manifest: true

View File

@ -0,0 +1,51 @@
# frozen_string_literal: true
class DeviseCreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
## Database authenticatable
t.string :username, null: false, default: ''
t.string :email, null: false, default: ''
t.string :encrypted_password, null: false, default: ''
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.inet :current_sign_in_ip
t.inet :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
t.timestamps null: false
t.datetime :deleted_at, default: nil
# admin settings
t.boolean :admin, default: false
end
add_index :users, :username, unique: true
add_index :users, :email, unique: true
add_index :users, %i[email username]
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token, unique: true
add_index :users, :unlock_token, unique: true
add_index :users, :deleted_at
end
end

View File

@ -0,0 +1,16 @@
class CreateActiveAdminComments < ActiveRecord::Migration[6.0]
def self.up
create_table :active_admin_comments do |t|
t.string :namespace
t.text :body
t.references :resource, polymorphic: true
t.references :author, polymorphic: true
t.timestamps
end
add_index :active_admin_comments, [:namespace]
end
def self.down
drop_table :active_admin_comments
end
end

64
db/schema.rb Normal file
View File

@ -0,0 +1,64 @@
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `rails
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_03_19_234126) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "active_admin_comments", force: :cascade do |t|
t.string "namespace"
t.text "body"
t.string "resource_type"
t.bigint "resource_id"
t.string "author_type"
t.bigint "author_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id"
t.index ["namespace"], name: "index_active_admin_comments_on_namespace"
t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id"
end
create_table "users", force: :cascade do |t|
t.string "username", default: "", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.integer "failed_attempts", default: 0, null: false
t.string "unlock_token"
t.datetime "locked_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "deleted_at"
t.boolean "admin", default: false
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["deleted_at"], name: "index_users_on_deleted_at"
t.index ["email", "username"], name: "index_users_on_email_and_username"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
t.index ["username"], name: "index_users_on_username", unique: true
end
end

12
db/seeds.rb Normal file
View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
#
# Examples:
#
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
# Character.create(name: 'Luke', movie: movies.first)
return unless Rails.env.development?
User.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password', admin: true)

74
docker-compose.yml Normal file
View File

@ -0,0 +1,74 @@
version: "2.1"
services:
mailcatcher:
image: jeanberu/mailcatcher:0.6.5
ports:
- "1080:1080"
- "1025:1025"
postgres:
image: "postgres:11.5-alpine"
environment:
POSTGRES_USER: "user"
POSTGRES_PASSWORD: "password"
ports:
- "5432:5432"
# volumes:
# - "postgres:/var/lib/postgresql/data"
redis:
image: redis:5.0-alpine
command: redis-server
expose:
- "6379"
# volumes:
# - "redis:/var/lib/redis/data"
healthcheck:
test: "redis-cli ping"
interval: 5s
timeout: 5s
retries: 10
sidekiq:
depends_on:
- redis
- postgres
build: .
command: bundle exec sidekiq -C config/sidekiq.yml
volumes:
- .:/app
env_file:
- '.env.docker'
webpacker:
build: .
env_file:
- '.env.docker'
command: ./bin/webpack-dev-server
volumes:
- .:/app
ports:
- '3035:3035'
- '8080:8080'
app:
build: .
depends_on:
- postgres
- redis
- mailcatcher
- webpacker
ports:
- "3000:3000"
volumes:
- ".:/app"
shm_size: 512M # https://testingrepository.com/fix-no-session-chromedriver-error/
stdin_open: true
tty: true
env_file:
- '.env.docker'
# volumes:
# redis:
# postgres:

0
lib/assets/.keep Normal file
View File

0
lib/tasks/.keep Normal file
View File

0
log/.keep Normal file
View File

15
package.json Normal file
View File

@ -0,0 +1,15 @@
{
"name": "app",
"private": true,
"dependencies": {
"@rails/actioncable": "^6.0.0",
"@rails/ujs": "^6.0.0",
"@rails/webpacker": "4.2.2",
"stimulus": "^1.1.1",
"turbolinks": "^5.2.0"
},
"version": "0.1.0",
"devDependencies": {
"webpack-dev-server": "^3.10.3"
}
}

12
postcss.config.js Normal file
View File

@ -0,0 +1,12 @@
module.exports = {
plugins: [
require('postcss-import'),
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
})
]
}

67
public/404.html Normal file
View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
.rails-default-error-page {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
.rails-default-error-page div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
.rails-default-error-page div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
.rails-default-error-page h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
.rails-default-error-page div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body class="rails-default-error-page">
<!-- This file lives in public/404.html -->
<div class="dialog">
<div>
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

67
public/422.html Normal file
View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<title>The change you wanted was rejected (422)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
.rails-default-error-page {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
.rails-default-error-page div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
.rails-default-error-page div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
.rails-default-error-page h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
.rails-default-error-page div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body class="rails-default-error-page">
<!-- This file lives in public/422.html -->
<div class="dialog">
<div>
<h1>The change you wanted was rejected.</h1>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

66
public/500.html Normal file
View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>We're sorry, but something went wrong (500)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
.rails-default-error-page {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
.rails-default-error-page div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
.rails-default-error-page div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
.rails-default-error-page h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
.rails-default-error-page div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body class="rails-default-error-page">
<!-- This file lives in public/500.html -->
<div class="dialog">
<div>
<h1>We're sorry, but something went wrong.</h1>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

View File

View File

0
public/favicon.ico Normal file
View File

1
public/robots.txt Normal file
View File

@ -0,0 +1 @@
# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file

40
script/test Normal file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
# script/test: Run test suite for application. Optionally pass in a path to an
# individual test file to run a single test.
set -e
# cd to project root
cd "$(dirname "$0")/.."
export PROJECT_NAME="app" RAILS_ENV="test" RACK_ENV="test"
printf "\n===> Setting $RAILS_ENV environment ...\n"
docker-compose run -e RAILS_ENV=$RAILS_ENV app rails db:environment:set
# setup test database
printf "\n===> Migrating $RAILS_ENV database ...\n"
printf "\n*************************************************************"
printf "\n********************** MIGRATION NOTE ***********************"
printf "\n** Script assumes database is already created **"
printf "\n** **"
printf "\n** Run the following command if error encountered **"
printf "\n** **"
printf "\n** docker-compose run -e RAILS_ENV=$RAILS_ENV app rake db:create **"
printf "\n** **"
printf "\n*************************************************************"
printf "\n*************************************************************"
docker-compose run -e RAILS_ENV=$RAILS_ENV app rake db:drop db:create db:migrate
# run tests
printf "\n===> Running tests ...\n"
if [ -n "$1" ]; then
# pass arguments to test call. This is useful for calling a single test.
docker-compose --project-name=$PROJECT_NAME run -e RAILS_ENV=$RAILS_ENV --rm app rspec "$1"
else
docker-compose --project-name=$PROJECT_NAME run -e RAILS_ENV=$RAILS_ENV --rm app rspec
fi
docker-compose down

8
spec/factories/users.rb Normal file
View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :user do
email { Faker::Internet.email }
password { Faker::Internet.password(6, 50) }
end
end

56
spec/models/user_spec.rb Normal file
View File

@ -0,0 +1,56 @@
# frozen_string_literal: true
require 'rails_helper'
describe User, type: :model do
subject { FactoryBot.build_stubbed(:user) }
context 'fields' do
## Database authenticatable
it { is_expected.to have_db_column(:email).of_type(:string) }
it { is_expected.to have_db_column(:username).of_type(:string) }
it { is_expected.to have_db_column(:encrypted_password).of_type(:string) }
## Recoverable
it { is_expected.to have_db_column(:reset_password_token).of_type(:string) }
it { is_expected.to have_db_column(:reset_password_sent_at).of_type(:datetime) }
## Trackable
it { is_expected.to have_db_column(:sign_in_count).of_type(:integer).with_options(default: 0) }
it { is_expected.to have_db_column(:current_sign_in_at).of_type(:datetime) }
it { is_expected.to have_db_column(:last_sign_in_at).of_type(:datetime) }
it { is_expected.to have_db_column(:current_sign_in_ip).of_type(:inet) }
it { is_expected.to have_db_column(:last_sign_in_ip).of_type(:inet) }
## Confirmable
it { is_expected.to have_db_column(:confirmation_token).of_type(:string) }
it { is_expected.to have_db_column(:confirmed_at).of_type(:datetime) }
it { is_expected.to have_db_column(:confirmation_sent_at).of_type(:datetime) }
it { is_expected.to have_db_column(:unconfirmed_email).of_type(:string) }
## Lockable
it { is_expected.to have_db_column(:failed_attempts).of_type(:integer).with_options(default: 0) }
it { is_expected.to have_db_column(:unlock_token).of_type(:string) }
it { is_expected.to have_db_column(:locked_at).of_type(:datetime) }
## Dates
it { is_expected.to have_db_column(:deleted_at).of_type(:datetime) }
it { is_expected.to have_db_column(:created_at).of_type(:datetime) }
it { is_expected.to have_db_column(:updated_at).of_type(:datetime) }
# admin/employee
it { is_expected.to have_db_column(:admin).of_type(:boolean).with_options(default: false) }
it { is_expected.to have_db_index(:confirmation_token).unique }
it { is_expected.to have_db_index(:email).unique }
it { is_expected.to have_db_index(:reset_password_token).unique }
it { is_expected.to have_db_index(:unlock_token).unique }
it { is_expected.to have_db_index(:username).unique }
it { is_expected.to be_paranoid }
end
describe 'associations' do
# it { is_expected.to have_many(:user_notification_subscriptions) }
end
describe 'callbacks' do
end
describe 'validations' do
it { should validate_email_format_of(:email).with_message('format is not valid') }
# it { is_expected.to callback(:activate_beta_code).after(:create) }
end
end

0
tmp/.keep Normal file
View File

0
vendor/.keep vendored Normal file
View File

7504
yarn.lock Normal file

File diff suppressed because it is too large Load Diff