resource_quotable 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/Changelog.md +17 -0
  3. data/MIT-LICENSE +20 -0
  4. data/Rakefile +18 -0
  5. data/Readme.md +206 -0
  6. data/app/assets/config/resource_quotable_manifest.js +1 -0
  7. data/app/assets/stylesheets/resource_quotable/application.css +15 -0
  8. data/app/controllers/resource_quotable/application_controller.rb +15 -0
  9. data/app/controllers/resource_quotable/quota_controller.rb +106 -0
  10. data/app/controllers/resource_quotable/quotum_trackers_controller.rb +23 -0
  11. data/app/models/resource_quotable/application_record.rb +7 -0
  12. data/app/models/resource_quotable/quotum.rb +46 -0
  13. data/app/models/resource_quotable/quotum_tracker.rb +60 -0
  14. data/app/services/resource_quotable/action_services/base.rb +23 -0
  15. data/app/services/resource_quotable/action_services/check.rb +19 -0
  16. data/app/services/resource_quotable/action_services/check_multiple.rb +23 -0
  17. data/app/services/resource_quotable/action_services/increment.rb +18 -0
  18. data/app/services/resource_quotable/action_services/increment_multiple.rb +22 -0
  19. data/app/services/resource_quotable/base.rb +24 -0
  20. data/app/services/resource_quotable/create.rb +29 -0
  21. data/app/services/resource_quotable/destroy.rb +14 -0
  22. data/app/services/resource_quotable/quotum_tracker_services/reset.rb +17 -0
  23. data/app/services/resource_quotable/reset/all.rb +16 -0
  24. data/app/services/resource_quotable/reset/any.rb +16 -0
  25. data/app/services/resource_quotable/reset/base.rb +22 -0
  26. data/app/services/resource_quotable/reset/daily.rb +16 -0
  27. data/app/services/resource_quotable/reset/monthly.rb +16 -0
  28. data/app/services/resource_quotable/reset/weekly.rb +16 -0
  29. data/app/services/resource_quotable/reset/yearly.rb +16 -0
  30. data/app/services/resource_quotable/update.rb +23 -0
  31. data/app/views/layouts/resource_quotable/application.html.erb +15 -0
  32. data/app/views/resource_quotable/quota/_edit.html.erb +11 -0
  33. data/app/views/resource_quotable/quota/_index.html.erb +43 -0
  34. data/app/views/resource_quotable/quota/_new.html.erb +34 -0
  35. data/app/views/resource_quotable/quota/_show.html.erb +41 -0
  36. data/app/views/resource_quotable/quota/create.js.erb +3 -0
  37. data/app/views/resource_quotable/quota/destroy.js.erb +3 -0
  38. data/app/views/resource_quotable/quota/edit.html.erb +1 -0
  39. data/app/views/resource_quotable/quota/edit.js.erb +1 -0
  40. data/app/views/resource_quotable/quota/index/_row.html.erb +3 -0
  41. data/app/views/resource_quotable/quota/index/_row_content.html.erb +43 -0
  42. data/app/views/resource_quotable/quota/index.html.erb +1 -0
  43. data/app/views/resource_quotable/quota/index.js.erb +1 -0
  44. data/app/views/resource_quotable/quota/new.html.erb +1 -0
  45. data/app/views/resource_quotable/quota/new.js.erb +1 -0
  46. data/app/views/resource_quotable/quota/show/_row.html.erb +3 -0
  47. data/app/views/resource_quotable/quota/show/_row_content.html.erb +7 -0
  48. data/app/views/resource_quotable/quota/show.html.erb +1 -0
  49. data/app/views/resource_quotable/quota/show.js.erb +1 -0
  50. data/app/views/resource_quotable/quota/update.js.erb +3 -0
  51. data/app/views/resource_quotable/quotum_trackers/index/_row_content.html.erb +8 -0
  52. data/app/views/resource_quotable/quotum_trackers/reset.js.erb +3 -0
  53. data/config/routes.rb +11 -0
  54. data/db/migrate/20220805102601_create_resource_quotable_quota.rb +17 -0
  55. data/db/migrate/20220811072023_create_resource_quotable_quotum_trackers.rb +18 -0
  56. data/lib/concerns/controllers/allowed_to_manage_quota_check.rb +73 -0
  57. data/lib/concerns/models/act_as_quota_trackable.rb +23 -0
  58. data/lib/concerns/models/act_as_quotable.rb +19 -0
  59. data/lib/resource_quotable/engine.rb +13 -0
  60. data/lib/resource_quotable/exeptions.rb +9 -0
  61. data/lib/resource_quotable/generators/views_generator.rb +18 -0
  62. data/lib/resource_quotable/helper.rb +27 -0
  63. data/lib/resource_quotable/version.rb +5 -0
  64. data/lib/resource_quotable.rb +68 -0
  65. data/lib/tasks/resource_quotable_tasks.rake +5 -0
  66. metadata +322 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8ebb826f39ace180d8f32e12d12ae50ab90a8b2deefe5f19e156810a5ea99636
