glib-web 0.4.24 → 0.4.25
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 +4 -4
- data/app/controllers/concerns/glib/auth/policy.rb +61 -11
- data/app/controllers/glib/home_controller.rb +2 -0
- data/app/helpers/glib/json_ui/list_builders.rb +9 -3
- data/app/helpers/glib/json_ui/menu_builder.rb +1 -0
- data/app/helpers/glib/json_ui/page_helper.rb +1 -1
- data/app/policies/glib/application_policy.rb +158 -148
- data/app/views/json_ui/garage/lists/templating.json.jbuilder +8 -7
- data/app/views/json_ui/garage/views/images.json.jbuilder +15 -18
- data/lib/glib/json_crawler/action_crawlers/nav_initiate.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a78169ee4aa218427c3afb3fdb50fd77280f627
|
4
|
+
data.tar.gz: d86539782b4e6c0a50cbba7e5ac5b39565e9feb5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 495d37ef44d6fbad0a970f0f3b3bf35effe81b5ceb866c5eeb1606d179f217f747365d1987caaf910d83c0f26cec6d50ee147bfdcfe0581df583dd367e154d6b
|
7
|
+
data.tar.gz: e8942b48722e047778a7bbb8ed9d84734b14ad048700efc05edf835e1770bbeb08e4e63ebe4e43e1212363f16748c51e93167a49332b06d6373f80872e0b4647
|
@@ -15,28 +15,38 @@ module Glib::Auth
|
|
15
15
|
# after_action :verify_authorized
|
16
16
|
|
17
17
|
helper_method :policy, :can?, :cannot?
|
18
|
-
|
19
18
|
end
|
20
19
|
|
21
20
|
module Overrides
|
21
|
+
|
22
22
|
public # Override
|
23
|
-
def policy(record)
|
23
|
+
def policy(record, policy_name = nil)
|
24
|
+
policy_name ||= record
|
25
|
+
|
24
26
|
@__pundit_policies ||= {}
|
25
|
-
return @__pundit_policies[
|
27
|
+
return @__pundit_policies[policy_name] if @__pundit_policies[policy_name]
|
26
28
|
|
27
|
-
if
|
29
|
+
if policy_name.is_a?(Symbol) && policy_name.to_s.ends_with?('_admin')
|
28
30
|
policy_class = CommonAdminPolicy
|
29
31
|
else
|
30
|
-
policy_class = Pundit::PolicyFinder.new(
|
32
|
+
policy_class = Pundit::PolicyFinder.new(policy_name).policy
|
31
33
|
end
|
32
|
-
|
33
|
-
|
34
|
+
|
35
|
+
raise "Policy not found for #{policy_name.is_a?(Symbol) || policy_name.is_a?(Class) ? policy_name : policy_name.class}" unless policy_class
|
36
|
+
|
37
|
+
@__pundit_policies[policy_name] = policy_class.new(current_user, record, policy_name, self, request, params, *policy_class.args_builder.call(self))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Expose protected method
|
41
|
+
public # Override
|
42
|
+
def policy_scope(*args)
|
43
|
+
super
|
34
44
|
end
|
35
45
|
end
|
36
46
|
|
37
|
-
|
38
|
-
def raise_access_denied(record)
|
39
|
-
raise UnauthorizedError.new(record: record, policy: policy
|
47
|
+
private
|
48
|
+
def raise_access_denied(record, policy)
|
49
|
+
raise UnauthorizedError.new(record: record, policy: policy, query: "#{action_name}?")
|
40
50
|
end
|
41
51
|
|
42
52
|
public
|
@@ -49,6 +59,34 @@ module Glib::Auth
|
|
49
59
|
!policy(record).send("#{action}?")
|
50
60
|
end
|
51
61
|
|
62
|
+
# Inspired from https://github.com/ryanb/cancan/wiki/Non-RESTful-Controllers
|
63
|
+
public
|
64
|
+
def glib_authorize_resource(*args)
|
65
|
+
options = args.extract_options!
|
66
|
+
resource_name = args.first
|
67
|
+
|
68
|
+
resource_name ||= controller_name.split('/').last.singularize
|
69
|
+
|
70
|
+
if (resource_key = options[:class]).nil?
|
71
|
+
policy_name = resource_name.camelize.constantize
|
72
|
+
else
|
73
|
+
policy_name = case resource_key
|
74
|
+
when false
|
75
|
+
resource_name.to_sym
|
76
|
+
when Symbol, Class
|
77
|
+
resource_key
|
78
|
+
else
|
79
|
+
raise "Invalid resource class: #{resource_key}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
resource_instance = instance_variable_get("@#{resource_name}") || policy_name
|
84
|
+
|
85
|
+
query = "#{action_name}?"
|
86
|
+
policy_instance = policy(resource_instance, policy_name)
|
87
|
+
raise_access_denied(resource_instance, policy_instance) unless policy_instance.public_send(query)
|
88
|
+
end
|
89
|
+
|
52
90
|
|
53
91
|
|
54
92
|
class UnauthorizedError < Pundit::NotAuthorizedError
|
@@ -57,7 +95,19 @@ module Glib::Auth
|
|
57
95
|
|
58
96
|
|
59
97
|
module ClassMethods
|
60
|
-
|
98
|
+
def glib_auth_init
|
99
|
+
before_action :glib_load_resource
|
100
|
+
before_action :glib_authorize_resource
|
101
|
+
# glib_authorize_resource
|
102
|
+
end
|
103
|
+
|
104
|
+
# def __glib_load_resource
|
105
|
+
# case action_name.to_sym
|
106
|
+
# # glib_load_resource
|
107
|
+
# end
|
108
|
+
# end
|
109
|
+
|
110
|
+
# TODO: Consider deprecating
|
61
111
|
public
|
62
112
|
def authorize_resource(*args)
|
63
113
|
options = args.extract_options!
|
@@ -24,9 +24,15 @@ module Glib
|
|
24
24
|
string :imageUrl
|
25
25
|
action :onClick
|
26
26
|
|
27
|
-
# NOTE: Experimental. Still deciding whether this needs to be a full blown panel or
|
28
|
-
# an array of badges (with relevant properties, e.g. text, color, etc)
|
29
|
-
views :accessoryViews
|
27
|
+
# # NOTE: Experimental. Still deciding whether this needs to be a full blown panel or
|
28
|
+
# # an array of badges (with relevant properties, e.g. text, color, etc)
|
29
|
+
# views :accessoryViews
|
30
|
+
|
31
|
+
def chips(block)
|
32
|
+
json.chips do
|
33
|
+
block.call page.menu_builder
|
34
|
+
end
|
35
|
+
end
|
30
36
|
end
|
31
37
|
|
32
38
|
class Featured < Thumbnail
|
@@ -75,7 +75,7 @@ module Glib
|
|
75
75
|
# json.leftItems do
|
76
76
|
# options[:leftItems]&.call @menu_builder
|
77
77
|
# end
|
78
|
-
json.logoUrl "http://localhost:3000/assets/logo_dark-02d9b6a91fdbf22515da7b921d31367b70696214415f6789d2f90232e4a287b7.svg"
|
78
|
+
# json.logoUrl "http://localhost:3000/assets/logo_dark-02d9b6a91fdbf22515da7b921d31367b70696214415f6789d2f90232e4a287b7.svg"
|
79
79
|
json.rightItems do
|
80
80
|
options[:rightItems]&.call @menu_builder
|
81
81
|
end
|
@@ -1,148 +1,158 @@
|
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
#
|
54
|
-
#
|
55
|
-
# - child_policy#
|
56
|
-
# -
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
#
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
#
|
128
|
-
#
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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, :policy_name, :controller, :request, :params
|
6
|
+
|
7
|
+
private
|
8
|
+
def initialize(user, record, policy_name, 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
|
+
@policy_name = policy_name
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_reader :catch_all
|
21
|
+
|
22
|
+
# This is to define the authorization logic for an action (or a group of actions). It's different from controller's
|
23
|
+
# authorize().
|
24
|
+
private # Used by child
|
25
|
+
def authorize(*actions, &block)
|
26
|
+
actions.each do |action|
|
27
|
+
if action == :manage
|
28
|
+
# Serve as a catch-all to all actions that have not been specified in the policy.
|
29
|
+
@catch_all = block
|
30
|
+
else
|
31
|
+
method_name = "#{action}?"
|
32
|
+
# Avoid accidentally redefining multiple times from child policies. But it's okay if the child policy
|
33
|
+
# wants to override the parent's authorization method.
|
34
|
+
raise "Action authorization has been declared: #{action}" if instance_methods(false).include?(method_name.to_sym)
|
35
|
+
define_method method_name, &block
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def catch_all
|
43
|
+
self.class.catch_all
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
# To ensure the block is called on the policy's instance instead class.
|
48
|
+
def call_catch_all
|
49
|
+
instance_eval(&catch_all)
|
50
|
+
end
|
51
|
+
|
52
|
+
authorize :index do
|
53
|
+
# We need this line because in `index` action, this method will be called instead of method_missing().
|
54
|
+
# Having this line ensures that the catch_all behaviour works according to the priority below:
|
55
|
+
# - child_policy#index?
|
56
|
+
# - child_policy#manage? -- catch_all
|
57
|
+
# - application_policy@index?
|
58
|
+
return call_catch_all if catch_all
|
59
|
+
|
60
|
+
false
|
61
|
+
end
|
62
|
+
|
63
|
+
authorize :show do
|
64
|
+
return call_catch_all if catch_all
|
65
|
+
|
66
|
+
scope.where(id: record.id).exists?
|
67
|
+
end
|
68
|
+
|
69
|
+
authorize :create do
|
70
|
+
return call_catch_all if catch_all
|
71
|
+
|
72
|
+
false
|
73
|
+
end
|
74
|
+
|
75
|
+
authorize :new do
|
76
|
+
return call_catch_all if catch_all
|
77
|
+
|
78
|
+
create?
|
79
|
+
end
|
80
|
+
|
81
|
+
authorize :update do
|
82
|
+
return call_catch_all if catch_all
|
83
|
+
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
authorize :edit do
|
88
|
+
return call_catch_all if catch_all
|
89
|
+
|
90
|
+
update?
|
91
|
+
end
|
92
|
+
|
93
|
+
authorize :destroy do
|
94
|
+
return call_catch_all if catch_all
|
95
|
+
|
96
|
+
false
|
97
|
+
end
|
98
|
+
|
99
|
+
public
|
100
|
+
def method_missing(name, *args, &block)
|
101
|
+
if name.to_s.end_with?('?') && catch_all
|
102
|
+
call_catch_all
|
103
|
+
else
|
104
|
+
super
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
public
|
109
|
+
def scope
|
110
|
+
policy_scope_class = Pundit::PolicyFinder.new(@policy_name).scope
|
111
|
+
return unless policy_scope_class
|
112
|
+
|
113
|
+
controller.policy_scope(record.class, policy_scope_class: policy_scope_class)
|
114
|
+
end
|
115
|
+
|
116
|
+
# TODO: Remove. Deprecated
|
117
|
+
private # Used by child
|
118
|
+
def public?
|
119
|
+
true
|
120
|
+
end
|
121
|
+
|
122
|
+
private # Used by child
|
123
|
+
def everyone
|
124
|
+
true
|
125
|
+
end
|
126
|
+
|
127
|
+
# # 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
|
128
|
+
# private # Used by child
|
129
|
+
# def not_deleted_unless_owner_or_moderator?(&block)
|
130
|
+
# block ||= lambda { |unused_arg| @user.moderator? }
|
131
|
+
# !@record.deleted? || (@user && (@user.id == @record.user_owner_id || block.call(@record)))
|
132
|
+
# end
|
133
|
+
|
134
|
+
# private # Used by child
|
135
|
+
# def not_deleted_unless_moderator?(&block)
|
136
|
+
# block ||= lambda { |unused_arg| @user.moderator? }
|
137
|
+
# !@record.deleted? || (@user && block.call(@record))
|
138
|
+
# end
|
139
|
+
|
140
|
+
public
|
141
|
+
def self.args_builder
|
142
|
+
Proc.new { |controller| [] }
|
143
|
+
end
|
144
|
+
|
145
|
+
class Scope
|
146
|
+
attr_reader :user, :scope
|
147
|
+
|
148
|
+
def initialize(user, scope)
|
149
|
+
@user = user
|
150
|
+
@scope = scope
|
151
|
+
end
|
152
|
+
|
153
|
+
def resolve
|
154
|
+
scope.none
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -16,13 +16,14 @@ json_ui_page json do |page|
|
|
16
16
|
template.thumbnail title: 'Item with thumbnail image', subtitle: 'Item subtitle', imageUrl: glib_json_image_standard_url
|
17
17
|
template.featured title: 'Featured with featured image', subtitle: 'Item subtitle', imageUrl: glib_json_image_standard_url
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
19
|
+
# TODO
|
20
|
+
# template.thumbnail title: 'Item with accessories (Experimental)', subtitle: 'Item subtitle', accessoryViews: ->(thumbnail) do
|
21
|
+
# thumbnail.panels_horizontal childViews: ->(horizontal) do
|
22
|
+
# horizontal.chip text: 'finished'
|
23
|
+
# horizontal.spacer width: 10
|
24
|
+
# horizontal.chip text: 'succeeded'
|
25
|
+
# end
|
26
|
+
# end
|
26
27
|
|
27
28
|
end
|
28
29
|
end
|
@@ -3,7 +3,8 @@ json.title 'Views'
|
|
3
3
|
page = json_ui_page json
|
4
4
|
render "#{@path_prefix}/nav_menu", json: json, page: page
|
5
5
|
|
6
|
-
small_image_url = 'https://icons-for-free.com/iconfiles/png/128/of+thrones+game+thrones+series+character+avatar+jon+snow-1320568555745862611.png'
|
6
|
+
# small_image_url = 'https://icons-for-free.com/iconfiles/png/128/of+thrones+game+thrones+series+character+avatar+jon+snow-1320568555745862611.png'
|
7
|
+
small_image_url = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSGQpSWjtELISLBlmugOZ6wzl1JamYXQvbFeYywpfg3E8b8DrO0Kg&s'
|
7
8
|
|
8
9
|
page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
|
9
10
|
scroll.h2 text: 'Avatar'
|
@@ -33,7 +34,7 @@ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
|
|
33
34
|
|
34
35
|
scroll.spacer height: 60
|
35
36
|
scroll.hr
|
36
|
-
|
37
|
+
|
37
38
|
scroll.spacer height: 60
|
38
39
|
scroll.h2 text: 'Original size'
|
39
40
|
scroll.spacer height: 6
|
@@ -49,7 +50,7 @@ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
|
|
49
50
|
scroll.h2 text: 'fit: clip (default) to full width (scale down)'
|
50
51
|
scroll.spacer height: 6
|
51
52
|
scroll.image width: 'matchParent', url: glib_json_image_standard_url
|
52
|
-
|
53
|
+
|
53
54
|
scroll.spacer height: 20
|
54
55
|
scroll.h2 text: 'fit: clip (default) to full width (scale up)'
|
55
56
|
scroll.spacer height: 6
|
@@ -58,35 +59,31 @@ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
|
|
58
59
|
scroll.spacer height: 20
|
59
60
|
scroll.h2 text: 'fit: clip (default) to width (scale down)'
|
60
61
|
scroll.spacer height: 6
|
61
|
-
scroll.image width:
|
62
|
-
|
63
|
-
# TODO: Make sure this is the same as https://docs.imgix.com/apis/url/size/fit#clip
|
62
|
+
scroll.image width: 320, url: glib_json_image_standard_url
|
63
|
+
|
64
64
|
scroll.spacer height: 20
|
65
65
|
scroll.h2 text: 'fit: clip (default) to height (scale down)'
|
66
66
|
scroll.spacer height: 6
|
67
|
-
scroll.image height:
|
68
|
-
|
67
|
+
scroll.image height: 320, url: glib_json_image_standard_url
|
68
|
+
|
69
69
|
scroll.spacer height: 20
|
70
70
|
scroll.h2 text: 'fit: clip (default) to width (scale up)'
|
71
71
|
scroll.spacer height: 6
|
72
|
-
scroll.image width:
|
73
|
-
|
74
|
-
# TODO: Make sure this is the same as https://docs.imgix.com/apis/url/size/fit#clip
|
72
|
+
scroll.image width: 320, url: small_image_url
|
73
|
+
|
75
74
|
scroll.spacer height: 20
|
76
75
|
scroll.h2 text: 'fit: clip (default) to height (scale up)'
|
77
76
|
scroll.spacer height: 6
|
78
|
-
scroll.image height:
|
79
|
-
|
80
|
-
# TODO: Make sure this is the same as https://docs.imgix.com/apis/url/size/fit#crop
|
77
|
+
scroll.image height: 320, url: small_image_url
|
78
|
+
|
81
79
|
# Reference: https://docs.imgix.com/apis/url/size/fit#crop
|
82
80
|
scroll.spacer height: 20
|
83
81
|
scroll.h2 text: 'fit: crop to width'
|
84
82
|
scroll.spacer height: 6
|
85
|
-
scroll.image width:
|
86
|
-
|
87
|
-
# TODO: Make sure this is the same as https://docs.imgix.com/apis/url/size/fit#crop
|
83
|
+
scroll.image width: 200, url: glib_json_image_standard_url, fit: :crop
|
84
|
+
|
88
85
|
scroll.spacer height: 20
|
89
86
|
scroll.h2 text: 'fit: crop to height'
|
90
87
|
scroll.spacer height: 6
|
91
|
-
scroll.image height:
|
88
|
+
scroll.image height: 200, url: glib_json_image_standard_url, fit: :crop
|
92
89
|
end
|