rockstart 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|