tb_core 1.3.5 → 1.3.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 06f0ab03560e57efe477e7fb0f9ae6f72a8a042c
4
- data.tar.gz: e8d702fe0332d78ae18bc9d0605db1d89ec3cb26
3
+ metadata.gz: f6bf453f0beae57a1071c09c8d17bb2af451d8f1
4
+ data.tar.gz: 24fcc7c6774cf0957886dd28675a5fa9fd8cdc6f
5
5
  SHA512:
6
- metadata.gz: 6b6d73ea8d50f6930b71df507147e5644128cd2a04024522984aed28fe1832dcc1e9e37059945c34e22a31b41747d9a914868af5eead68d5a466917bdd3b0a46
7
- data.tar.gz: 778f7e4d4a48508249c54cff93cdda5334a0beddf158e4a5b68eaab544e9cc6539a53b18fc8aa64480267b549a436cf2713f4d7b7344380a6a232ae815071a40
6
+ metadata.gz: 6e82de4ddd86404ab8a03bce734b7bc6a5f57e63e1528d9b9c4e58b687cb0eee48bb41f6921997463e68d7062bc09f76f52cd4b3bdfebb544ba75e3db32b33e5
7
+ data.tar.gz: ed7a6ac11107b0602eb0d21a50af16662657aa0462e7a288acb5f00c9dda9c78e364478d45e9d0b6a93438f2629fb7bb92a401df7a57da0978ddeca17586defe
@@ -1,5 +1,4 @@
1
1
  //= require jquery
2
- //= require jquery_ujs
3
2
  //= require tinymce-jquery
4
3
  //= require bootstrap-sprockets
5
4
  //= require ../../tb_core
