File tree Expand file tree Collapse file tree
reactive_record/active_record Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -348,6 +348,7 @@ class DisplaySquare
348348 .on(:click ) { Game .handle_click(id) }
349349 end
350350end
351+
351352class DisplayBoard < HyperComponent
352353 render(DIV ) do
353354 (0 ..6 ).step(3 ) do |row |
@@ -503,5 +504,5 @@ a component **unless** the state will be accessed outside the component. Howev
503504would be better off to move the state into a separate store.
504505
505506> In addition components also act as the ** Observers** in the system. What this means is
506- that current component that is running its render method is recording all stores that call ` observe ` , when
507+ that the current component that is running its render method is recording all stores that call ` observe ` , when
507508a store mutates, then all the components that recorded observations will be rerendered.
Original file line number Diff line number Diff line change @@ -129,19 +129,31 @@ def finder_method(name, &block)
129129 end
130130 end
131131
132+ def allow_remote_access_to ( *methods , &block )
133+ methods = methods . collect { |meth | meth . is_a? ( Hash ) ? meth . keys : meth } . flatten
134+ methods . each do |name |
135+ define_method ( "__secure_remote_access_to_#{ name } " ) do |_self , acting_user , *args |
136+ begin
137+ old = self . acting_user
138+ self . acting_user = acting_user
139+ allowed = !block || instance_eval ( &block ) rescue nil
140+ return send ( name , *args ) if allowed
141+
142+ Hyperstack ::InternalPolicy . raise_operation_access_violation (
143+ :illegal_remote_access , "Access denied to #{ name } "
144+ )
145+ ensure
146+ self . acting_user = old
147+ end
148+ end
149+ end
150+ end
151+
132152 def server_method ( name , _opts = { } , &block )
133153 # callable from the server internally
134154 define_method ( name , &block )
135155 # callable remotely from the client
136- define_method ( "__secure_remote_access_to_#{ name } " ) do |_self , acting_user , *args |
137- begin
138- old = self . acting_user
139- self . acting_user = acting_user
140- send ( name , *args )
141- ensure
142- self . acting_user = old
143- end
144- end
156+ allow_remote_access_to ( name )
145157 end
146158
147159 # relationships (and scopes) are regulated using a tri-state system. Each
Original file line number Diff line number Diff line change @@ -364,6 +364,18 @@ def server_method(name, default: nil)
364364 end
365365 end
366366
367+ def allow_remote_access_to ( *methods )
368+ methods . each do |meth |
369+ if meth . is_a? Hash
370+ puts "defining these guys: #{ meth } "
371+ meth . each { |name , default | server_method ( name , default : default ) }
372+ else
373+ puts "defining this guy: #{ meth } "
374+ server_method ( meth )
375+ end
376+ end
377+ end
378+
367379 # define all the methods for each column. To allow overriding the methods they will NOT
368380 # be defined if already defined (i.e. by the model) See the instance_methods module for how
369381 # super calls are handled in this case. The _hyperstack_internal_setter_... methods
Original file line number Diff line number Diff line change @@ -88,4 +88,42 @@ class ServerMethodTester < HyperComponent
8888 expect ( TestModel . count ) . to be_zero
8989 expect ( ChildModel . count ) . to be_zero
9090 end
91+
92+ it "will allow remote access to methods" do
93+ TodoItem . class_eval do
94+ def foo
95+ "foo"
96+ end
97+
98+ def bar
99+ "bar"
100+ end
101+
102+ def broken
103+ "broken"
104+ end
105+
106+ def defaulted
107+ "defaulted"
108+ end
109+ end
110+ isomorphic do
111+ TodoItem . class_eval do
112+ allow_remote_access_to ( :foo , :bar ) { acting_user . nil? }
113+ allow_remote_access_to ( :broken ) { acting_user . admin? }
114+ allow_remote_access_to ( :dontcallme , defaulted : "loading" ) { true }
115+ end
116+ end
117+ client_option raise_on_js_errors : :off
118+ expect { TodoItem . last . foo } . on_client_to be_nil
119+ expect { Hyperstack ::Model . load { TodoItem . last . foo } } . on_client_to eq ( "foo" )
120+ expect { TodoItem . last . bar } . on_client_to be_nil
121+ expect { Hyperstack ::Model . load { TodoItem . last . bar } } . on_client_to eq ( "bar" )
122+ expect { Hyperstack ::Model . load { TodoItem . last . broken } } . on_client_to be_nil
123+ expect { TodoItem . last . defaulted } . on_client_to eq "loading"
124+ expect { Hyperstack ::Model . load { TodoItem . last . defaulted } } . on_client_to eq ( "defaulted" )
125+ errors = page . driver . browser . manage . logs . get ( :browser ) . select { |m | m . level == "SEVERE" }
126+ expect ( errors . count ) . to eq ( 2 )
127+ expect ( errors . first . message ) . to match ( /the server responded with a status of 403 \( Forbidden\) / )
128+ end
91129end
Original file line number Diff line number Diff line change @@ -82,7 +82,11 @@ def before_mount(&block)
8282
8383 def isomorphic ( &block )
8484 yield
85- before_mount ( &block )
85+ if page . instance_variable_get ( '@hyper_spec_mounted' )
86+ internal_evaluate_ruby ( &block )
87+ else
88+ before_mount ( &block )
89+ end
8690 end
8791
8892 # Allows options to the mount method to be specified globally
Original file line number Diff line number Diff line change @@ -108,6 +108,20 @@ def factorial(n)
108108 expect ( evaluate_ruby ( 'factorial(5)' ) ) . to eq ( factorial ( 5 ) )
109109 end
110110
111+ it "can load isomorphic code after loading" do
112+ on_client do
113+ CONSTANT = 1
114+ end
115+ CONSTANT = 1
116+ isomorphic do
117+ def factorial ( n )
118+ n ==CONSTANT ? CONSTANT : n * factorial ( n -CONSTANT )
119+ end
120+ nil
121+ end
122+ expect ( evaluate_ruby ( 'factorial(5)' ) ) . to eq ( factorial ( 5 ) )
123+ end
124+
111125 context 'promise helpers' do
112126 # just to demonstrate a few things:
113127 # 1 - You can use methods like mount, isomorphic, on_client in before(:each) blocks
You can’t perform that action at this time.
0 commit comments