rockstart 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +100 -0
- data/Rakefile +19 -0
- data/lib/generators/rockstart/USAGE +13 -0
- data/lib/generators/rockstart/devise/USAGE +9 -0
- data/lib/generators/rockstart/devise/devise_generator.rb +258 -0
- data/lib/generators/rockstart/devise/templates/controllers/passwords_controller.rb +56 -0
- data/lib/generators/rockstart/devise/templates/controllers/registrations_controller.rb +88 -0
- data/lib/generators/rockstart/devise/templates/controllers/sessions_controller.rb +32 -0
- data/lib/generators/rockstart/devise/templates/create_user_migration.rb.tt +11 -0
- data/lib/generators/rockstart/devise/templates/models/user.rb +42 -0
- data/lib/generators/rockstart/devise/templates/spec/factories/users.rb +17 -0
- data/lib/generators/rockstart/devise/templates/spec/models/user_spec.rb +64 -0
- data/lib/generators/rockstart/devise/templates/spec/requests/users/passwords_spec.rb +202 -0
- data/lib/generators/rockstart/devise/templates/spec/requests/users/registrations_spec.rb +445 -0
- data/lib/generators/rockstart/devise/templates/spec/requests/users/sessions_spec.rb +171 -0
- data/lib/generators/rockstart/devise/templates/spec/support/devise_request_spec_helper.rb +29 -0
- data/lib/generators/rockstart/devise/templates/translations.en.yml +4 -0
- data/lib/generators/rockstart/docker/USAGE +10 -0
- data/lib/generators/rockstart/docker/docker_generator.rb +86 -0
- data/lib/generators/rockstart/docker/templates/app/Dockerfile-app +47 -0
- data/lib/generators/rockstart/docker/templates/docker-compose.test.yml +29 -0
- data/lib/generators/rockstart/docker/templates/docker-compose.yml +47 -0
- data/lib/generators/rockstart/docker/templates/dockerignore +16 -0
- data/lib/generators/rockstart/docker/templates/dotenv.docker.tt +4 -0
- data/lib/generators/rockstart/docker/templates/localhost_domains.ext.tt +7 -0
- data/lib/generators/rockstart/docker/templates/setup-localhost.tt +27 -0
- data/lib/generators/rockstart/docker/templates/web/Dockerfile-web +15 -0
- data/lib/generators/rockstart/docker/templates/web/nginx.conf +62 -0
- data/lib/generators/rockstart/frontend_helpers/USAGE +8 -0
- data/lib/generators/rockstart/frontend_helpers/frontend_helpers_generator.rb +65 -0
- data/lib/generators/rockstart/frontend_helpers/templates/application_urls.rb +26 -0
- data/lib/generators/rockstart/frontend_helpers/templates/application_urls_helper.rb +20 -0
- data/lib/generators/rockstart/frontend_helpers/templates/titles.en.yml.tt +5 -0
- data/lib/generators/rockstart/logging/USAGE +8 -0
- data/lib/generators/rockstart/logging/logging_generator.rb +12 -0
- data/lib/generators/rockstart/logging/templates/rockstart/lograge_initializer.rb +50 -0
- data/lib/generators/rockstart/postgres/USAGE +8 -0
- data/lib/generators/rockstart/postgres/postgres_generator.rb +32 -0
- data/lib/generators/rockstart/postgres/templates/config/database.yml.tt +18 -0
- data/lib/generators/rockstart/postgres/templates/migration.rb.tt +7 -0
- data/lib/generators/rockstart/pundit/USAGE +8 -0
- data/lib/generators/rockstart/pundit/pundit_generator.rb +32 -0
- data/lib/generators/rockstart/pundit/templates/app/controllers/concerns/pundit_error_handling.rb +29 -0
- data/lib/generators/rockstart/pundit/templates/app/policies/application_policy.rb +71 -0
- data/lib/generators/rockstart/pundit/templates/app/policies/user_policy.rb +47 -0
- data/lib/generators/rockstart/pundit/templates/config/locales/pundit.en.yml +6 -0
- data/lib/generators/rockstart/pundit/templates/lib/templates/pundit/policy/policy.rb +36 -0
- data/lib/generators/rockstart/pundit/templates/lib/templates/rspec/policy/policy_spec.rb +58 -0
- data/lib/generators/rockstart/pundit/templates/spec/policies/user_policy_spec.rb +95 -0
- data/lib/generators/rockstart/pundit/templates/spec/support/pundit_matchers.rb +7 -0
- data/lib/generators/rockstart/quality/USAGE +10 -0
- data/lib/generators/rockstart/quality/quality_generator.rb +28 -0
- data/lib/generators/rockstart/quality/templates/quality.rake +4 -0
- data/lib/generators/rockstart/quality/templates/rubocop.rake +4 -0
- data/lib/generators/rockstart/quality/templates/rubocop.yml +45 -0
- data/lib/generators/rockstart/rockstart_generator.rb +77 -0
- data/lib/generators/rockstart/rspec/USAGE +8 -0
- data/lib/generators/rockstart/rspec/rspec_generator.rb +70 -0
- data/lib/generators/rockstart/rspec/templates/dotenv.development +1 -0
- data/lib/generators/rockstart/rspec/templates/dotenv.test +1 -0
- data/lib/generators/rockstart/rspec/templates/rspec_templates/model/model_spec.rb +13 -0
- data/lib/generators/rockstart/rspec/templates/support/factory_bot.rb +6 -0
- data/lib/generators/rockstart/rspec/templates/support/shoulda_matchers.rb +9 -0
- data/lib/generators/rockstart/rspec/templates/support/test_helpers.rb +9 -0
- data/lib/generators/rockstart/scaffold_templates/USAGE +8 -0
- data/lib/generators/rockstart/scaffold_templates/scaffold_templates_generator.rb +39 -0
- data/lib/generators/rockstart/scaffold_templates/templates/api_controller.rb.tt +96 -0
- data/lib/generators/rockstart/scaffold_templates/templates/controller.rb.tt +126 -0
- data/lib/generators/rockstart/scaffold_templates/templates/rspec/scaffold/api_request_spec.rb +139 -0
- data/lib/generators/rockstart/scaffold_templates/templates/rspec/scaffold/request_spec.rb +408 -0
- data/lib/generators/rockstart/security/USAGE +13 -0
- data/lib/generators/rockstart/security/security_generator.rb +108 -0
- data/lib/generators/rockstart/security/templates/brakeman.rake +6 -0
- data/lib/generators/rockstart/security/templates/bundler_audit.rake +4 -0
- data/lib/generators/rockstart/security/templates/cache_support.rb +18 -0
- data/lib/generators/rockstart/security/templates/content_security_policy_initializer.rb.tt +56 -0
- data/lib/generators/rockstart/security/templates/content_security_spec.rb.tt +83 -0
- data/lib/generators/rockstart/security/templates/csp_violations_controller.rb +39 -0
- data/lib/generators/rockstart/security/templates/rack_attack.rb +98 -0
- data/lib/generators/rockstart/security/templates/security.rake +9 -0
- data/lib/generators/rockstart/security/templates/session_store_initializer.rb.tt +7 -0
- data/lib/generators/rockstart/smtp_mailer/USAGE +8 -0
- data/lib/generators/rockstart/smtp_mailer/smtp_mailer_generator.rb +30 -0
- data/lib/generators/rockstart/smtp_mailer/templates/config/initializers/action_mailer.rb +10 -0
- data/lib/generators/rockstart/tailwindcss/USAGE +8 -0
- data/lib/generators/rockstart/tailwindcss/tailwindcss_generator.rb +30 -0
- data/lib/generators/rockstart/tailwindcss/templates/application.css +3 -0
- data/lib/generators/rockstart/tailwindcss/templates/postcss.config.js +32 -0
- data/lib/rockstart/base_generator.rb +32 -0
- data/lib/rockstart/env.rb +16 -0
- data/lib/rockstart/railtie.rb +6 -0
- data/lib/rockstart/version.rb +5 -0
- data/lib/rockstart.rb +9 -0
- data/lib/tasks/rockstart_tasks.rake +5 -0
- metadata +187 -0
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails_helper"
|
4
|
+
|
5
|
+
RSpec.describe "Users::Passwords", type: :request do
|
6
|
+
describe "GET /users/sign_in" do
|
7
|
+
context "as a guest" do
|
8
|
+
it "renders a successful response" do
|
9
|
+
get new_user_session_path
|
10
|
+
expect(response).to be_successful
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "as an authenticated user" do
|
15
|
+
let(:authenticated_user) { create(:user) }
|
16
|
+
|
17
|
+
before do
|
18
|
+
sign_in authenticated_user
|
19
|
+
end
|
20
|
+
|
21
|
+
it "redirects back to the user dashboard" do
|
22
|
+
get new_user_session_path
|
23
|
+
expect(response).to redirect_to(url_for_user_dashboard)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with a soft deleted user" do
|
28
|
+
let(:soft_deleted_user) { create(:user, :soft_deleted) }
|
29
|
+
|
30
|
+
before do
|
31
|
+
sign_in soft_deleted_user
|
32
|
+
end
|
33
|
+
|
34
|
+
it "redirects back to the landing page" do
|
35
|
+
get new_user_session_path
|
36
|
+
expect(response).to redirect_to(url_for_authentication)
|
37
|
+
|
38
|
+
follow_redirect!
|
39
|
+
expect(response.body).to have_selector(".alert-alert", text: t("devise.failure.deleted_account"))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "POST /users/sign_in", :cache_testing do
|
45
|
+
context "with known user credentials" do
|
46
|
+
let(:valid_password) { Faker::Internet.password }
|
47
|
+
let(:known_user) { create(:user, password: valid_password) }
|
48
|
+
|
49
|
+
let(:valid_sign_in_params) do
|
50
|
+
{
|
51
|
+
user: {
|
52
|
+
email: known_user.email,
|
53
|
+
password: valid_password
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
it "redirects to the dashboard" do
|
59
|
+
post new_user_session_path, params: valid_sign_in_params
|
60
|
+
expect(response).to redirect_to(url_for_user_dashboard)
|
61
|
+
|
62
|
+
follow_redirect!
|
63
|
+
expect(controller.current_user).to eq known_user.reload
|
64
|
+
expect(response.body).to have_selector(".alert-notice", text: t("devise.sessions.signed_in"))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "with known user credentials" do
|
69
|
+
let(:known_user) { create(:user) }
|
70
|
+
|
71
|
+
let(:invalid_sign_in_params) do
|
72
|
+
{
|
73
|
+
user: {
|
74
|
+
email: known_user.email,
|
75
|
+
password: Faker::Internet.password
|
76
|
+
}
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
it "renders the sign in form with an error" do
|
81
|
+
post new_user_session_path, params: invalid_sign_in_params
|
82
|
+
expect(response).to be_successful
|
83
|
+
|
84
|
+
expect(response.body).to have_selector(".alert-alert", text: t("devise.failure.invalid", authentication_keys: "Email"))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "with unknown user credentials" do
|
89
|
+
let(:unknown_sign_in_params) do
|
90
|
+
{
|
91
|
+
user: {
|
92
|
+
email: Faker::Internet.email,
|
93
|
+
password: Faker::Internet.password
|
94
|
+
}
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
it "renders the sign in form with an error" do
|
99
|
+
post new_user_session_path, params: unknown_sign_in_params
|
100
|
+
expect(response).to be_successful
|
101
|
+
|
102
|
+
expect(response.body).to have_selector(".alert-alert", text: t("devise.failure.invalid", authentication_keys: "Email"))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it "rate limits requests based off ip address" do
|
107
|
+
5.times do
|
108
|
+
post new_user_session_path, params: {
|
109
|
+
user: {
|
110
|
+
email: Faker::Internet.email,
|
111
|
+
password: Faker::Internet.password
|
112
|
+
}
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
post new_user_session_path, params: {
|
117
|
+
user: {
|
118
|
+
email: Faker::Internet.email,
|
119
|
+
password: Faker::Internet.password
|
120
|
+
}
|
121
|
+
}
|
122
|
+
expect(response).to have_http_status(:too_many_requests)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "rate limits requests based off email address" do
|
126
|
+
valid_email_parameters = {
|
127
|
+
user: {
|
128
|
+
email: Faker::Internet.email,
|
129
|
+
password: Faker::Internet.password
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
5.times do |n|
|
134
|
+
post new_user_session_path, params: valid_email_parameters, headers: {
|
135
|
+
"REMOTE_ADDR" => format("120.0.1.%<n>d", n: n)
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
post new_user_session_path, params: valid_email_parameters
|
140
|
+
expect(response).to have_http_status(:too_many_requests)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "DELETE /users/sign_outs" do
|
145
|
+
context "with an authenticated user" do
|
146
|
+
let(:authenticated_user) { create(:user) }
|
147
|
+
|
148
|
+
before do
|
149
|
+
sign_in(authenticated_user)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "redirects to the login page with a notice" do
|
153
|
+
delete destroy_user_session_path
|
154
|
+
expect(response).to redirect_to(url_for_authentication)
|
155
|
+
|
156
|
+
follow_redirect!
|
157
|
+
expect(response.body).to have_selector(".alert-notice", text: t("devise.sessions.signed_out"))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "with a guest" do
|
162
|
+
it "redirects to the login page with a notice" do
|
163
|
+
delete destroy_user_session_path
|
164
|
+
expect(response).to redirect_to(url_for_authentication)
|
165
|
+
|
166
|
+
follow_redirect!
|
167
|
+
expect(response.body).to have_selector(".alert-notice", text: t("devise.sessions.signed_out"))
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Helpers for Devise Authentication with request specs
|
4
|
+
module DeviseRequestSpecHelper
|
5
|
+
include Warden::Test::Helpers
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.before(:each) { Warden.test_mode! }
|
9
|
+
base.after(:each) { Warden.test_reset! }
|
10
|
+
end
|
11
|
+
|
12
|
+
def sign_in(resource)
|
13
|
+
login_as(resource, scope: warden_scope(resource))
|
14
|
+
end
|
15
|
+
|
16
|
+
def sign_out(resource)
|
17
|
+
logout(warden_scope(resource))
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def warden_scope(resource)
|
23
|
+
resource.class.name.underscore.to_sym
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec.configure do |config|
|
28
|
+
config.include DeviseRequestSpecHelper, type: :request
|
29
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Description:
|
2
|
+
Configures a Rails app to run in Docker
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate rockstart:docker
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
A Dockerfile containing the app and test suite
|
9
|
+
A docker-compose.yml with all required resources
|
10
|
+
A docker-compose.test.yml which will run the full test suite
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Rockstart::DockerGenerator < Rails::Generators::Base
|
4
|
+
include Rails::Generators::AppName
|
5
|
+
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
|
8
|
+
desc "This generator configures a Rails Application to work with Docker"
|
9
|
+
|
10
|
+
class_option :root_image, type: :string,
|
11
|
+
desc: "Docker image to build the container from",
|
12
|
+
default: "ruby:#{RUBY_VERSION}"
|
13
|
+
|
14
|
+
class_option :app_home, type: :string,
|
15
|
+
desc: "Mount directory used within Docker image",
|
16
|
+
default: Rails.application.engine_name
|
17
|
+
|
18
|
+
class_option :assets, type: :boolean,
|
19
|
+
desc: "Include frontend assets support (node|yarn)",
|
20
|
+
default: true
|
21
|
+
|
22
|
+
class_option :devise, type: :boolean,
|
23
|
+
desc: "Include Devise support",
|
24
|
+
default: true
|
25
|
+
|
26
|
+
class_option :postgres, type: :boolean,
|
27
|
+
desc: "Include Postgres support",
|
28
|
+
default: Rockstart::Env.postgres_db?
|
29
|
+
|
30
|
+
def create_dockerignore
|
31
|
+
copy_file "dockerignore", ".dockerignore"
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_dockerfile
|
35
|
+
@root_image = options[:root_image]
|
36
|
+
@app_home = options[:app_home]
|
37
|
+
@postgres = options[:postgres]
|
38
|
+
@assets = options[:assets]
|
39
|
+
template "app/Dockerfile-app", "Dockerfile"
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_nginx_image
|
43
|
+
@root_image = options[:root_image]
|
44
|
+
@app_home = options[:app_home]
|
45
|
+
template "web/Dockerfile-web", "docker/web/Dockerfile"
|
46
|
+
template "web/nginx.conf", "docker/web/nginx.conf"
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_docker_compose
|
50
|
+
@app_home = options[:app_home]
|
51
|
+
template "docker-compose.yml", "docker-compose.yml"
|
52
|
+
template "docker-compose.test.yml", "docker-compose.test.yml"
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_certs_directory
|
56
|
+
FileUtils.mkdir_p(Rails.root.join("docker", "certs", "web"))
|
57
|
+
append_file ".gitignore", "\n# Docker Configuration\ndocker/certs\n"
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_dotenv
|
61
|
+
template "dotenv.docker.tt", ".env.docker"
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_localhost_certificates
|
65
|
+
template "localhost_domains.ext.tt", "docker/certs/web/#{app_name}_localhost.ext"
|
66
|
+
template "setup-localhost.tt", "bin/setup-localhost"
|
67
|
+
File.chmod(0o755, Rails.root.join("bin", "setup-localhost"))
|
68
|
+
append_file ".gitignore", "\n# localhost certificate authority\nlocalhostCA.*\n"
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def devise?
|
74
|
+
options[:devise]
|
75
|
+
end
|
76
|
+
|
77
|
+
def postgres?
|
78
|
+
options[:postgres]
|
79
|
+
end
|
80
|
+
|
81
|
+
# Generates an example password
|
82
|
+
def example_db_password
|
83
|
+
require "base64"
|
84
|
+
Base64.urlsafe_encode64(Rails.application.engine_name)
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
FROM <%= @root_image %>
|
2
|
+
|
3
|
+
# Install dependencies
|
4
|
+
RUN apt-get update -qq \
|
5
|
+
&& apt-get install -y build-essential \
|
6
|
+
&& apt-get install -y libxml2-dev libxslt1-dev \
|
7
|
+
<%- if @postgres -%>
|
8
|
+
&& apt-get install -y libpq-dev \
|
9
|
+
<%- end -%>
|
10
|
+
<%- if @assets -%>
|
11
|
+
&& curl -sL https://deb.nodesource.com/setup_10.x | bash - \
|
12
|
+
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
|
13
|
+
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
|
14
|
+
&& apt-get update && apt-get install -y nodejs yarn \
|
15
|
+
<%- end -%>
|
16
|
+
&& apt-get clean
|
17
|
+
|
18
|
+
ENV RACK_ENV=production \
|
19
|
+
<%- if @assets -%>
|
20
|
+
NODE_ENV=production \
|
21
|
+
<%- end -%>
|
22
|
+
RAILS_LOG_TO_STDOUT=true \
|
23
|
+
RAILS_ENV=production
|
24
|
+
|
25
|
+
RUN mkdir /<%= @app_home %>
|
26
|
+
WORKDIR /<%= @app_home %>
|
27
|
+
|
28
|
+
# Install gems
|
29
|
+
ADD Gemfile* /<%= @app_home %>/
|
30
|
+
RUN gem install bundler:2.1.4 \
|
31
|
+
&& bundle config set deployment 'true' \
|
32
|
+
&& bundle config set without 'development' \
|
33
|
+
&& bundle install
|
34
|
+
|
35
|
+
# Install application
|
36
|
+
ADD . /<%= @app_home %>
|
37
|
+
|
38
|
+
# Perform post-installation tasks
|
39
|
+
RUN bundle exec rake tmp:create \
|
40
|
+
<%- if @assets -%>
|
41
|
+
&& bundle exec rake assets:precompile \
|
42
|
+
<%- end -%>
|
43
|
+
&& bundle exec rake tmp:clear
|
44
|
+
|
45
|
+
# Start the application server
|
46
|
+
EXPOSE 3000
|
47
|
+
CMD ["bundle", "exec", "rails", "server", "-p", "3000", "-b", "0.0.0.0"]
|
@@ -0,0 +1,29 @@
|
|
1
|
+
version: '2.0'
|
2
|
+
services:
|
3
|
+
sut:
|
4
|
+
build: .
|
5
|
+
command: bash -c "bundle exec rake db:migrate && bundle exec rake"
|
6
|
+
depends_on:
|
7
|
+
<%- if postgres? -%>
|
8
|
+
- db
|
9
|
+
<%- end -%>
|
10
|
+
- mailcatcher
|
11
|
+
environment:
|
12
|
+
- RAILS_ENV=test
|
13
|
+
<%- if postgres? -%>
|
14
|
+
- TEST_DATABASE_URL=postgres://<%= app_name %>:<%= app_name %>_test@db/<%= app_name %>_test
|
15
|
+
<%- end -%>
|
16
|
+
- SMTP_SERVER=mailcatcher
|
17
|
+
- SMTP_PORT=1025
|
18
|
+
env_file:
|
19
|
+
- ./.env.test
|
20
|
+
<%- if postgres? -%>
|
21
|
+
db:
|
22
|
+
image: postgres
|
23
|
+
environment:
|
24
|
+
- POSTGRES_DB=<%= app_name %>_test
|
25
|
+
- POSTGRES_USER=<%= app_name %>
|
26
|
+
- POSTGRES_PASSWORD=<%= app_name %>_test
|
27
|
+
<%- end -%>
|
28
|
+
mailcatcher:
|
29
|
+
image: sj26/mailcatcher
|
@@ -0,0 +1,47 @@
|
|
1
|
+
version: '2.0'
|
2
|
+
services:
|
3
|
+
app:
|
4
|
+
build: .
|
5
|
+
environment:
|
6
|
+
<%- if postgres? -%>
|
7
|
+
- DATABASE_URL=postgres://<%= app_name %>:<%= example_db_password %>@db/<%= app_name %>_production
|
8
|
+
<%- end -%>
|
9
|
+
- SMTP_SERVER=mailcatcher
|
10
|
+
- SMTP_PORT=1025
|
11
|
+
env_file:
|
12
|
+
- ./.env.docker
|
13
|
+
<%- if postgres? -%>
|
14
|
+
depends_on:
|
15
|
+
- db
|
16
|
+
<%- end -%>
|
17
|
+
volumes:
|
18
|
+
- static-assets:/<%= @app_home %>/public
|
19
|
+
<%- if postgres? -%>
|
20
|
+
db:
|
21
|
+
image: postgres
|
22
|
+
environment:
|
23
|
+
- POSTGRES_DB=<%= app_name %>_production
|
24
|
+
- POSTGRES_USER=<%= app_name %>
|
25
|
+
- POSTGRES_PASSWORD=<%= example_db_password %>
|
26
|
+
volumes:
|
27
|
+
- ./tmp/db:/var/lib/postgresql/data
|
28
|
+
<%- end -%>
|
29
|
+
mailcatcher:
|
30
|
+
image: sj26/mailcatcher
|
31
|
+
ports:
|
32
|
+
- 1080:1080
|
33
|
+
web:
|
34
|
+
build:
|
35
|
+
context: ./docker/web/
|
36
|
+
depends_on:
|
37
|
+
- app
|
38
|
+
ports:
|
39
|
+
- 80:80
|
40
|
+
- 443:443
|
41
|
+
volumes:
|
42
|
+
- ./docker/certs/web:/<%= @app_home %>/certs
|
43
|
+
- static-assets:/<%= @app_home %>/public
|
44
|
+
- web-logs:/<%= @app_home %>/log
|
45
|
+
volumes:
|
46
|
+
static-assets: {}
|
47
|
+
web-logs: {}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -o errexit
|
4
|
+
set -o pipefail
|
5
|
+
set -o nounset
|
6
|
+
|
7
|
+
echo "=== Creating Certification Authority for localhost ==="
|
8
|
+
|
9
|
+
openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 \
|
10
|
+
-keyout localhostCA.key \
|
11
|
+
-out localhostCA.pem \
|
12
|
+
-subj "/C=US/CN=Example-Root-CA"
|
13
|
+
|
14
|
+
openssl x509 -outform pem -in localhostCA.pem -out localhostCA.crt
|
15
|
+
|
16
|
+
echo "=== Generating Domain Name Certificate ==="
|
17
|
+
|
18
|
+
openssl req -new -nodes -newkey rsa:2048 \
|
19
|
+
-keyout docker/certs/web/<%= app_name %>.key \
|
20
|
+
-out docker/certs/web/<%= app_name %>.csr \
|
21
|
+
-subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=<%= app_name %>.local"
|
22
|
+
|
23
|
+
openssl x509 -req -sha256 -days 1024 \
|
24
|
+
-in docker/certs/web/<%= app_name %>.csr \
|
25
|
+
-CA localhostCA.pem -CAkey localhostCA.key \
|
26
|
+
-CAcreateserial -extfile docker/certs/<%= app_name %>_localhost.ext \
|
27
|
+
-out docker/certs/web/<%= app_name %>.crt
|
@@ -0,0 +1,15 @@
|
|
1
|
+
FROM nginx
|
2
|
+
|
3
|
+
RUN apt-get update -qq && apt-get -y install apache2-utils
|
4
|
+
|
5
|
+
ENV RAILS_ROOT /<%= @app_home %>
|
6
|
+
|
7
|
+
WORKDIR /<%= @app_home %>
|
8
|
+
|
9
|
+
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
10
|
+
|
11
|
+
EXPOSE 80
|
12
|
+
EXPOSE 443
|
13
|
+
|
14
|
+
# Use the "exec" form of CMD so Nginx shuts down gracefully on SIGTERM (i.e. `docker stop`)
|
15
|
+
CMD [ "nginx", "-g", "daemon off;" ]
|
@@ -0,0 +1,62 @@
|
|
1
|
+
upstream rails_app {
|
2
|
+
server app:3000;
|
3
|
+
}
|
4
|
+
|
5
|
+
server {
|
6
|
+
listen 80;
|
7
|
+
listen 443 ssl;
|
8
|
+
|
9
|
+
# define your domain
|
10
|
+
# server_name www.example.com;
|
11
|
+
|
12
|
+
ssl_certificate /<%= @app_home %>/certs/<%= app_name %>.crt;
|
13
|
+
ssl_certificate_key /<%= @app_home %>/certs/<%= app_name %>.key;
|
14
|
+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
15
|
+
ssl_ciphers HIGH:!aNULL:!MD5;
|
16
|
+
|
17
|
+
# define the public application root
|
18
|
+
root /<%= @app_home %>/public;
|
19
|
+
index index.html;
|
20
|
+
|
21
|
+
# define where Nginx should write its logs
|
22
|
+
access_log /<%= @app_home %>/log/nginx.access.log;
|
23
|
+
error_log /<%= @app_home %>/log/nginx.error.log;
|
24
|
+
|
25
|
+
# serve static (compiled) assets directly if they exist
|
26
|
+
location ~ ^/(assets|packs)/ {
|
27
|
+
try_files $uri =404;
|
28
|
+
|
29
|
+
access_log off; # don't save asset requests to access logs
|
30
|
+
gzip_static on; # to serve pre-gzipped version
|
31
|
+
|
32
|
+
# Cache assets for as long as possible
|
33
|
+
expires max;
|
34
|
+
add_header Cache-Control public;
|
35
|
+
|
36
|
+
# Some browsers still send conditional-GET requests if there's a
|
37
|
+
# Last-Modified header or an ETag header even if they haven't
|
38
|
+
# reached the expiry date sent in the Expires header.
|
39
|
+
add_header Last-Modified "";
|
40
|
+
add_header ETag "";
|
41
|
+
break;
|
42
|
+
}
|
43
|
+
|
44
|
+
# send non-static file requests to the app server
|
45
|
+
location / {
|
46
|
+
try_files $uri @rails;
|
47
|
+
}
|
48
|
+
|
49
|
+
location @rails {
|
50
|
+
proxy_set_header X-Real-IP $remote_addr;
|
51
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
52
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
53
|
+
proxy_set_header Host $http_host;
|
54
|
+
proxy_redirect off;
|
55
|
+
proxy_pass http://rails_app;
|
56
|
+
}
|
57
|
+
|
58
|
+
error_page 404 /404.html;
|
59
|
+
error_page 500 502 503 504 /500.html;
|
60
|
+
# client_max_body_size 1m;
|
61
|
+
# keepalive_timeout 10;
|
62
|
+
}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Rockstart::FrontendHelpersGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
5
|
+
|
6
|
+
class_option :force_url_helpers, type: :boolean,
|
7
|
+
desc: "Force creation of blank Application URL Helpers",
|
8
|
+
default: false
|
9
|
+
|
10
|
+
def install_simple_form
|
11
|
+
gem "simple_form"
|
12
|
+
|
13
|
+
Bundler.with_clean_env do
|
14
|
+
run "bundle install --quiet"
|
15
|
+
|
16
|
+
generate "simple_form:install"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def install_titles
|
21
|
+
gem "title", github: "calebthompson/title"
|
22
|
+
|
23
|
+
template "titles.en.yml.tt", "config/locales/titles.en.yml"
|
24
|
+
|
25
|
+
gsub_file "app/views/layouts/application.html.erb", %r{\<title(.+)\</title},
|
26
|
+
"<title><%= title %></title"
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_application_urls_concern
|
30
|
+
if force_url_helpers? || !File.exist?(Rails.root.join(application_urls_concern_path))
|
31
|
+
copy_file "application_urls.rb", application_urls_concern_path
|
32
|
+
else
|
33
|
+
say "Skipping #{application_urls_concern_path}"
|
34
|
+
end
|
35
|
+
inject_into_file "app/controllers/application_controller.rb",
|
36
|
+
" include ApplicationUrls\n",
|
37
|
+
before: /^end$/
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_application_urls_helper
|
41
|
+
if force_url_helpers? || !File.exist?(Rails.root.join(application_urls_helper_path))
|
42
|
+
copy_file "application_urls_helper.rb", application_urls_helper_path
|
43
|
+
else
|
44
|
+
say "Skipping #{application_urls_helper_path}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def default_title
|
51
|
+
Rails.application.class.to_s.split("::").first
|
52
|
+
end
|
53
|
+
|
54
|
+
def force_url_helpers?
|
55
|
+
options.fetch(:force_url_helpers)
|
56
|
+
end
|
57
|
+
|
58
|
+
def application_urls_concern_path
|
59
|
+
File.join("app", "controllers", "concerns", "application_urls.rb")
|
60
|
+
end
|
61
|
+
|
62
|
+
def application_urls_helper_path
|
63
|
+
File.join("spec", "support", "application_urls_helper.rb")
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# ApplicationUrls generated by rockstart:frontend_helpers
|
4
|
+
module ApplicationUrls
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper_method :url_for_authentication
|
9
|
+
helper_method :url_for_landing_page
|
10
|
+
helper_method :url_for_user_dashboard
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def url_for_authentication
|
16
|
+
root_url # TODO: Provide url for authentication page
|
17
|
+
end
|
18
|
+
|
19
|
+
def url_for_landing_page
|
20
|
+
root_url # TODO: Provide url for landing page
|
21
|
+
end
|
22
|
+
|
23
|
+
def url_for_user_dashboard
|
24
|
+
root_url # TODO: Provide url for user dashboard link
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# ApplicationUrlsHelper generated by rockstart:frontend_helpers
|
4
|
+
module ApplicationUrlsHelper
|
5
|
+
def url_for_authentication
|
6
|
+
root_url # TODO: Provide url for authentication page
|
7
|
+
end
|
8
|
+
|
9
|
+
def url_for_landing_page
|
10
|
+
root_url # TODO: Provide url for landing page
|
11
|
+
end
|
12
|
+
|
13
|
+
def url_for_user_dashboard
|
14
|
+
root_url # TODO: Provide url for user dashboard link
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.include ApplicationUrlsHelper
|
20
|
+
end
|