Skip to content
This repository was archived by the owner on Mar 24, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d5dc783
adding theme and theme_status models
Jun 24, 2015
51bc06e
adding empty slim views for index and new actions of themes_controller
Jun 24, 2015
b4be15b
adding missing files of new action view and rspec of themes_controller
Jun 24, 2015
e8a6165
shortening validations of theme and theme_status models
Jun 25, 2015
5675050
adding policy conditions tests for theme_upload model
Jun 25, 2015
b0dd7eb
adding nullability tests of theme and theme_status model columns
Jun 25, 2015
88fdf16
added tests for theme_upload model
Jun 26, 2015
a0dc853
saving Theme in create_completed method of theme_controller
Jun 26, 2015
c63730b
merging development
Jun 26, 2015
772a68a
removing debug-related line from the working code
Jun 26, 2015
8719d6c
avoiding deprecation warning with OpenSSL::Digest
Jun 26, 2015
8821e16
requiring rails_helper in specs
Jun 26, 2015
4ea4e38
renaming secret key configuration setting according to AWS terminology
Jun 26, 2015
6a2f7a6
moving theme_upload_spec to classes folder
Jun 30, 2015
d3c6b41
better formatting of theme_upload tests
Jun 30, 2015
6e71e24
better formatting for theme_controller status
Jun 30, 2015
78fc950
adding more tests for key format in create_completed method of themes…
Jun 30, 2015
51a2e1a
adding more theme attribute assertions for create_completed method of…
Jun 30, 2015
f6554d0
replacing theme_status model with status enum in theme model
Jun 30, 2015
c6359f0
removing theme status not covered by tests yet
Jun 30, 2015
00312e1
DRY-ing theme status spec
Jun 30, 2015
4f51512
Merge from development
alexander-e1off Jul 10, 2015
a629634
Moved AWS secret information into .env file
alexander-e1off Jul 13, 2015
77a7f4f
Refactored to use themes_helper instead of theme_upload class, added …
alexander-e1off Jul 14, 2015
9f87632
Updated Role: added theme permissions, updated themes_controller_spec…
olgaborovaya Jul 14, 2015
2b09f6b
Updated Theme to validate filename extension
alexander-e1off Jul 14, 2015
01e0927
themes_controller:DELETE#destroy and themes_controller_spec: DELETE#d…
olgaborovaya Jul 14, 2015
ae26997
DRY-ed themes_helper
alexander-e1off Jul 15, 2015
8d4e1e1
Added transfer_theme_job
alexander-e1off Jul 16, 2015
a4a9162
DRY-ed themes_controller
alexander-e1off Jul 17, 2015
8edf83b
Theme: added theme file management in AWS
alexander-e1off Jul 20, 2015
cd00570
DRY-ed Theme
alexander-e1off Jul 20, 2015
0168998
Fixed code review findings
alexander-e1off Jul 20, 2015
14d2908
Added sidekiq backend, added retry_job for AWS connection error
alexander-e1off Jul 21, 2015
076d0d6
Added usage of devise-async and apartment-sidekiq gems
alexander-e1off Jul 21, 2015
3c6758f
Added Sidekiq monitoring, added Theme views
alexander-e1off Jul 22, 2015
6c9d214
Merged
USAWal Jul 27, 2015
c18f10d
Added Theme management acceptance tests
alexander-e1off Jul 28, 2015
88d2ed4
Update sass-rails gem version
alexander-e1off Jul 28, 2015
d005220
DRY-ed themes_index_page_spec
alexander-e1off Jul 29, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ HOST=lvh.me:3000
GMAIL_DOMAIN=gmail.com
GMAIL_USERNAME=dontreply1357@gmail.com
GMAIL_PASSWORD=13579rty
AWS_SECRET_ACCESS_KEY=xbnXDiIvtqVAmoaFT5yYZWu4Wye/l+CvQt6Cp2bm
AWS_ACCESS_KEY=AKIAIQ2MGPRTWCHJKK5A
12 changes: 12 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ gem 'coffee-rails', '~> 4.1.0'