4
+ data.tar.gz: cd2009f815c64a62f51a03a3977a0bfc5d53acbacfe91da5d839b2007e74ee27
5
+ SHA512:
6
+ metadata.gz: ba541c1da670b1d167bc313399e32c63cfb3858a37072d3ea169a368f1b5e11a813d2c0f5f6e13054afbc6bae72727d5c067fa570c53bafc8108f734fddbbf25
7
+ data.tar.gz: 6896c4c58ed19679d083243c3cead8419684d73703c50eb52ab634fb78f0a21047e4668a804e3c2be0e0c3a9005169abdda8a7ab3dd945beead747e9a67d042c
data/Changelog.md ADDED
@@ -0,0 +1,17 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/).
6
+
7
+ ## [0.2.0] (unreleased)
8
+ ### Changed
9
+ - Change Quota system to allow user group configuration.
10
+
11
+ ## [0.1.0] (1/9/22)
12
+ ### Changed
13
+ - Quota system by user. (alpha version available in branch `by_user`)
14
+
15
+ ## [0.0.0] (4/8/22)
16
+ ### Changed
17
+ - Initial repo creation.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+
5
+ APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
6
+ load 'rails/tasks/engine.rake'
7
+
8
+ load 'rails/tasks/statistics.rake'
9
+
10
+ require 'bundler/gem_tasks'
11
+
12
+ require 'rspec/core'
13
+ require 'rspec/core/rake_task'
14
+
15
+ desc 'Run all specs in spec directory (excluding plugin specs)'
16
+ RSpec::Core::RakeTask.new(spec: 'app:db:test:prepare')
17
+
18
+ task default: :spec
data/Readme.md ADDED
@@ -0,0 +1,206 @@
1
+ # ResourceQuotable
2
+ A Rails quota limit gem for resources. UNDER DEVELOPMENT
3
+
4
+ ## Installation
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'resource_quotable'
9
+ ```
10
+
11
+ And then execute:
12
+ ```bash
13
+ $ bundle install
14
+ ```
15
+
16
+ Install migrations:
17
+ ```bash
18
+ $ rails resource_quotable:install:migrations
19
+ $ rails db:migrate
20
+ ```
21
+
22
+ Mount engine:
23
+ ```ruby
24
+ # config/routes.rb
25
+ Rails.application.routes.draw do
26
+ # ...
27
+ mount ResourceQuotable::Engine => '/resource_quotable'
28
+ # ...
29
+ end
30
+
31
+ ```
32
+
33
+ Configure:
34
+ ```ruby
35
+ # config/initializers/resource_quotable.rb
36
+
37
+ ResourceQuotable.setup do |config|
38
+
39
+ ##
40
+ # Mandatory settings
41
+ #
42
+ # Resources to track quota.
43
+ # format: Array of strings. Could be anything.
44
+ #
45
+ config.resources = %w[ResourceA ResourceB NotModel]
46
+
47
+ ##
48
+ # Optional settings
49
+
50
+ # Method to access group form user instance.
51
+ # default: 'group'
52
+ config.group_method = 'user_group'
53
+
54
+ # Method to access users form group instance.
55
+ # default: 'users'
56
+ config.users_method = 'admin_users'
57
+
58
+ # main_content ID for rendering.
59
+ # default: 'resource_quotable_content'
60
+ config.main_content = 'resource_quotable_content'
61
+
62
+ # Base controller.
63
+ # default: '::ApplicationController'
64
+ config.base_controller = '::ApplicationController'
65
+
66
+ # Actions
67
+ # Default [:create,:update, :destroy]
68
+ config.actions = {
69
+ create: 0,
70
+ update: 1,
71
+ destroy: 2,
72
+ send: 3
73
+ }.freeze
74
+
75
+ end
76
+ ```
77
+
78
+ Attach Quotable to model.
79
+
80
+ ```ruby
81
+ class User < ApplicationRecord
82
+ acts_as_quota_trackable
83
+ # ....
84
+ belongs_to :group
85
+ # ....
86
+ end
87
+
88
+ class Group < ApplicationRecord
89
+ acts_as_quotable
90
+ # ....
91
+ has_many :users, dependent: :destroy
92
+ # ....
93
+ end
94
+ ```
95
+
96
+ ## Usage
97
+
98
+ ```erb
99
+ <% if allowed_to? :create, 'Post' %>
100
+ <%= link_to "New", new_post_path %>
101
+ <% end %>
102
+ ```
103
+
104
+ ```ruby
105
+ class PostController < ApplicationController
106
+ # ...
107
+
108
+ def new
109
+ quota_authorize! :create, 'Post'
110
+ # ...
111
+ end
112
+
113
+ def create
114
+ quota_increment! :create, 'Post'
115
+ # ...
116
+ end
117
+
118
+ # ...
119
+ end
120
+ ```
121
+
122
+ ## Customizations
123
+
124
+ Customize views
125
+
126
+ `rails g resource_quotable:views`
127
+
128
+ Customize Controllers
129
+
130
+ ```ruby
131
+ class ApplicationController < ActionController::Base
132
+ # ...
133
+
134
+ # Customize how to get the current user model to track
135
+ # default: current_user
136
+ def load_quotable_tracker_user
137
+ # ...
138
+ end
139
+
140
+ # Customize how to retrieve the group model
141
+ # default: quotum_params[:group_type].constantize.find(quotum_params[:group_id])
142
+ def load_quotable_group
143
+ # ...
144
+ end
145
+
146
+ # Customize if the current_user can access to the quota management interface
147
+ # default: true
148
+ def allowed_to_manage_quota?
149
+ # ...
150
+ end
151
+
152
+ # Customize How Quotum model are retrieve/filter. Useful for scopes
153
+ # default: Quotum
154
+ def quota_scoped
155
+ # ...
156
+ end
157
+
158
+ # hook before every action
159
+ # default: nil
160
+ def resource_quotable_before
161
+ # ...
162
+ end
163
+
164
+ # hook after every action
165
+ # default: nil
166
+ def resource_quotable_after
167
+ # ...
168
+ end
169
+
170
+ # ...
171
+ end
172
+ ```
173
+
174
+ ## API
175
+
176
+ Still Working on this doc....
177
+
178
+ API is exposed as a services layer.
179
+
180
+ ```ruby
181
+
182
+ # Check quota for 20 actions on resource for this user
183
+ ResourceQuotable::ActionServices::CheckMultiple.call(user: user, resource: 'ResourceX', action: :create, amount: 20)
184
+ # Increment 20 quota for actions on resource for this user
185
+ ResourceQuotable::ActionServices::IncrementMultiple.call(user: user, resource: 'ResourceX', action: :create, amount: 20)
186
+
187
+ # Reset. Probably a good idea to have a cron job that call this.
188
+ ResourceQuotable::Reset::Any.call
189
+ ResourceQuotable::Reset::Yearly.call
190
+ ResourceQuotable::Reset::Monthly.call
191
+ ResourceQuotable::Reset::Weekly.call
192
+ ResourceQuotable::Reset::Daily.call
193
+ ```
194
+
195
+ ## Contributing
196
+
197
+ ```bash
198
+ $ docker-sync start
199
+ $ docker-compose build
200
+ $ docker-compose run web bundle install
201
+ $ docker-compose run web bundle rails db:setup
202
+ $ docker-compose run web bundle rspec
203
+ ```
204
+
205
+ ## License
206
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/resource_quotable .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ class ApplicationController < ResourceQuotable.base_controller # :nodoc:
5
+ protected
6
+
7
+ def default_load_quotable_group
8
+ quotum_params[:group_type].constantize.find(quotum_params[:group_id])
9
+ end
10
+
11
+ def check_authorization
12
+ raise ResourceQuotable::AuthorizationError unless allowed_to_manage_quota?
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ class QuotaController < ResourceQuotable::ApplicationController # :nodoc:
5
+ layout ResourceQuotable.layout
6
+
7
+ before_action :check_authorization
8
+ before_action :load_quotum, only: %i[show edit update destroy]
9
+
10
+ def index
11
+ resource_quotable_before
12
+ @page = params[:page] || 1
13
+ @per_page = params[:per_page] || 5
14
+
15
+ @quota = quota_scoped.page(@page).per(@per_page)
16
+ resource_quotable_after
17
+ end
18
+
19
+ def show
20
+ resource_quotable_before
21
+ @quotum_trackers = @quotum.quotum_trackers.page(@page).per(@per_page)
22
+ resource_quotable_after
23
+ end
24
+
25
+ def new
26
+ resource_quotable_before
27
+ @quotum = Quotum.new
28
+ resource_quotable_after
29
+ end
30
+
31
+ def create
32
+ resource_quotable_before
33
+ @quotum = ResourceQuotable::Create.call(
34
+ group: load_quotable_group || default_load_quotable_group,
35
+ resource: quotum_params[:resource_class],
36
+ action: quotum_params[:action].to_sym,
37
+ period: quotum_params[:period].to_sym,
38
+ limit: quotum_params[:limit].to_i
39
+ )
40
+ resource_quotable_after
41
+ respond_to do |format|
42
+ format.html do
43
+ flash[:notice] = 'Quotum created'
44
+ redirect_to action: :index
45
+ end
46
+ format.js
47
+ end
48
+ end
49
+
50
+ def edit
51
+ resource_quotable_before
52
+ resource_quotable_after
53
+ end
54
+
55
+ def update
56
+ resource_quotable_before
57
+ @quotum = ResourceQuotable::Update.call(
58
+ quotum: @quotum,
59
+ limit: quotum_edit_params[:limit].to_i
60
+ )
61
+ resource_quotable_after
62
+ respond_to do |format|
63
+ format.html do
64
+ flash[:notice] = 'Quotum updated'
65
+ redirect_to action: :show, id: @quotum.id
66
+ end
67
+ format.js
68
+ end
69
+ end
70
+
71
+ def destroy
72
+ resource_quotable_before
73
+ @id = @quotum.id
74
+ ResourceQuotable::Destroy.call(quotum: @quotum)
75
+ resource_quotable_after
76
+ respond_to do |format|
77
+ format.html do
78
+ flash[:notice] = 'Quotum deleted'
79
+ redirect_to action: :index
80
+ end
81
+ format.js
82
+ end
83
+ end
84
+
85
+ protected
86
+
87
+ def quotum_params
88
+ params.require(:quotum).permit(
89
+ :period,
90
+ :limit,
91
+ :resource_class,
92
+ :action,
93
+ :group_id,
94
+ :group_type
95
+ )
96
+ end
97
+
98
+ def quotum_edit_params
99
+ params.require(:quotum).permit(:limit)
100
+ end
101
+
102
+ def load_quotum
103
+ @quotum = quota_scoped.find(params[:id])
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ class QuotumTrackersController < ResourceQuotable::ApplicationController # :nodoc:
5
+ layout ResourceQuotable.layout
6
+
7
+ before_action :check_authorization
8
+
9
+ def reset
10
+ resource_quotable_before
11
+
12
+ @quotum_tracker = ResourceQuotable::QuotumTrackerServices::Reset.call(quotum_tracker: load_quotum_tracker)
13
+
14
+ resource_quotable_after
15
+ end
16
+
17
+ protected
18
+
19
+ def load_quotum_tracker
20
+ QuotumTracker.find(params[:id])
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ class ApplicationRecord < ActiveRecord::Base # :nodoc:
5
+ self.abstract_class = true
6
+ end
7
+ end
@@ -0,0 +1,46 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: resource_quotable_quota
4
+ #
5
+ # id :integer not null, primary key
6
+ # action :integer default("create"), not null
7
+ # group_type :string not null
8
+ # limit :integer default(1), not null
9
+ # period :integer default("any"), not null
10
+ # resource_class :string not null
11
+ # created_at :datetime
12
+ # updated_at :datetime
13
+ # group_id :integer not null
14
+ #
15
+ # Indexes
16
+ #
17
+ # index_resource_quotable_quota_on_group_id (group_id)
18
+ # resource_quotable_quota_unique_index (group_id,resource_class,action,period) UNIQUE
19
+ #
20
+
21
+ # frozen_string_literal: true
22
+
23
+ module ResourceQuotable
24
+ class Quotum < ApplicationRecord # :nodoc:
25
+ belongs_to :group, polymorphic: true, inverse_of: :quota
26
+ has_many :quotum_trackers, dependent: :destroy
27
+
28
+ scope :for_resource_action, ->(resource, action) { where(action: action, resource_class: resource) }
29
+
30
+ validates :resource_class, :action, :period, :limit, presence: true
31
+
32
+ enum action: ResourceQuotable.actions, _suffix: true
33
+
34
+ enum period: {
35
+ any: 0,
36
+ daily: 1,
37
+ weekly: 2,
38
+ monthly: 3,
39
+ yearly: 4
40
+ }, _suffix: true
41
+
42
+ def to_s
43
+ "#{period.to_s.capitalize} #{action} #{resource_class}."
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,60 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: resource_quotable_quotum_trackers
4
+ #
5
+ # id :integer not null, primary key
6
+ # counter :integer default(0), not null
7
+ # flag :boolean default(FALSE), not null
8
+ # user_type :string not null
9
+ # quotum_id :integer not null
10
+ # user_id :integer not null
11
+ #
12
+ # Indexes
13
+ #
14
+ # index_resource_quotable_quotum_trackers_on_quotum_id (quotum_id)
15
+ # index_resource_quotable_quotum_trackers_on_user_id (user_id)
16
+ # resource_quotable_quotum_trackers_unique_index (user_id,quotum_id) UNIQUE
17
+ #
18
+
19
+ # frozen_string_literal: true
20
+
21
+ module ResourceQuotable
22
+ # Flag is true when the quota has been reached.
23
+ class QuotumTracker < ApplicationRecord
24
+ belongs_to :quotum
25
+ belongs_to :user, polymorphic: true, inverse_of: :quotum_trackers
26
+
27
+ validates :counter, presence: true
28
+
29
+ scope :with_active_counter, -> { where('counter > 0') }
30
+ scope :for_user, ->(user) { where(user: user) }
31
+ scope :under_limit, ->(limit_to_check_against) { where('counter < ?', limit_to_check_against) }
32
+ scope :over_limit, ->(limit_to_check_against) { where('counter >= ?', limit_to_check_against) }
33
+ scope :flagged, -> { where(flag: true) }
34
+ scope :not_flagged, -> { where(flag: false) }
35
+
36
+ delegate :action, :resource_class, :limit, :period, to: :quotum
37
+
38
+ def increment!
39
+ raise ResourceQuotable::QuotaLimitError if flag
40
+
41
+ new_counter = counter + 1
42
+ update(counter: new_counter, flag: (new_counter >= limit))
43
+ end
44
+
45
+ def increment_by!(amount)
46
+ new_counter = counter + amount
47
+ raise ResourceQuotable::QuotaMultiLimitError if new_counter > limit
48
+
49
+ update(counter: new_counter, flag: (new_counter >= limit))
50
+ end
51
+
52
+ def reset!
53
+ return if counter.zero?
54
+
55
+ self.counter = 0
56
+ self.flag = (counter >= limit)
57
+ save
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ module ActionServices
5
+ # Check Resource#action Quota for a user.
6
+ # return false if it is ok.
7
+ # return true if it is blocked
8
+ class Base < ResourceQuotable::Base
9
+ attr_accessor :user, :action, :resource
10
+
11
+ validates :user, :resource, presence: true
12
+ validates_inclusion_of :action, in: ResourceQuotable.actions.keys
13
+
14
+ protected
15
+
16
+ def find_or_create_quotum_tracker(quotum)
17
+ quotum_tracker = quotum.quotum_trackers.find_by(user: user)
18
+ quotum_tracker ||= user.quotum_trackers.create!(quotum: quotum, counter: 0, flag: !quotum.limit.positive?)
19
+ quotum_tracker
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ module ActionServices
5
+ # Check Resource#action Quota for a user.
6
+ # return false if it is ok.
7
+ # return true if it is blocked
8
+ class Check < Base
9
+ def call
10
+ user.quota_for_resource_action(resource, action).each do |quotum|
11
+ quotum_tracker = find_or_create_quotum_tracker(quotum)
12
+
13
+ return true if quotum_tracker.flag?
14
+ end
15
+ false
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ module ActionServices
5
+ # Check Resource#action Quota for a user.
6
+ # return false if it is ok.
7
+ # return true if it is blocked
8
+ class CheckMultiple < Base
9
+ attr_accessor :amount
10
+
11
+ validates :amount, presence: true
12
+
13
+ def call
14
+ user.quota_for_resource_action(resource, action).each do |quotum|
15
+ quotum_tracker = find_or_create_quotum_tracker(quotum)
16
+
17
+ return true if quotum_tracker.counter + amount > quotum.limit
18
+ end
19
+ false
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ module ActionServices
5
+ # Increment Resource#action Quota counter for a user.
6
+ class Increment < Base
7
+ def call
8
+ ResourceQuotable::Quotum.transaction do
9
+ user.quota_for_resource_action(resource, action).each do |quotum|
10
+ quotum_tracker = find_or_create_quotum_tracker(quotum)
11
+
12
+ quotum_tracker.increment!
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ module ActionServices
5
+ # Increment Resource#action Quota counter for a user.
6
+ class IncrementMultiple < Base
7
+ attr_accessor :amount
8
+
9
+ validates :amount, presence: true
10
+
11
+ def call
12
+ ResourceQuotable::Quotum.transaction do
13
+ user.quota_for_resource_action(resource, action).each do |quotum|
14
+ quotum_tracker = find_or_create_quotum_tracker(quotum)
15
+
16
+ quotum_tracker.increment_by!(amount)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ResourceQuotable
4
+ class Base # :nodoc:
5
+ include ActiveModel::Validations
6
+
7
+ def initialize(args = {})
8
+ args.each do |k, v|
9
+ instance_variable_set("@#{k}", v) unless v.nil?
10
+ end
11
+ end
12
+
13
+ def self.call(args = {})
14
+ service = new(args)
15
+ raise ArgumentError, service.errors.full_messages.join(', ') if service.invalid?
16
+
17
+ service.call
18
+ end
19
+
20
+ def call
21
+ raise ResourceQuotable::AbstractClassError
22
+ end
23
+ end
24
+ end