@@ -1,3 +1,6 @@
1
+ //= require_self
2
+ //= require jquery_ujs
3
+
1
4
  (function(){
2
5
 
3
6
  /*
@@ -20,15 +23,17 @@ tb.remote = {
20
23
  $document.on('ajax:error', 'form[data-errors]', onRemoteFormErrors);
21
24
  $document.on('ajax:success', 'tr a[data-method=delete][data-remote=true]', onRemoteDeleteTableRow);
22
25
  $document.on('ajax:aborted:file', 'form', onRemoteAbortedFile);
26
+ $document.ready(extendEnableFormElementMethod);
23
27
  }
24
28
  };
25
29
 
26
30
  /*
27
31
  * UJS likes to request application/javascript by default, but Twice Baked prefers JSON.
28
32
  */
29
- var onRemoteFormBefore = function(xhr, settings){
30
- if($(this).data('type') === undefined){
31
- $(this).data('type', 'json');
33
+ var onRemoteFormBefore = function(event){
34
+ var $form = $(this);
35
+ if($form.data('type') === undefined){
36
+ $form.data('type', 'json');
32
37
  }
33
38
  };
34
39
 
@@ -97,7 +102,7 @@ var onRemoteFormErrors = function(event, jqXHR, textStatus, errorThrown){
97
102
  displayErrorsInline($form, jqXHR.responseJSON.errors);
98
103
  }
99
104
  else{
100
- displayErrorsAlert(jqXHR.responseJSON.full_messages);
105
+ displayErrorsAlert(jqXHR.responseJSON);
101
106
  }
102
107
  }
103
108
  else if(jqXHR.status == 401 || jqXHR.status == 403){
@@ -159,11 +164,15 @@ var displayErrorsInline = function($form, errors){
159
164
  /*
160
165
  * Display errors in a standard window.alert dialog
161
166
  */
162
- var displayErrorsAlert = function(errors){
167
+ var displayErrorsAlert = function(json){
163
168
  var text = "Please correct the following errors:\n";
164
- var len = errors.length;
165
- for(var i=0; i<len; i++){
166
- text += " - " + errors[i] + "\n";
169
+ var label, message;
170
+ var index = 0;
171
+ for(var key in json.errors){
172
+ label = json.labels[index];
173
+ message = json.errors[key][0];
174
+ text += " - " + label + ' ' + message + "\n";
175
+ index++;
167
176
  }
168
177
  window.alert(text);
169
178
  };
@@ -208,24 +217,26 @@ var onRemoteAbortedFile = function(event, inputs){
208
217
  * delay and a success text value to the button before returning to
209
218
  * default state.
210
219
  */
211
- var originalEnableFormElement = $.rails.enableFormElement;
212
-
213
- $.rails.enableFormElement = function(element){
214
- var success = $(element).parents('form').data('lastRemoteSuccess');
215
- var message = element.data('enableWith');
216
-
217
- if(success && message){
218
- var method = element.is('button') ? 'html' : 'val';
219
- element[method](message);
220
- setTimeout(function(){
221
- originalEnableFormElement(element);
222
- }, 1000);
223
- }
224
- else{
225
- originalEnableFormElement(element);
226
- }
220
+ var extendEnableFormElementMethod = function(){
221
+ var originalEnableFormElement = $.rails.enableFormElement;
222
+
223
+ $.rails.enableFormElement = function(element){
224
+ var success = $(element).parents('form').data('lastRemoteSuccess');
225
+ var message = element.data('enableWith');
226
+
227
+ if(success && message){
228
+ var method = element.is('button') ? 'html' : 'val';
229
+ element[method](message);
230
+ setTimeout(function(){
231
+ originalEnableFormElement(element);
232
+ }, 1000);
233
+ }
234
+ else{
235
+ originalEnableFormElement(element);
236
+ }
237
+ };
227
238
  };
228
239
 
229
- $(document).ready(tb.remote.init);
240
+ tb.remote.init();
230
241
 
231
242
  })();
@@ -4,7 +4,6 @@ class Admin::ApplicationController < Spud::ApplicationController
4
4
  add_breadcrumb "Dashboard", :admin_root_path
5
5
  layout 'admin/detail'
6
6
  respond_to :html, :json
7
- # self.responder = TbCore::Responder
8
7
 
9
8
  private
10
9
 
@@ -2,7 +2,7 @@ class Admin::RolesController < Admin::ApplicationController
2
2
 
3
3
  before_action :get_record, :only => [:show, :edit, :update, :destroy]
4
4
  respond_to :html, :json, :xml
5
- belongs_to_spud_app :users
5
+ belongs_to_app :users
6
6
  add_breadcrumb "Users", :admin_users_path
7
7
  add_breadcrumb "Roles", :admin_roles_path
8
8
 
@@ -14,14 +14,14 @@ class Admin::SettingsController < Admin::ApplicationController
14
14
  end
15
15
 
16
16
  def update
17
- if @current_user.update_attributes(user_params)
17
+ if check_password && @current_user.update_attributes(user_params)
18
18
  if user_params.include?(:password)
19
- SpudUserSession.create(@current_user)
19
+ SpudUserSession.create(@current_user)
20
20
  end
21
21
  flash[:notice] = "User settings saved successfully."
22
22
  respond_with @current_user, :location => admin_settings_path
23
23
  else
24
- render 'edit'
24
+ render 'edit', :status => 401
25
25
  end
26
26
  end
27
27
 
@@ -31,4 +31,16 @@ private
31
31
  params.require(:spud_user).permit(:login, :first_name, :last_name, :email, :password, :password_confirmation, :time_zone)
32
32
  end
33
33
 
34
+ def check_password
35
+ if params[:spud_user][:password].nil? || params[:spud_user][:password].empty?
36
+ return true
37
+ else
38
+ if !current_user.valid_password?(params[:current_password])
39
+ current_user.errors.add(:current_password, "is not correct. Please enter correct password.")
40
+ return false
41
+ end
42
+ return true
43
+ end
44
+ end
45
+
34
46
  end
@@ -1,7 +1,6 @@
1
1
  class Admin::UsersController < Admin::ApplicationController
2
2
 
3
- self.responder = TbCore::Responder
4
- belongs_to_spud_app :users
3
+ belongs_to_app :users
5
4
  add_breadcrumb "Users", :admin_users_path
6
5
  before_action :load_user, :only => [:edit, :update, :show, :destroy]
7
6
  after_action :send_credentials_email, :only => [:create, :update]
@@ -10,6 +10,8 @@ class Spud::ApplicationController < ActionController::Base
10
10
  include TbCore::ApplicationHelper
11
11
  before_action :set_mailer_default_url
12
12
 
13
+ self.responder = TbCore::Responder
14
+
13
15
  rescue_from Spud::RequestError, :with => :handle_request_error
14
16
  rescue_from ActiveRecord::RecordNotFound, :with => :handle_record_not_found
15
17
  rescue_from ActionController::UnknownFormat, :with => :handle_unknown_format_error
@@ -4,7 +4,6 @@
4
4
  skip_before_action :check_requires_password_change, :only => [:destroy, :change_password, :set_change_password]
5
5
 
6
6
  respond_to :html, :json, :js
7
- self.responder = TbCore::Responder
8
7
  layout 'user_sessions'
9
8
 
10
9
  def new
@@ -38,7 +38,14 @@
38
38
  <h4>Credentials</h4>
39
39
 
40
40
  <div class="form-group">
41
- <%= f.label :password, :class => "col-sm-2 control-label" %>
41
+ <%= f.label :current_password, :class => "col-sm-2 control-label" %>
42
+ <div class="col-sm-10">
43
+ <%= password_field :current_password, nil, class:"form-control" %>
44
+ <p class="help-block">Enter current password to change it.</p>
45
+ </div>
46
+ </div>
47
+ <div class="form-group">
48
+ <%= f.label "New Password", :class => "col-sm-2 control-label" %>
42
49
  <div class="col-sm-10">
43
50
  <%= f.password_field :password, :title => "", :class => 'form-control', :autocomplete => 'new-password' %>
44
51
  <p class="help-block">Password must be at least 8 characters</p>
@@ -1,6 +1,6 @@
1
1
  class Admin::<%= module_name_formatted.camelize%>Controller < Admin::ApplicationController
2
2
 
3
- belongs_to_spud_app :<%= module_name_formatted %>
3
+ belongs_to_app :<%= module_name_formatted %>
4
4
  add_breadcrumb "<%= module_name_formatted.humanize.titlecase %>", :admin_<%= module_name_formatted %>_path
5
5
  before_action :load_<%= module_name_formatted.singularize %>, :only => [:show, :edit, :update, :destroy]
6
6
 
@@ -1,5 +1,4 @@
1
1
  //= require jquery
2
- //= require jquery_ujs
3
2
  //= require tb_core
4
3
  //= require bootstrap_modules
5
4
  //= require_self
@@ -16,7 +16,6 @@ end
16
16
  module Spud
17
17
  module Core
18
18
  class Engine < ::Rails::Engine
19
- require "#{root}/lib/spud_core/belongs_to_app"
20
19
  require "#{root}/lib/spud_core/errors"
21
20
  require "#{root}/lib/spud_core/searchable"
22
21
  require "#{root}/lib/responds_to_parent"
@@ -26,7 +25,7 @@ module Spud
26
25
 
27
26
  initializer 'tb_core.controller_overrides' do |config|
28
27
  ActionController::Base.class_eval do
29
- include Spud::BelongsToApp
28
+ include TbCore::BelongsToApp
30
29
  end
31
30
  end
32
31
 
@@ -78,6 +77,10 @@ module Spud
78
77
  end
79
78
  end
80
79
 
80
+ initializer 'tb_core.assets' do
81
+ Rails.application.config.assets.precompile += ['admin/users_thumb.png', 'admin/module_icon.png']
82
+ end
83
+
81
84
  end
82
85
  end
83
86
  end
@@ -1,5 +1,5 @@
1
1
  module Spud
2
2
  module Core
3
- VERSION = "1.3.5"
3
+ VERSION = "1.3.6"
4
4
  end
5
5
  end
@@ -0,0 +1,55 @@
1
+ module TbCore::BelongsToApp
2
+ extend ActiveSupport::Concern
3
+
4
+ module ClassMethods
5
+ def belongs_to_spud_app(name, options={})
6
+ ActiveSupport::Deprecation.warn 'ApplicationController#belongs_to_spud_app is deprecated. Please use #belongs_to_app instead.', caller
7
+ belongs_to_app(name, page_title: options[:page_title])
8
+ end
9
+
10
+ # Adds a before action to the current controller to act like the specified twice baked app
11
+ #
12
+ # symbol: This should be the :key value for the app you want to use
13
+ # page_title: Override the base name value for the app (optional)
14
+ # only: An array of controller actions you want this to apply to (optional)
15
+ #
16
+ def belongs_to_app(name, page_title: nil, only: nil)
17
+ before_action ->(){
18
+ act_as_app(name, page_title: page_title)
19
+ }, :only => only
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ # Call the make the current controller behave as though it belongs to the specified twice baked app
26
+ #
27
+ # symbol: This should be the :key value for the app you want to use
28
+ # page_title: Override the base name value for the app (optional)
29
+ #
30
+ def act_as_app(symbol, page_title: nil)
31
+ @page_application = Spud::Core.admin_applications.find{ |app| app[:key] == symbol }
32
+ if @page_application.blank?
33
+ raise "Requested application '#{symbol}' could not be found"
34
+ elsif !current_user.can_view_app?(@page_application)
35
+ raise Spud::AccessDeniedError.new(:item => 'module', :template => '/layouts/admin/error_page')
36
+ end
37
+ @page_thumbnail = @page_application[:thumbnail]
38
+ @page_name = determine_page_name(page_title || @page_application[:name], action_name)
39
+ end
40
+
41
+ # Takes a base app name and controller action name and returns an appropriate page title
42
+ #
43
+ def determine_page_name(base_name, action_name)
44
+ if action_name == 'new' || action_name == 'create'
45
+ return "New #{base_name.singularize}"
46
+ elsif action_name == 'edit' || action_name == 'update'
47
+ return "Edit #{base_name.singularize}"
48
+ elsif action_name == 'show'
49
+ return "#{base_name.singularize} Detail"
50
+ else
51
+ return base_name
52
+ end
53
+ end
54
+
55
+ end
@@ -109,12 +109,16 @@ class TbCore::FormBuilder < ActionView::Helpers::FormBuilder
109
109
 
110
110
  # Builds a row of save/cancel buttons
111
111
  #
112
- def tb_save_buttons(model_name, cancel_path)
112
+ def tb_save_buttons(model_name, cancel_path, delete_path=nil)
113
113
  content_tag :div, :class => 'form-group' do
114
114
  content_tag :div, :class => 'col-sm-offset-2 col-sm-10' do
115
115
  concat submit "Save #{model_name}", :class => 'btn btn-primary', :data => {:disable_with => "Saving #{model_name}...", :enable_with => 'Saved!'}
116
116
  concat ' '
117
117
  concat @template.link_to 'Cancel', cancel_path, :class => 'btn btn-default', :data => {:dismiss => :modal}
118
+ if delete_path != nil
119
+ concat ' '
120
+ concat @template.link_to 'Delete', delete_path, :class => 'btn btn-danger', :data => {:confirm => "This action can't be undone. Would you like to delete the #{model_name.downcase}?"}, :method => :delete
121
+ end
118
122
  end
119
123
  end
120
124
  end
@@ -1,5 +1,14 @@
1
1
  module TbCore::Mysql2Extensions
2
- extend ActiveSupport::Concern
2
+
3
+ # Create a new table
4
+ #
5
+ def create_table(table_name, options = {})
6
+ if @connection.query_options[:encoding] == 'utf8mb4'
7
+ super(table_name, options.reverse_merge(:options => 'ROW_FORMAT=DYNAMIC ENGINE=InnoDB'))
8
+ else
9
+ super
10
+ end
11
+ end
3
12
 
4
13
  # Build a hash of length options for a given table and column name
5
14
  #
@@ -23,10 +23,13 @@ class TbCore::Responder < ActionController::Responder
23
23
  end
24
24
 
25
25
  # Default responder only sends the basic errors array
26
- # This override also sends the full messages for convenience
26
+ # This override also sends the translated labels for convenience
27
27
  #
28
28
  def json_resource_errors
29
- return {:errors => resource.errors, :full_messages => resource.errors.full_messages}
29
+ return {
30
+ :errors => resource.errors,
31
+ :labels => resource.errors.keys.collect{ |attribute| resource.class.human_attribute_name(attribute) }
32
+ }
30
33
  end
31
34
 
32
35
  end
@@ -13,6 +13,13 @@ describe Admin::SettingsController, :type => :controller do
13
13
  end
14
14
 
15
15
  describe 'update' do
16
+ it "should give an error if password change does not include a valid current password" do
17
+ u = FactoryGirl.build(:spud_user)
18
+ u.password = "test"
19
+ put :update, :spud_user => {:first_name => "Mike", :password => "Imapassword", :current_password => "ImaTest"}
20
+ is_expected.to respond_with 401
21
+ end
22
+
16
23
  it "should redirect to the settings page with a successful update" do
17
24
  put :update, :spud_user => {:first_name => "Mike"}
18
25
  expect(response).to redirect_to(admin_settings_path)
@@ -1,5 +1,4 @@
1
1
  //= require jquery
2
- //= require jquery_ujs
3
2
  //= require tb_core
4
3
  //= require bootstrap-sprockets
5
4
  //= require_self
@@ -0,0 +1,67 @@
1
+ require 'rails_helper'
2
+
3
+ class DummyController < ActionController::Base
4
+ attr_accessor :current_user
5
+ end
6
+
7
+ describe TbCore::BelongsToApp do
8
+
9
+ let(:controller){
10
+ DummyController.new()
11
+ }
12
+
13
+ before(:each) do
14
+
15
+ end
16
+
17
+ describe '.belongs_to_app' do
18
+ it 'should add a before_action' do
19
+ # Not sure how to test for this...
20
+ DummyController.belongs_to_app(:users)
21
+ end
22
+ end
23
+
24
+ describe '#acts_as_app' do
25
+ it 'should configure the app' do
26
+ controller.current_user = FactoryGirl.create(:spud_user, :super_admin => true)
27
+ controller.send(:act_as_app, :users)
28
+ expect(controller.instance_variable_get('@page_application')).to be_a(Hash)
29
+ end
30
+
31
+ it 'should raise an error if the app cannot be found' do
32
+ expect{
33
+ controller.send(:act_as_app, :fail)
34
+ }.to raise_error
35
+ end
36
+
37
+ it 'should raise an error if the user does not have access' do
38
+ controller.current_user = FactoryGirl.create(:spud_user, :super_admin => false)
39
+ expect{
40
+ controller.send(:act_as_app, :users)
41
+ }.to raise_error(Spud::AccessDeniedError)
42
+ end
43
+ end
44
+
45
+ describe '#determine_page_name' do
46
+ it 'should contain "New"' do
47
+ result = controller.send(:determine_page_name, 'Users', 'new')
48
+ expect(result).to eq('New User')
49
+ end
50
+
51
+ it 'should contain "Edit"' do
52
+ result = controller.send(:determine_page_name, 'Users', 'edit')
53
+ expect(result).to eq('Edit User')
54
+ end
55
+
56
+ it 'should contain "Detail"' do
57
+ result = controller.send(:determine_page_name, 'Users', 'show')
58
+ expect(result).to eq('User Detail')
59
+ end
60
+
61
+ it 'should return the base name' do
62
+ result = controller.send(:determine_page_name, 'Users', 'other')
63
+ expect(result).to eq('Users')
64
+ end
65
+ end
66
+
67
+ end
@@ -6,6 +6,19 @@ describe TbCore::Mysql2Extensions do
6
6
  SpudUser.connection
7
7
  }
8
8
 
9
+ describe '#create_table' do
10
+ before(:each){
11
+ allow_any_instance_of(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter).to receive(:create_table) do |abstract_adapter, table_name, arguments|
12
+ arguments[:options]
13
+ end
14
+ }
15
+
16
+ it 'should pass the dynamic option' do
17
+ options = adapter.create_table(:tests)
18
+ expect(options).to match('ROW_FORMAT=DYNAMIC')
19
+ end
20
+ end
21
+
9
22
  describe '#length_options_for_utf8mb4_string_index' do
10
23
  it 'should return a hash with a single value' do
11
24
  options = adapter.length_options_for_utf8mb4_string_index(:spud_users, :first_name)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tb_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Woods
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-12 00:00:00.000000000 Z
11
+ date: 2016-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -410,7 +410,6 @@ files:
410
410
  - lib/generators/spud/templates/views/layouts/application.html.erb
411
411
  - lib/generators/spud/templates/views/layouts/error_page.html.erb
412
412
  - lib/responds_to_parent.rb
413
- - lib/spud_core/belongs_to_app.rb
414
413
  - lib/spud_core/catch_all_route.rb
415
414
  - lib/spud_core/configuration.rb
416
415
  - lib/spud_core/engine.rb
@@ -420,6 +419,7 @@ files:
420
419
  - lib/spud_core/version.rb
421
420
  - lib/tasks/spud_core_tasks.rake
422
421
  - lib/tb_core.rb
422
+ - lib/tb_core/belongs_to_app.rb
423
423
  - lib/tb_core/form_builder.rb
424
424
  - lib/tb_core/mysql2_extensions.rb
425
425
  - lib/tb_core/responder.rb
@@ -478,6 +478,7 @@ files:
478
478
  - spec/factories/spud_user_factories.rb
479
479
  - spec/helpers/spud/admin/application_helper_spec.rb
480
480
  - spec/lib/spud_core/configuration_spec.rb
481
+ - spec/lib/tb_core/belongs_to_app_spec.rb
481
482
  - spec/lib/tb_core/mysql2_extensions_spec.rb
482
483
  - spec/models/spud_role_spec.rb
483
484
  - spec/models/spud_user_spec.rb
@@ -561,6 +562,7 @@ test_files:
561
562
  - spec/factories/spud_user_factories.rb
562
563
  - spec/helpers/spud/admin/application_helper_spec.rb
563
564
  - spec/lib/spud_core/configuration_spec.rb
565
+ - spec/lib/tb_core/belongs_to_app_spec.rb
564
566
  - spec/lib/tb_core/mysql2_extensions_spec.rb
565
567
  - spec/models/spud_role_spec.rb
566
568
  - spec/models/spud_user_spec.rb
@@ -1,46 +0,0 @@
1
- module Spud::BelongsToApp
2
- extend ActiveSupport::Concern
3
-
4
- included do
5
- extend ClassMethods
6
- end
7
-
8
- module ClassMethods
9
- def belongs_to_spud_app(name=nil,options={})
10
- @page_title = options[:page_title]
11
- Spud::Core.admin_applications.each do |app|
12
- if app[:key] == name
13
- @page_application = app
14
- break
15
- end
16
- end
17
- self.class_eval do
18
- before_action do |controller|
19
- @page_thumbnail = self.class.page_application[:thumbnail]
20
- @application_name = self.class.page_application[:name]
21
- @page_name = self.class.page_title
22
-
23
- if !current_user.can_view_app?(self.class.page_application)
24
- raise Spud::AccessDeniedError.new(:item => 'module', :template => '/layouts/admin/error_page')
25
- end
26
-
27
- if controller.action_name == 'new' || controller.action_name == 'create'
28
- @page_name = "New #{@page_name.singularize}"
29
- elsif controller.action_name == 'edit' || controller.action_name == 'update'
30
- @page_name = "Edit #{@page_name.singularize}"
31
- elsif controller.action_name == 'show'
32
- @page_name = "#{@page_name.singularize} Detail"
33
- end
34
- end
35
- end
36
- end
37
-
38
- def page_application
39
- @page_application || self.superclass.instance_variable_get('@page_application')
40
- end
41
-
42
- def page_title
43
- @page_title || self.superclass.instance_variable_get('@page_title') || page_application[:name]
44
- end
45
- end
46
- end