spree_devices 1.2.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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +1 -0
  4. data/.rubocop +2 -0
  5. data/.rubocop.yml +37 -0
  6. data/.ruby-gemset +1 -0
  7. data/.ruby-version +1 -0
  8. data/Gemfile +17 -0
  9. data/Gemfile.lock +402 -0
  10. data/Jenkinsfile +68 -0
  11. data/LICENSE +26 -0
  12. data/README.md +33 -0
  13. data/Rakefile +21 -0
  14. data/app/assets/javascripts/spree/backend/spree_devices.js +2 -0
  15. data/app/assets/javascripts/spree/frontend/spree_devices.js +2 -0
  16. data/app/assets/stylesheets/spree/backend/spree_devices.css +4 -0
  17. data/app/assets/stylesheets/spree/frontend/spree_devices.css +4 -0
  18. data/app/controllers/spree/api/base_controller_decorator.rb +24 -0
  19. data/app/controllers/spree/api/v1/devices_controller.rb +24 -0
  20. data/app/controllers/spree/devices_controller.rb +22 -0
  21. data/app/models/spree/device.rb +6 -0
  22. data/app/models/spree/user_decorator.rb +4 -0
  23. data/app/models/spree/user_device.rb +17 -0
  24. data/app/overrides/spree/users/show/add_devices_to_account_my_orders.html.erb.deface +2 -0
  25. data/app/services/spree/device_service.rb +36 -0
  26. data/app/views/spree/api/v1/devices/index.v1.rabl +2 -0
  27. data/app/views/spree/api/v1/devices/show.v1.rabl +2 -0
  28. data/app/views/spree/api/v1/shared/error.v1.rabl +5 -0
  29. data/app/views/spree/devices/index.html.erb +20 -0
  30. data/bin/rails +7 -0
  31. data/config/locales/ar.yml +3 -0
  32. data/config/locales/en.yml +6 -0
  33. data/config/routes.rb +11 -0
  34. data/db/migrate/20160317153123_create_devices.rb +9 -0
  35. data/db/migrate/20160317154122_create_user_devices.rb +9 -0
  36. data/db/migrate/20160321135103_rename_device_code_to_device_uid.rb +5 -0
  37. data/db/migrate/20160511093138_rename_devices_tables.rb +6 -0
  38. data/lib/generators/spree_devices/install/install_generator.rb +33 -0
  39. data/lib/spree_devices.rb +5 -0
  40. data/lib/spree_devices/engine.rb +31 -0
  41. data/lib/spree_devices/engine_factories/device_factory.rb +6 -0
  42. data/lib/spree_devices/engine_factories/user_device_factory.rb +6 -0
  43. data/lib/spree_devices/factories.rb +5 -0
  44. data/spec/api/v1/devices_spec.rb +96 -0
  45. data/spec/api/v1/products_spec.rb +33 -0
  46. data/spec/controllers/devices_controller_spec.rb +50 -0
  47. data/spec/spec_helper.rb +97 -0
  48. data/spec/support/devices_api.rb +22 -0
  49. data/spec/utils/rubocop_spec.rb +8 -0
  50. data/spree_devices.gemspec +26 -0
  51. metadata +215 -0
