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| %> +
+ <%= f.label :slack_url, "Slack URL for notifications" %> + <%= f.text_field :slack_url, autofocus: true, class: "form-control" %> + +

+ Instructions for finding your Slack URL can be found + <%= link_to "here", + "https://slack.com/apps/A0F7XDUAZ-incoming-webhooks", + target: :blank %>. +

+
+ +
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.label :aws_secret, "AWS Secret" %> + <%= f.text_field :aws_secret, class: "form-control" %> + +

+ Instructions for finding your AWS Key and Secret can be found + <%= link_to "here", "#" %>. +

+
+ +
+ <%= 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 @@ 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

+ +
+ + + + + + + + + + <%= render(@users) %> + +
EmailCreated on
+
+ +
+
+
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