# Use apartment for multi-tenant databases
gem 'apartment', '~> 1.0.1'
gem 'apartment-sidekiq', '~> 0.2.0'

#bootstrap CSS
#gem 'bootstrap-sass'
# Devise is a flexible authentication solution for Rails based on Warden
gem 'devise', '~> 3.5.1'
gem 'devise-async', '~>0.10.1'

# simple authorization solution for Rails which is decoupled from user roles
gem 'cancancan', '~> 1.12.0'
Expand All @@ -36,6 +38,11 @@ gem 'sdoc', '~> 0.4.0', group: :doc

gem 'slim-rails', '~> 3.0.1'

# Simple, efficient background processing
gem 'sidekiq', '~> 3.4.2'
# For Sidekiq monitor
gem 'sinatra', '~> 1.4.6'

# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

Expand All @@ -48,6 +55,9 @@ gem 'unicorn', '~> 4.9.0'
# Shim to load environment variables from .env into ENV in development.
gem 'dotenv-rails', '~> 2.0.2', :groups => [:development, :test]

# Official Amazon AWS SDK
gem 'aws-sdk', '~> 2.1.7'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
Expand All @@ -64,11 +74,13 @@ group :test do
gem 'capybara', '~> 2.4.4'
gem 'database_cleaner', '~> 1.4.1'
gem 'rspec-rails', '~> 3.2.3'
gem 'rspec-its', '~> 1.2.0'
gem 'factory_girl', '~> 4.5.0'
gem 'rspec-expectations', '~> 3.2.1'
gem 'factory_girl_rails', '~> 4.0'
gem 'shoulda-matchers', '~> 2.8.0'
gem 'faker', '~> 1.4.3'
gem 'rspec-activejob', '~> 0.4.1'
end