data/Jenkinsfile ADDED
@@ -0,0 +1,68 @@
1
+ pipeline {
2
+
3
+ agent {
4
+ docker {
5
+ image 'repository.ingemark.com/ingemark/spree-extensions-build-container:0.0.1'
6
+ args "-u root"
7
+ }
8
+ }
9
+
10
+ triggers {
11
+ pollSCM 'H/2 * * * *'
12
+ }
13
+
14
+ options {
15
+ ansiColor('xterm')
16
+ buildDiscarder(logRotator(numToKeepStr: '10'))
17
+ disableConcurrentBuilds()
18
+ timeout(time: 1, unit: 'HOURS')
19
+ }
20
+
21
+ stages {
22
+ stage("Bundle install") {
23
+ steps {
24
+ sh 'bundle install'
25
+ }
26
+ }
27
+
28
+ stage("Rake test") {
29
+ steps {
30
+ sh 'rake test_app'
31
+
32
+ }
33
+ }
34
+
35
+ stage("Run tests") {
36
+ steps {
37
+ sh 'rspec'
38
+
39
+ }
40
+ }
41
+
42
+ stage("GEM build") {
43
+ steps {
44
+ sh "gem build spree_devices.gemspec 2>&1 | grep File | awk '{ print \$2 }' > output.txt"
45
+ }
46
+ }
47
+
48
+ stage("Deploy to GemInaBox") {
49
+ steps {
50
+ script {
51
+ env.FILENAME = readFile 'output.txt'
52
+ }
53
+
54
+ sh 'gem push "${env.FILENAME}" http://razvoj.local.ingemark.com:9292'
55
+ }
56
+ }
57
+ }
58
+
59
+ post {
60
+ changed {
61
+ mail(
62
+ to: "alen.basic@ingemark.com",
63
+ subject: "Job '${JOB_NAME}' build ${BUILD_DISPLAY_NAME} status has changed to : ${currentBuild.currentResult}!",
64
+ body: "Please go to ${BUILD_URL} for details."
65
+ )
66
+ }
67
+ }
68
+ }
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2016 [name of plugin creator]
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ SpreeDevices
2
+ ============
3
+
4
+ Introduction goes here.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Add spree_devices to your Gemfile:
10
+
11
+ ```ruby
12
+ gem 'spree_devices'
13
+ ```
14
+
15
+ Bundle your dependencies and run the installation generator:
16
+
17
+ ```shell
18
+ bundle
19
+ bundle exec rails g spree_devices:install
20
+ ```
21
+
22
+ Testing
23
+ -------
24
+
25
+ Before starting tests you need to generate testing_app
26
+ ```shell
27
+ bundle exec rake test_app
28
+ ```
29
+
30
+
31
+
32
+
33
+ Copyright (c) 2016 [Matej Minažek], released under the New BSD License
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default do
10
+ if Dir['spec/dummy'].empty?
11
+ Rake::Task[:test_app].invoke
12
+ Dir.chdir('../../')
13
+ end
14
+ Rake::Task[:spec].invoke
15
+ end
16
+
17
+ desc 'Generates a dummy app for testing'
18
+ task :test_app do
19
+ ENV['LIB_NAME'] = 'spree_devices'
20
+ Rake::Task['extension:test_app'].invoke
21
+ end
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js'
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
4
+ */
@@ -0,0 +1,24 @@
1
+ Spree::Api::BaseController.class_eval do
2
+ before_action :check_device
3
+
4
+ private
5
+
6
+ def check_device
7
+ return unless current_api_user
8
+ return unless mobile?
9
+
10
+ device_uid = request.headers['Device-Uid']
11
+ user_device = device_service.find_user_device(current_api_user, device_uid)
12
+
13
+ user_device.touch && return if user_device.present? # rubocop:disable Rails/SkipsModelValidations
14
+ raise CanCan::AccessDenied
15
+ end
16
+
17
+ def mobile?
18
+ request.headers['X-OS'] =~ /iOS|Android/i
19
+ end
20
+
21
+ def device_service
22
+ Spree::DeviceService.instance
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ class Spree::Api::V1::DevicesController < Spree::Api::BaseController
2
+ skip_before_action :check_device, only: :create
3
+ before_action :set_user
4
+
5
+ def create
6
+ @resource = device_service.find_or_create_user_device(@user, params[:name], params[:uid])
7
+
8
+ if @resource.errors.any?
9
+ render 'spree/api/errors/invalid_resource', status: 422
10
+ else
11
+ head :ok
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def set_user
18
+ @user = current_api_user
19
+ end
20
+
21
+ def device_service
22
+ Spree::DeviceService.instance
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ class Spree::DevicesController < Spree::BaseController
2
+ before_action :set_user
3
+
4
+ def index
5
+ @user_devices = @user.user_devices
6
+ end
7
+
8
+ def destroy
9
+ device_service.destroy_user_device(@user, params[:id])
10
+ redirect_to devices_path
11
+ end
12
+
13
+ private
14
+
15
+ def set_user
16
+ @user = spree_current_user
17
+ end
18
+
19
+ def device_service
20
+ Spree::DeviceService.instance
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ class Spree::Device < ApplicationRecord
2
+ has_many :user_devices, dependent: :destroy
3
+
4
+ validates :name, presence: true
5
+ validates :uid, presence: true
6
+ end
@@ -0,0 +1,4 @@
1
+ Spree::User.class_eval do
2
+ has_many :user_devices, dependent: :destroy
3
+ has_many :devices, through: :user_devices
4
+ end
@@ -0,0 +1,17 @@
1
+ class Spree::UserDevice < ApplicationRecord
2
+ belongs_to :device
3
+ belongs_to :user
4
+
5
+ validates :user, presence: true
6
+ validates_associated :device
7
+ validate :device_limit
8
+
9
+ private
10
+
11
+ def device_limit
12
+ return if user.blank?
13
+ return unless new_record?
14
+ max_number_of_devices = SpreeDevices.config.try(:max_number_of_devices) || 3
15
+ errors.add(:device, I18n.t('errors.device_limit_reached')) if user.devices.count >= max_number_of_devices
16
+ end
17
+ end
@@ -0,0 +1,2 @@
1
+ <!-- insert_after "[data-hook='account_my_orders']" -->
2
+ <h3><%= link_to 'Devices', devices_path %></h3>
@@ -0,0 +1,36 @@
1
+ module Spree
2
+ class DeviceService
3
+ include Singleton
4
+
5
+ def find_or_create_user_device(user, name, uid)
6
+ user_device = find_user_device(user, uid)
7
+ return user_device if user_device.present?
8
+
9
+ create_user_device(user, name, uid)
10
+ end
11
+
12
+ def destroy_user_device(user, device_id)
13
+ device = Spree::Device.find(device_id)
14
+ user_device = Spree::UserDevice.where(user: user, device: device).first
15
+ user_device.destroy if user_device.present?
16
+ device.destroy if device.user_devices.count.zero?
17
+ end
18
+
19
+ def find_user_device(user, uid)
20
+ Spree::UserDevice.joins(:device)
21
+ .where('spree_user_devices.user_id = ?', user.id)
22
+ .where('spree_devices.uid = ?', uid).first
23
+ end
24
+
25
+ private
26
+
27
+ def create_user_device(user, name, uid)
28
+ device = Spree::Device.where(name: name, uid: uid).first_or_initialize
29
+ user_device = Spree::UserDevice.new(user: user, device: device)
30
+
31
+ user_device.save
32
+
33
+ user_device
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,2 @@
1
+ collection @devices
2
+ attributes :id, :name, :code
@@ -0,0 +1,2 @@
1
+ object @device
2
+ attributes :id, :name, :code
@@ -0,0 +1,5 @@
1
+ object @error
2
+
3
+ node :error do |error|
4
+ { code: error.code, description: error.description }
5
+ end
@@ -0,0 +1,20 @@
1
+ <h3>Connected devices</h3>
2
+
3
+ <table class="table">
4
+ <tr>
5
+ <th>Device name</th>
6
+ <th>Device uid</th>
7
+ <th>Connected</th>
8
+ <th>Last access</th>
9
+ <th>Actions</th>
10
+ </tr>
11
+ <% @user_devices.each do |user_device| %>
12
+ <tr>
13
+ <td><%= user_device.device.name %></td>
14
+ <td><%= user_device.device.uid %></td>
15
+ <td><%= user_device.created_at %></td>
16
+ <td><%= user_device.updated_at %></td>
17
+ <td><%= link_to 'Remove', device_path(id: user_device.device.id), method: 'delete' %></td>
18
+ </tr>
19
+ <% end %>
20
+ </table>
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_devices/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,3 @@
1
+ ar:
2
+ errors:
3
+ device_limit_reached: "AR Maximum allowed number of devices limit reached"
@@ -0,0 +1,6 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ errors:
6
+ device_limit_reached: "Maximum allowed number of devices limit reached"
data/config/routes.rb ADDED
@@ -0,0 +1,11 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ # Add your extension routes here
3
+
4
+ namespace :api, defaults: { format: 'json' } do
5
+ namespace :v1 do
6
+ resources :devices, only: [:create]
7
+ end
8
+ end
9
+
10
+ resources :devices, only: %i[index destroy]
11
+ end
@@ -0,0 +1,9 @@
1
+ class CreateDevices < ActiveRecord::Migration[4.2]
2
+ def change
3
+ create_table :devices do |t|
4
+ t.string :name
5
+ t.string :code
6
+ t.timestamps null: false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class CreateUserDevices < ActiveRecord::Migration[4.2]
2
+ def change
3
+ create_table :user_devices do |t|
4
+ t.integer :user_id
5
+ t.integer :device_id
6
+ t.timestamps null: false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class RenameDeviceCodeToDeviceUid < ActiveRecord::Migration[4.2]
2
+ def change
3
+ rename_column :devices, :code, :uid
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class RenameDevicesTables < ActiveRecord::Migration[4.2]
2
+ def change
3
+ rename_table :devices, :spree_devices
4
+ rename_table :user_devices, :spree_user_devices
5
+ end
6
+ end
@@ -0,0 +1,33 @@
1
+ module SpreeDevices
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ class_option :auto_run_migrations, type: :boolean, default: false
5
+
6
+ def add_javascripts
7
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/spree_devices\n"
8
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/spree_devices\n"
9
+ end
10
+
11
+ def add_stylesheets
12
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css',
13
+ " *= require spree/frontend/spree_devices\n", before: %r{\*/}, verbose: true
14
+ inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css',
15
+ " *= require spree/backend/spree_devices\n", before: %r{\*/}, verbose: true
16
+ end
17
+
18
+ def add_migrations
19
+ run 'bundle exec rake railties:install:migrations FROM=spree_devices'
20
+ end
21
+
22
+ def run_migrations
23
+ run_migrations = options[:auto_run_migrations] ||
24
+ ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
25
+ if run_migrations
26
+ run 'bundle exec rake db:migrate'
27
+ else
28
+ Rails.logger 'Skipping rake db:migrate, don\'t forget to run it!'
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end