glib-web 0.4.2 → 0.4.3

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
  SHA256:
3
- metadata.gz: '00370028bd3cdc3097c1b40e128c34ec08271d2858b5a83d2c54ebceb5f18c6e'
4
- data.tar.gz: 5021c723ca5ef541455c0497fc0a25f86945b7d99383698fb76d587d034f2f9b
3
+ metadata.gz: 38b5751f1b2684f0d68bacb791098fc4aab5ab6b42cb25f1891a1f27bbdbbc8f
4
+ data.tar.gz: eed1f00a5ccd846f36d7291620f45f8702a63f80ffe8b94364243a5f1ce3cb55
5
5
  SHA512:
6
- metadata.gz: f7cc0a4fa5a08a8673e3306dfb91ca07e341c395b4a3f1e4cce985b7da72e394844ff5596087e657b15a1c610366aa34f5958446b40ba27c7a3ce3fc9afbd253
7
- data.tar.gz: 9c4b027e7025dcb06a7734839fde49dc8138ae5865e442faebe0f0e715dc9d3077747f1e52b6f5198337d36635de9af89f52970abcf82a24929dc23ee5877948
6
+ metadata.gz: a464dbf43a08c5f9b131c5e18b48bda98d40ef29e0298827b78e901f667df0901f227be11809feb39be6d55aa1b9b09133cfa119d06829f5dd663a569ef2e6eb
7
+ data.tar.gz: ca3b4567e5344a9d057c66d772aded64ba86b810d650837b1581eb40a3a981eed7e646c58e5915964f3a612088b0451a8cd490542e51d288bd5e4f30ba5d28a3
@@ -0,0 +1,98 @@
1
+ module Glib::Auth
2
+ module Policy
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include Pundit
7
+ include Overrides
8
+ extend ClassMethods
9
+
10
+ # TODO: Ultimately we want to uncomment this line, but:
11
+ # - Need to be able to set aside some time to run rspec tests to ensure nothing gets broken
12
+ # - Need to find a solution where we can reuse a single public policy
13
+ # after_action :verify_authorized
14
+
15
+ helper_method :policy, :can?, :cannot?
16
+
17
+ end
18
+
19
+ module Overrides
20
+ public # Override
21
+ def policy(record)
22
+ return @__pundit_policy if defined? @__pundit_policy
23
+
24
+ if record.is_a?(Symbol) && record.to_s.ends_with?('_admin')
25
+ policy_class = CommonAdminPolicy
26
+ else
27
+ policy_class = Pundit::PolicyFinder.new(record).policy
28
+ end
29
+ raise "Policy not found for #{record.class}" unless policy_class
30
+ @__pundit_policy = policy_class.new(current_user, record, self, request, params, *policy_class.args_builder.call(self))
31
+ end
32
+ end
33
+
34
+ public
35
+ def raise_access_denied(record)
36
+ # raise Pundit::NotAuthorizedError.new(record: record, policy: policy(record), query: "#{action_name}?")
37
+ raise UnauthorizedError.new(record: record, policy: policy(record), query: "#{action_name}?")
38
+ end
39
+
40
+ public
41
+ def can?(action, record)
42
+ policy(record).send("#{action}?")
43
+ end
44
+
45
+ public
46
+ def cannot?(action, record)
47
+ !policy(record).send("#{action}?")
48
+ end
49
+
50
+
51
+
52
+ class UnauthorizedError < Pundit::NotAuthorizedError
53
+ end
54
+
55
+
56
+
57
+ module ClassMethods
58
+ # Inspired from https://github.com/ryanb/cancan/wiki/Non-RESTful-Controllers
59
+ public
60
+ def authorize_resource(*args)
61
+ options = args.extract_options!
62
+ resource_name = args.first
63
+
64
+ self.before_action(options.slice(:only, :except, :if, :unless)) do |controller|
65
+ resource_name ||= resource_name_from_controller
66
+
67
+ if !(resource_key = options[:class]).nil?
68
+ resource = case resource_key
69
+ when false
70
+ resource_name.to_sym
71
+ when Symbol, Class
72
+ resource_key
73
+ else
74
+ raise "Invalid resource class: #{resource_key}"
75
+ end
76
+
77
+ authorize resource
78
+ # if (policy = policy(resource)) && policy.class.instance_variable_defined?(:@manage_permission)
79
+ # skip_authorization if policy.manage?
80
+ # else
81
+ # authorize resource
82
+ # end
83
+ elsif (resource_instance = controller.instance_variable_get("@#{resource_name}"))
84
+ authorize resource_instance
85
+ else
86
+ authorize resource_name.camelize.constantize
87
+ end
88
+
89
+ verify_authorized
90
+ end
91
+ end
92
+ end
93
+
94
+ def resource_name_from_controller
95
+ params[:controller].split('/').last.singularize
96
+ end
97
+ end
98
+ end
@@ -2,15 +2,14 @@ module Glib::Json::DynamicText
2
2
  def __json_dynamic_text_perform
