diff --git a/.gitignore b/.gitignore
index 82701fe..ac75264 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,5 @@
/yarn-error.log
.byebug_history
+
+test/reports/
diff --git a/Gemfile b/Gemfile
index ec2aff9..a63fd78 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,6 +5,7 @@ git_source(:github) do |repo_name|
"https://github.com/#{repo_name}.git"
end
+gem 'attr_encrypted', '~> 3.0', github: 'attr-encrypted/attr_encrypted'
gem 'bootstrap', '~> 4.0.0.alpha6'
gem 'devise', '~> 4.3.0'
gem 'devise_invitable', '~> 1.7', '>= 1.7.2'
diff --git a/Gemfile.lock b/Gemfile.lock
index b595341..a61a1f6 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,3 +1,10 @@
+GIT
+ remote: https://github.com/attr-encrypted/attr_encrypted.git
+ revision: e19445a9ae38ed9a55608d28a80e32126f30efd1
+ specs:
+ attr_encrypted (3.0.3)
+ encryptor (~> 3.0.0)
+
GEM
remote: https://rubygems.org/
specs:
@@ -69,6 +76,7 @@ GEM
devise_invitable (1.7.2)
actionmailer (>= 4.1.0)
devise (>= 4.0.0)
+ encryptor (3.0.0)
erubi (1.6.1)
execjs (2.7.0)
factory_girl (4.8.0)
@@ -203,6 +211,7 @@ PLATFORMS
ruby
DEPENDENCIES
+ attr_encrypted (~> 3.0)!
bootstrap (~> 4.0.0.alpha6)
byebug
capybara (~> 2.13)
diff --git a/Procfile b/Procfile
index fdb99da..6a153b3 100644
--- a/Procfile
+++ b/Procfile
@@ -1 +1 @@
-web: bundle exec rails server
+web: bundle exec rails server -p 3000
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 5985993..bb97671 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -4,7 +4,7 @@ class ApplicationController < ActionController::Base
layout(:by_resource)
before_action(:configure_permitted_parameters, if: :devise_controller?)
- before_action(:configure_app)
+ before_action(:configure_initial_account)
private
@@ -16,8 +16,8 @@ class ApplicationController < ActionController::Base
devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :password])
end
- def configure_app
- return unless AppSetup.new(current_user, request.path).required?
+ def configure_initial_account
+ return unless InitialAccountSetup.new(current_user, request.path).required?
flash[:info] = 'Welcome to Storm! Let\'s get your app setup.'
redirect_to(new_user_registration_path)
diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb
new file mode 100644
index 0000000..c34d754
--- /dev/null
+++ b/app/controllers/settings_controller.rb
@@ -0,0 +1,31 @@
+class SettingsController < ApplicationController
+ before_action(:authenticate_user!)
+ before_action(:create_settings, only: %w(edit))
+
+ def edit
+ @setting = Setting.first
+ end
+
+ def update
+ @setting = Setting.first
+
+ if @setting.update(setting_params)
+ flash[:notice] = 'Your settings have been updated.'
+ redirect_to root_path
+ else
+ flash[:alert] = 'Something went wrong updating settings.
+ Please check and try again'
+ render :edit
+ end
+ end
+
+ private
+
+ def setting_params
+ params.require(:setting).permit(:aws_key, :aws_secret, :slack_url)
+ end
+
+ def create_settings
+ SettingsCreator.execute if Setting.count.zero?
+ end
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 0000000..36aae15
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,7 @@
+class UsersController < ApplicationController
+ before_action(:authenticate_user!)
+
+ def index
+ @users = User.all
+ end
+end
diff --git a/app/models/setting.rb b/app/models/setting.rb
new file mode 100644
index 0000000..5ec281d
--- /dev/null
+++ b/app/models/setting.rb
@@ -0,0 +1,19 @@
+class Setting < ApplicationRecord
+ attr_encrypted(
+ :aws_key,
+ key: Rails.application.secrets.secret_key_base.byteslice(0, 32)
+ )
+ attr_encrypted(
+ :aws_secret,
+ key: Rails.application.secrets.secret_key_base.byteslice(0, 32)
+ )
+
+ before_create :validate_only_one_setting_record
+
+ private
+
+ def validate_only_one_setting_record
+ errors.add(:base, 'There can only be one setting') if
+ Setting.count.positive?
+ end
+end
diff --git a/app/services/app_setup.rb b/app/services/initial_account_setup.rb
similarity index 90%
rename from app/services/app_setup.rb
rename to app/services/initial_account_setup.rb
index e0433e7..28c6929 100644
--- a/app/services/app_setup.rb
+++ b/app/services/initial_account_setup.rb
@@ -1,5 +1,5 @@
-# AppSetup
-class AppSetup
+# InitialAccountSetup
+class InitialAccountSetup
attr_reader(:current_user, :current_path)
def initialize(current_user, current_path)
diff --git a/app/services/settings_creator.rb b/app/services/settings_creator.rb
new file mode 100644
index 0000000..9e4bcc1
--- /dev/null
+++ b/app/services/settings_creator.rb
@@ -0,0 +1,6 @@
+# SettingsCreator
+class SettingsCreator
+ def self.execute
+ Setting.create unless Setting.count.positive?
+ end
+end
diff --git a/app/views/settings/_form.html.erb b/app/views/settings/_form.html.erb
new file mode 100644
index 0000000..d900743
--- /dev/null
+++ b/app/views/settings/_form.html.erb
@@ -0,0 +1,39 @@
+<%= form_for(@setting, url: settings_path) do |f| %>
+
+
+ AWS Configuration
+
+
+ Althought completely optional, configuring Storm with AWS will give
+ you the ability to reboot servers from Slack.
+
+
+
+ <%= f.label :aws_key, "AWS Key" %>
+ <%= f.text_field :aws_key, class: "form-control" %>
+
+
+
+
+
+ <%= f.submit "Update Settings", class: "btn btn-primary btn-block" %>
+
+<% end %>
diff --git a/app/views/settings/edit.html.erb b/app/views/settings/edit.html.erb
new file mode 100644
index 0000000..65764fd
--- /dev/null
+++ b/app/views/settings/edit.html.erb
@@ -0,0 +1,13 @@
+
+
Let's update your settings
+
+
+
+
+
+
+ <%= render "form" %>
+
+
+
+
diff --git a/app/views/shared/_navbar.html.erb b/app/views/shared/_navbar.html.erb
index c558ec6..3fbeebc 100644
--- a/app/views/shared/_navbar.html.erb
+++ b/app/views/shared/_navbar.html.erb
@@ -2,6 +2,10 @@
<%= nav_link("Websites", root_path) %>
<%= nav_link("Stats", "#") %>
- <%= nav_link("Accounts", "#") %>
+ <%= nav_link("Settings", edit_settings_path) %>
+ <%= nav_link("Users", users_path) %>
+ <% if user_signed_in? %>
+ <%= nav_link("Sign Out", destroy_user_session_path, method: :delete) %>
+ <% end %>
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb
new file mode 100644
index 0000000..6b565ec
--- /dev/null
+++ b/app/views/users/_user.html.erb
@@ -0,0 +1,6 @@
+
+ <%= user.email %> |
+ <%= user.created_at %> |
+
+ |
+
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb
new file mode 100644
index 0000000..cff6ffe
--- /dev/null
+++ b/app/views/users/index.html.erb
@@ -0,0 +1,23 @@
+
+
+
+
Users
+
+
+
+
+
+ Email |
+ Created on |
+ |
+
+
+
+ <%= render(@users) %>
+
+
+
+
+
+
+
diff --git a/config/routes.rb b/config/routes.rb
index 10b3788..b59d6ec 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -16,5 +16,7 @@ Rails.application.routes.draw do
sign_up: 'sign-up'
}
+ resource(:settings, only: %w(edit update))
+ resources(:users, only: %w(index))
resources(:websites, only: %w(new create))
end
diff --git a/db/migrate/20170714145639_create_settings.rb b/db/migrate/20170714145639_create_settings.rb
new file mode 100644
index 0000000..6b8c9bc
--- /dev/null
+++ b/db/migrate/20170714145639_create_settings.rb
@@ -0,0 +1,17 @@
+class CreateSettings < ActiveRecord::Migration[5.1]
+ def up
+ create_table :settings do |t|
+ t.string :slack_url
+ t.string :encrypted_aws_key
+ t.string :encrypted_aws_key_iv
+ t.string :encrypted_aws_secret
+ t.string :encrypted_aws_secret_iv
+
+ t.timestamps
+ end
+ end
+
+ def down
+ drop_table(:settings)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 5cf0bae..5783bab 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170630210637) do
+ActiveRecord::Schema.define(version: 20170714145639) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -23,6 +23,16 @@ ActiveRecord::Schema.define(version: 20170630210637) do
t.index ["website_id"], name: "index_pings_on_website_id"
end
+ create_table "settings", force: :cascade do |t|
+ t.string "slack_url"
+ t.string "encrypted_aws_key"
+ t.string "encrypted_aws_key_iv"
+ t.string "encrypted_aws_secret"
+ t.string "encrypted_aws_secret_iv"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
diff --git a/test/controllers/settings_controller_test.rb b/test/controllers/settings_controller_test.rb
new file mode 100644
index 0000000..6fe2aad
--- /dev/null
+++ b/test/controllers/settings_controller_test.rb
@@ -0,0 +1,32 @@
+require 'test_helper'
+
+class SettingsControllerTest < ActionDispatch::IntegrationTest
+ feature 'as as authenticated user' do
+ before(:each) do
+ @user = create(:user)
+ sign_in(@user)
+ end
+
+ test 'should get edit settings' do
+ get(edit_settings_url)
+ assert_response(:success)
+ end
+
+ test 'should patch update' do
+ # Create a setting so that one exists in the DB to update
+ Setting.create(aws_key: 'testing')
+
+ assert_no_difference('Setting.count') do
+ patch(settings_url, params: { setting: { aws_key: 'test' } })
+ assert_redirected_to(root_url)
+ end
+ end
+ end
+
+ feature 'as as an unauthenticated user' do
+ test 'should get redirected to sign-in' do
+ get(users_url)
+ assert_redirected_to(new_user_session_path)
+ end
+ end
+end
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
new file mode 100644
index 0000000..ba9522a
--- /dev/null
+++ b/test/controllers/users_controller_test.rb
@@ -0,0 +1,22 @@
+require 'test_helper'
+
+class UsersControllerTest < ActionDispatch::IntegrationTest
+ feature 'as as authenticated user' do
+ before(:each) do
+ @user = create(:user)
+ sign_in(@user)
+ end
+
+ test 'should get index' do
+ get(users_url)
+ assert_response(:success)
+ end
+ end
+
+ feature 'as as an unauthenticated user' do
+ test 'should get redirected to sign-in' do
+ get(users_url)
+ assert_redirected_to(new_user_session_path)
+ end
+ end
+end
diff --git a/test/controllers/websites_controller_test.rb b/test/controllers/websites_controller_test.rb
index fc2e921..8c0ac8b 100644
--- a/test/controllers/websites_controller_test.rb
+++ b/test/controllers/websites_controller_test.rb
@@ -35,7 +35,7 @@ class WebsitesControllerTest < ActionDispatch::IntegrationTest
end
end
- feature 'as an authenticated user' do
+ feature 'as an unauthenticated user' do
test 'should not get index' do
assert_raise do
get('/websites')
diff --git a/test/factories/settings.rb b/test/factories/settings.rb
new file mode 100644
index 0000000..5fbf823
--- /dev/null
+++ b/test/factories/settings.rb
@@ -0,0 +1,4 @@
+FactoryGirl.define do
+ factory :setting do
+ end
+end
diff --git a/test/models/setting_test.rb b/test/models/setting_test.rb
new file mode 100644
index 0000000..16553d1
--- /dev/null
+++ b/test/models/setting_test.rb
@@ -0,0 +1,15 @@
+require 'test_helper'
+
+class SettingTest < ActiveSupport::TestCase
+ test 'aws_key is encrypted' do
+ setting = Setting.new(aws_key: 'foo')
+ assert(setting.save)
+ assert_not_nil(setting.encrypted_aws_key)
+ end
+
+ test 'aws_secret is encrypted' do
+ setting = Setting.new(aws_secret: 'foo')
+ assert(setting.save)
+ assert_not_nil(setting.encrypted_aws_secret)
+ end
+end