# Deployment
Expand Down
57 changes: 46 additions & 11 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,19 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
apartment (1.0.1)
apartment (1.0.2)
activerecord (>= 3.1.2, < 5.0)
rack (>= 1.3.6)
arel (6.0.0)
apartment-sidekiq (0.2.0)
apartment (~> 1.0)
sidekiq (>= 2.11)
arel (6.0.2)
aws-sdk (2.1.8)
aws-sdk-resources (= 2.1.8)
aws-sdk-core (2.1.8)
jmespath (~> 1.0)
aws-sdk-resources (2.1.8)
aws-sdk-core (= 2.1.8)
bcrypt (3.1.10)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
Expand Down Expand Up @@ -83,7 +92,7 @@ GEM
colorize (0.7.7)
columnize (0.9.0)
connection_pool (2.2.0)
cucumber (1.3.19)
cucumber (1.3.20)
builder (>= 2.1.2)
diff-lcs (>= 1.1.3)
gherkin (~> 2.12)
Expand All @@ -104,6 +113,8 @@ GEM
responders
thread_safe (~> 0.1)
warden (~> 1.2.3)
devise-async (0.10.1)
devise (~> 3.2)
diff-lcs (1.2.5)
dotenv (2.0.2)
dotenv-rails (2.0.2)
Expand All @@ -124,10 +135,12 @@ GEM
activesupport (>= 4.1.0)
hitimes (1.2.2)
i18n (0.7.0)
jbuilder (2.3.0)
jbuilder (2.3.1)
activesupport (>= 3.0.0, < 5)
multi_json (~> 1.2)
jquery-rails (4.0.3)
jmespath (1.0.2)
multi_json (~> 1.0)
jquery-rails (4.0.4)
rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
Expand All @@ -140,7 +153,7 @@ GEM
mime-types (2.6.1)
mini_portile (0.6.2)
minitest (5.7.0)
multi_json (1.11.1)
multi_json (1.11.2)
multi_test (0.1.2)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
Expand All @@ -149,7 +162,9 @@ GEM
mini_portile (~> 0.6.0)
orm_adapter (0.5.0)
pg (0.18.2)
rack (1.6.1)
rack (1.6.4)
rack-protection (1.5.3)
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.2.1)
Expand Down Expand Up @@ -184,11 +199,17 @@ GEM
redis (~> 3.0, >= 3.0.4)
responders (2.1.0)
railties (>= 4.2.0, < 5)
rspec-activejob (0.4.1)
activejob (>= 4.2)
rspec-mocks
rspec-core (3.2.3)
rspec-support (~> 3.2.0)
rspec-expectations (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-its (1.2.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
rspec-mocks (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
Expand All @@ -201,8 +222,8 @@ GEM
rspec-mocks (~> 3.2.0)
rspec-support (~> 3.2.0)
rspec-support (3.2.2)
sass (3.4.14)
sass-rails (5.0.2)
sass (3.4.16)
sass-rails (5.0.3)
railties (>= 4.0.0, < 5.0)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
Expand All @@ -219,6 +240,10 @@ GEM
json (~> 1.0)
redis (~> 3.2, >= 3.2.1)
redis-namespace (~> 1.5, >= 1.5.2)
sinatra (1.4.6)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
slim (3.0.6)
temple (~> 0.7.3)
tilt (>= 1.3.3, < 2.1)
Expand All @@ -231,7 +256,7 @@ GEM
spring (1.3.6)
sprockets (3.2.0)
rack (~> 1.0)
sprockets-rails (2.3.1)
sprockets-rails (2.3.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
Expand All @@ -258,7 +283,7 @@ GEM
raindrops (~> 0.7)
warden (1.2.3)
rack (>= 1.0)
web-console (2.1.2)
web-console (2.2.1)
activemodel (>= 4.0)
binding_of_caller (>= 0.7.2)
railties (>= 4.0)
Expand All @@ -271,6 +296,8 @@ PLATFORMS

DEPENDENCIES
apartment (~> 1.0.1)
apartment-sidekiq (~> 0.2.0)
aws-sdk (~> 2.1.7)
byebug
cancancan (~> 1.12.0)
capistrano (~> 3.4.0)
Expand All @@ -284,6 +311,7 @@ DEPENDENCIES
cucumber-rails (~> 1.4.2)
database_cleaner (~> 1.4.1)
devise (~> 3.5.1)
devise-async (~> 0.10.1)
dotenv-rails (~> 2.0.2)
factory_girl (~> 4.5.0)
factory_girl_rails (~> 4.0)
Expand All @@ -292,14 +320,21 @@ DEPENDENCIES
jquery-rails
pg (~> 0.18.2)
rails (= 4.2.1)
rspec-activejob (~> 0.4.1)
rspec-expectations (~> 3.2.1)
rspec-its (~> 1.2.0)
rspec-rails (~> 3.2.3)
sass-rails (~> 5.0)
sdoc (~> 0.4.0)
shoulda-matchers (~> 2.8.0)
sidekiq (~> 3.4.2)
sinatra (~> 1.4.6)
slim-rails (~> 3.0.1)
spring
turbolinks
uglifier (>= 1.3.0)
unicorn (~> 4.9.0)
web-console (~> 2.0)

BUNDLED WITH
1.10.3
12 changes: 10 additions & 2 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
rescue_from CanCan::AccessDenied do
redirect_to root_path
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_path, alert: exception.message
end

protected

# Helper method used in layout to render model errors, should be overriden in controllers
def errors
{}
end
helper_method :errors

end
30 changes: 30 additions & 0 deletions app/controllers/themes_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class ThemesController < ApplicationController
before_action :authenticate_user!
load_and_authorize_resource

# GET#index
def index
@themes = Theme.all
end

# GET#create_completed redirect from AWS
def create_completed
key = params.require(:key)
theme_file_name = key.sub(/[^_]*_/, '') # theme zip file name (theme name) is located after the first _ (underscore)
theme_name = File.basename theme_file_name, File.extname(theme_file_name)
theme = Theme.new name: theme_name, zip_file_url: key, status: :processing
redirect_to action: (theme.save ? 'index' : 'new')
if theme.errors.blank?
flash.notice = "Theme '#{theme_name}' uploaded successfully"
else
flash.alert = theme.errors.full_messages
end
end

# DELETE#destroy
def destroy
@theme.destroy
flash.notice = "Theme '#{@theme.name}' successfully deleted"
redirect_to themes_path
end
end
32 changes: 32 additions & 0 deletions app/helpers/themes_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module ThemesHelper
UPLOADS_FOLDER = 'uploads/'

def theme_upload_params
return @theme_upload_params if @theme_upload_params

bucket_name = Rails.application.config.aws_public_bucket_name
redirect_url = request.protocol + request.host_with_port + '/themes/create_completed'

@theme_upload_params = { form_action: "https://#{bucket_name}.s3.amazonaws.com/",
form_method: 'post',
form_enclosure_type: 'multipart/form-data',
acl: 'private',
redirect_url: redirect_url,
file_id: "#{UPLOADS_FOLDER}#{SecureRandom.uuid}_${filename}",
access_key: Rails.application.config.aws_access_key }

conditions = [[:eq, :$bucket, bucket_name],
[:eq, :$acl, :private],
[:"content-length-range", 1, Rails.application.config.aws_max_theme_zip_file_length],
[:"starts-with", :$key, UPLOADS_FOLDER],
[:eq, :$success_action_redirect, redirect_url]]
policy = { conditions: conditions, expiration: (Time.now + 10.hours).utc.iso8601 }
policy = Base64.strict_encode64(policy.to_json)

@theme_upload_params.merge! policy: policy
@theme_upload_params.merge! signature:
Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'),
Rails.application.config.aws_secret_access_key,
policy))
end
end
11 changes: 11 additions & 0 deletions app/jobs/delete_theme_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class DeleteThemeJob < ActiveJob::Base
queue_as :low_priority

rescue_from(Aws::S3::Errors::RequestTimeout) do
retry_job wait: 5.minutes, queue: :low_priority
end

def perform(zip_file_url, is_public_bucket)
AmazonAwsClient.try (is_public_bucket ? :delete_from_public_bucket : :delete_from_private_bucket), zip_file_url
end
end
12 changes: 12 additions & 0 deletions app/jobs/transfer_theme_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class TransferThemeJob < ActiveJob::Base
queue_as :default

rescue_from(Aws::S3::Errors::RequestTimeout) do
retry_job wait: 5.minutes, queue: :default
end

def perform(theme)
AmazonAwsClient.transfer_from_public_to_private_bucket theme.zip_file_url
theme.update! status: :uploaded
end
end
28 changes: 28 additions & 0 deletions app/libs/amazon_aws_client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module AmazonAwsClient
def self.client
credentials = Aws::Credentials.new Rails.application.config.aws_access_key, Rails.application.config.aws_secret_access_key
Aws::S3::Client.new region: Rails.application.config.aws_region, credentials: credentials
end

def self.transfer_from_public_to_private_bucket key
client = self.client
client.copy_object(bucket: Rails.application.config.aws_private_bucket_name,
key: key,
copy_source: Rails.application.config.aws_public_bucket_name + '/' + key)
client.delete_object bucket: Rails.application.config.aws_public_bucket_name, key: key
end

def self.delete_from_public_bucket key
self.delete_from_bucket Rails.application.config.aws_public_bucket_name, key
end

def self.delete_from_private_bucket key
self.delete_from_bucket Rails.application.config.aws_private_bucket_name, key
end

private

def self.delete_from_bucket bucket, key
self.client.delete_object bucket: bucket, key: key
end
end
4 changes: 4 additions & 0 deletions app/models/ability.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ def initialize(user)
can :destroy, User if user.role.can_delete_users?
can :update_users_role, User if user.role.can_update_users_role?
can :update_users_password, User if user.role.can_update_users_password?
can :read, Theme if user.role.can_create_themes? || user.role.can_delete_themes?
can :create, Theme if user.role.can_create_themes?
can :create_completed, Theme if user.role.can_create_themes?
can :destroy, Theme if user.role.can_delete_themes?
end
end
Loading