3
3
  if (hash = json_transformation_start).is_a?(Hash)
4
4
  @__specs = {}
5
-
5
+
6
6
  crawl hash['header']&.[]('childViews')
7
7
  crawl hash['body']&.[]('childViews')
8
8
  crawl hash['footer']&.[]('childViews')
9
9
 
10
- # TODO: retrieve texts from dynamictextreader
11
- # translated_texts = retrieve_remote_texts(@__specs.keys)
10
+ translated_texts = retrieve_remote_texts(@__specs.keys)
12
11
 
13
- translated_texts = retrieve_example_texts(@__specs.keys)
12
+ # translated_texts = retrieve_example_texts(@__specs.keys)
14
13
  translated_texts.each do |key, value|
15
14
  @__specs[key].each do |spec|
16
15
  spec.substitute_with(value)
@@ -32,6 +31,11 @@ module Glib::Json::DynamicText
32
31
  translated_texts
33
32
  end
34
33
 
34
+ def retrieve_remote_texts(keys)
35
+ response = RestClient.get(ENV['DTR_URL'], { params: { keys: keys } })
36
+ JSON.parse(response)
37
+ end
38
+
35
39
  def crawl views
36
40
  Glib::Json::DynamicText::crawl_multiple views, ->(view) do
37
41
  extract_spec(view, 'text')
@@ -52,7 +56,7 @@ module Glib::Json::DynamicText
52
56
  view[prop] = text.gsub(/\{\{(\w+)\}\}/) { args.fetch($1, "{{#{$1}}}") }
53
57
  end
54
58
  end
55
-
59
+
56
60
  def self.crawl_multiple views, block
57
61
  if views.is_a? Array
58
62
  views.each do |view|
@@ -85,7 +89,7 @@ module Glib::Json::DynamicText
85
89
  # panels/split
86
90
  # crawl_multiple view['leftViews'], block
87
91
  # crawl_multiple view['rightViews'], block
88
-
92
+
89
93
  # Split panel
90
94
  crawl_vertical_content view['left'], block
91
95
  crawl_vertical_content view['center'], block
@@ -82,6 +82,7 @@ module Glib
82
82
  string :body
83
83
  string :tag
84
84
  int :timeout
85
+ action :onClick
85
86
  end
86
87
 
87
88
  end
@@ -0,0 +1,148 @@
1
+ # The main purpose of this is for security. If it is important to display useful error message or to provide a "banana", then
2
+ # it's better to perform an explicit check (e.g. as a validation in the model or using a before_action).
3
+ module Glib
4
+ class ApplicationPolicy
5
+ attr_reader :user, :record, :controller, :request, :params
6
+
7
+ private
8
+ def initialize(user, record, controller, request, params)
9
+ @user = user
10
+ @record = record
11
+ @controller = controller
12
+ @request = request
13
+ # Don't get params from request because we might not have a proper request object. This might execute in Sidekiq.
14
+ # See Presenter::Model::inside_mock_controller()
15
+ @params = params
16
+ end
17
+
18
+ class << self
19
+ attr_reader :catch_all
20
+
21
+ # This is to define the authorization logic for an action (or a group of actions). It's different from controller's
22
+ # authorize().
23
+ private # Used by child
24
+ def authorize(*actions, &block)
25
+ actions.each do |action|
26
+ if action == :manage
27
+ # Serve as a catch-all to all actions that have not been specified in the policy.
28
+ @catch_all = block
29
+ else
30
+ method_name = "#{action}?"
31
+ # Avoid accidentally redefining multiple times from child policies. But it's okay if the child policy
32
+ # wants to override the parent's authorization method.
33
+ raise "Action authorization has been declared: #{action}" if instance_methods(false).include?(method_name.to_sym)
34
+ define_method method_name, &block
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+ def catch_all
42
+ self.class.catch_all
43
+ end
44
+
45
+ private
46
+ # To ensure the block is called on the policy's instance instead class.
47
+ def call_catch_all
48
+ instance_eval(&catch_all)
49
+ end
50
+
51
+ authorize :index do
52
+ # We need this line because in `index` action, this method will be called instead of method_missing().
53
+ # Having this line ensures that the catch_all behaviour works according to the priority below:
54
+ # - child_policy#index?
55
+ # - child_policy#manage? -- catch_all
56
+ # - application_policy@index?
57
+ return call_catch_all if catch_all
58
+
59
+ false
60
+ end
61
+
62
+ authorize :show do
63
+ return call_catch_all if catch_all
64
+
65
+ scope.where(id: record.id).exists?
66
+ end
67
+
68
+ authorize :create do
69
+ return call_catch_all if catch_all
70
+
71
+ false
72
+ end
73
+
74
+ authorize :new do
75
+ return call_catch_all if catch_all
76
+
77
+ create?
78
+ end
79
+
80
+ authorize :update do
81
+ return call_catch_all if catch_all
82
+
83
+ false
84
+ end
85
+
86
+ authorize :edit do
87
+ return call_catch_all if catch_all
88
+
89
+ update?
90
+ end
91
+
92
+ authorize :destroy do
93
+ return call_catch_all if catch_all
94
+
95
+ false
96
+ end
97
+
98
+ public
99
+ def method_missing(name, *args, &block)
100
+ if name.to_s.end_with?('?') && catch_all
101
+ call_catch_all
102
+ else
103
+ super
104
+ end
105
+ end
106
+
107
+ public
108
+ def scope
109
+ Pundit.policy_scope!(user, record.class)
110
+ end
111
+
112
+ private # Used by child
113
+ def public?
114
+ true
115
+ end
116
+
117
+ # # TODO: Revise because it seems there is no justification for allowing owner to see any of the deleted entities, which include User, Guild, and Post
118
+ # private # Used by child
119
+ # def not_deleted_unless_owner_or_moderator?(&block)
120
+ # block ||= lambda { |unused_arg| @user.moderator? }
121
+ # !@record.deleted? || (@user && (@user.id == @record.user_owner_id || block.call(@record)))
122
+ # end
123
+
124
+ # private # Used by child
125
+ # def not_deleted_unless_moderator?(&block)
126
+ # block ||= lambda { |unused_arg| @user.moderator? }
127
+ # !@record.deleted? || (@user && block.call(@record))
128
+ # end
129
+
130
+ public
131
+ def self.args_builder
132
+ Proc.new { |controller| [] }
133
+ end
134
+
135
+ class Scope
136
+ attr_reader :user, :scope
137
+
138
+ def initialize(user, scope)
139
+ @user = user
140
+ @scope = scope
141
+ end
142
+
143
+ def resolve
144
+ scope
145
+ end
146
+ end
147
+ end
148
+ end
@@ -6,7 +6,9 @@ json_ui_page json do |page|
6
6
  page.list firstSection: ->(section) do
7
7
  section.rows builder: ->(template) do
8
8
  template.thumbnail title: 'Send Desktop Notification', onClick: ->(action) do
9
- action.dialogs_notification title: 'Hello World', body: 'Body Message'
9
+ action.dialogs_notification title: 'Hello World', body: 'Body Message', onClick: ->(action) do
10
+ action.dialogs_alert message: 'TODO'
11
+ end
10
12
  end
11
13
  end
12
14
  end
@@ -1,4 +1,4 @@
1
- json.title 'Panels'
1
+ json.title 'Responsive Panels'
2
2
 
3
3
  json_ui_page json do |page|
4
4
  render "#{@path_prefix}/nav_menu", json: json, page: page
@@ -7,37 +7,49 @@ json_ui_page json do |page|
7
7
  scroll.label text: 'Shrink the browser\'s width to see how the column panels are rearranged. On mobile screens, they are always arranged vertically'
8
8
 
9
9
  scroll.spacer height: 20
10
- scroll.h2 text: 'Responsive panel with 12 columns'
10
+ scroll.h2 text: 'With 12 columns'
11
11
  scroll.spacer height: 6
12
12
  scroll.panels_responsive width: 'matchParent', childViews: ->(horizontal) do
13
- horizontal.panels_column lg: 8, backgroundColor: '#c3cad2', childViews: ->(column) do
13
+ horizontal.panels_column lg: { cols: 8 }, backgroundColor: '#c3cad2', childViews: ->(column) do
14
14
  column.button text: '1'
15
15
  end
16
- horizontal.panels_column lg: 4, backgroundColor: '#b3bac2', childViews: ->(column) do
16
+ horizontal.panels_column lg: { cols: 4 }, backgroundColor: '#b3bac2', childViews: ->(column) do
17
17
  column.button text: '2'
18
18
  end
19
19
  end
20
20
 
21
21
  scroll.spacer height: 20
22
- scroll.h2 text: 'Responsive panel with more than 12 columns'
22
+ scroll.h2 text: 'With more than 12 columns'
23
23
  scroll.spacer height: 6
24
24
  scroll.panels_responsive width: 'matchParent', childViews: ->(horizontal) do
25
- horizontal.panels_column lg: 4, backgroundColor: '#c3cad2', childViews: ->(column) do
25
+ horizontal.panels_column lg: { cols: 4 }, backgroundColor: '#c3cad2', childViews: ->(column) do
26
26
  column.button text: '1'
27
27
  end
28
- horizontal.panels_column lg: 4, backgroundColor: '#b3bac2', childViews: ->(column) do
28
+ horizontal.panels_column lg: { cols: 4 }, backgroundColor: '#b3bac2', childViews: ->(column) do
29
29
  column.button text: '2'
30
30
  end
31
- horizontal.panels_column lg: 4, backgroundColor: '#c3cad2', childViews: ->(column) do
31
+ horizontal.panels_column lg: { cols: 4 }, backgroundColor: '#c3cad2', childViews: ->(column) do
32
32
  column.button text: '3'
33
33
  end
34
- horizontal.panels_column lg: 4, backgroundColor: '#b3bac2', childViews: ->(column) do
34
+ horizontal.panels_column lg: { cols: 4 }, backgroundColor: '#b3bac2', childViews: ->(column) do
35
35
  column.button text: '4'
36
36
  end
37
- horizontal.panels_column lg: 4, backgroundColor: '#c3cad2', childViews: ->(column) do
37
+ horizontal.panels_column lg: { cols: 4 }, backgroundColor: '#c3cad2', childViews: ->(column) do
38
38
  column.button text: '5'
39
39
  end
40
40
  end
41
41
 
42
+ scroll.spacer height: 20
43
+ scroll.h2 text: 'With responsive paddings'
44
+ scroll.spacer height: 6
45
+ scroll.panels_responsive width: 'matchParent', childViews: ->(horizontal) do
46
+ horizontal.panels_column lg: { cols: 8, padding: { right: 20 } }, childViews: ->(column) do
47
+ column.button width: 'matchParent', text: '1'
48
+ end
49
+ horizontal.panels_column lg: { cols: 4 }, childViews: ->(column) do
50
+ column.button width: 'matchParent', text: '2'
51
+ end
52
+ end
53
+
42
54
  end
43
55
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glib-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
@@ -30,6 +30,34 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: 6.1.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: pundit
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 2.1.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 2.1.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: rest-client
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.1'
33
61
  description:
34
62
  email: ''
35
63
  executables: []
@@ -40,6 +68,7 @@ files:
40
68
  - app/controllers/concerns/application/json/transformation.rb
41
69
  - app/controllers/concerns/application/json/ui.rb
42
70
  - app/controllers/concerns/application/json/validation.rb
71
+ - app/controllers/concerns/glib/auth/policy.rb
43
72
  - app/controllers/concerns/glib/json/dynamic_text.rb
44
73
  - app/controllers/concerns/glib/json/libs.rb
45
74
  - app/controllers/concerns/glib/json/transformation.rb
@@ -63,6 +92,7 @@ files:
63
92
  - app/helpers/glib/json_ui/view_builder/panels.rb
64
93
  - app/models/glib/dynamic_text_record.rb
65
94
  - app/models/glib/text.rb
95
+ - app/policies/glib/application_policy.rb
66
96
  - app/views/app/views/json_ui/vue/renderer.html.erb
67
97
  - app/views/json_ui/garage/_nav_menu.json.jbuilder
68
98
  - app/views/json_ui/garage/actions/index.json.jbuilder