2323require 'base64'
2424
2525class TablesController < ApplicationController
26- before_action :sanitize_scope
27-
2826 def index
2927 return unless authorization ( 'system' )
30- render json : Table . all ( params [ :scope ] )
28+ scope = sanitize_params ( [ :scope ] )
29+ return unless scope
30+ scope = scope [ 0 ]
31+ render json : Table . all ( scope )
3132 end
3233
3334 def binary
3435 return unless authorization ( 'system' )
36+ scope , binary , definition , table = sanitize_params ( [ :scope , :binary , :definition , :table ] , require_params : false , allow_forward_slash : true )
37+ return unless scope
3538 begin
36- file = Table . binary ( params [ : scope] , params [ : binary] , params [ : definition] , params [ : table] )
39+ file = Table . binary ( scope , binary , definition , table )
3740 results = { 'filename' => file . filename , 'contents' => Base64 . encode64 ( file . contents ) }
3841 render json : results
3942 rescue Table ::NotFound => e
@@ -44,8 +47,10 @@ def binary
4447
4548 def definition
4649 return unless authorization ( 'system' )
50+ scope , definition , table = sanitize_params ( [ :scope , :definition , :table ] , require_params : false , allow_forward_slash : true )
51+ return unless scope
4752 begin
48- file = Table . definition ( params [ : scope] , params [ : definition] , params [ : table] )
53+ file = Table . definition ( scope , definition , table )
4954 render json : { 'filename' => file . filename , 'contents' => file . contents }
5055 rescue Table ::NotFound => e
5156 render ( json : { status : 'error' , message : e . message } , status : 404 ) and
@@ -55,8 +60,10 @@ def definition
5560
5661 def report
5762 return unless authorization ( 'system' )
63+ scope , binary , definition , table = sanitize_params ( [ :scope , :binary , :definition , :table ] , require_params : false , allow_forward_slash : true )
64+ return unless scope
5865 begin
59- file = Table . report ( params [ : scope] , params [ : binary] , params [ : definition] , params [ : table] )
66+ file = Table . report ( scope , binary , definition , table )
6067 render json : { 'filename' => file . filename , 'contents' => file . contents }
6168 rescue Table ::NotFound => e
6269 render ( json : { status : 'error' , message : e . message } , status : 404 ) and
@@ -66,17 +73,19 @@ def report
6673
6774 def body
6875 return unless authorization ( 'system' )
76+ scope , name = sanitize_params ( [ :scope , :name ] , require_params : true , allow_forward_slash : true )
77+ return unless scope
6978 # body doesn't raise if not found ... it returns nil
70- file = Table . body ( params [ : scope] , params [ : name] )
79+ file = Table . body ( scope , name )
7180 if file
7281 results = { }
7382
74- if File . extname ( params [ : name] ) == '.txt'
83+ if File . extname ( name ) == '.txt'
7584 results = { 'contents' => file }
7685 else
77- locked = Table . locked? ( params [ : scope] , params [ : name] )
86+ locked = Table . locked? ( scope , name )
7887 unless locked
79- Table . lock ( params [ : scope] , params [ : name] , username ( ) )
88+ Table . lock ( scope , name , username ( ) )
8089 end
8190 results = { 'contents' => Base64 . encode64 ( file ) , 'locked' => locked }
8291 end
@@ -91,8 +100,10 @@ def body
91100
92101 def load
93102 return unless authorization ( 'system' )
103+ scope , binary , definition = sanitize_params ( [ :scope , :binary , :definition ] , require_params : false , allow_forward_slash : true )
104+ return unless scope
94105 begin
95- render json : Table . load ( params [ : scope] , params [ : binary] , params [ : definition] )
106+ render json : Table . load ( scope , binary , definition )
96107 rescue Table ::NotFound => e
97108 render ( json : { status : 'error' , message : e . message } , status : 404 ) and
98109 return
@@ -101,8 +112,10 @@ def load
101112
102113 def save
103114 return unless authorization ( 'system' )
115+ scope , binary , definition = sanitize_params ( [ :scope , :binary , :definition ] , require_params : false , allow_forward_slash : true )
116+ return unless scope
104117 begin
105- Table . save ( params [ : scope] , params [ : binary] , params [ : definition] , params [ :tables ] )
118+ Table . save ( scope , binary , definition , params [ :tables ] )
106119 head :ok
107120 rescue Table ::NotFound => e
108121 render ( json : { status : 'error' , message : e . message } , status : 404 ) and
@@ -112,8 +125,10 @@ def save
112125
113126 def save_as
114127 return unless authorization ( 'system' )
128+ scope , name , new_name = sanitize_params ( [ :scope , :name , :new_name ] , require_params : true , allow_forward_slash : true )
129+ return unless scope
115130 begin
116- Table . save_as ( params [ : scope] , params [ : name] , params [ : new_name] )
131+ Table . save_as ( scope , name , new_name )
117132 head :ok
118133 rescue Table ::NotFound => e
119134 render ( json : { status : 'error' , message : e . message } , status : 404 ) and
@@ -123,8 +138,10 @@ def save_as
123138
124139 def generate
125140 return unless authorization ( 'system' )
141+ scope , definition = sanitize_params ( [ :scope , :definition ] , require_params : false , allow_forward_slash : true )
142+ return unless scope
126143 begin
127- filename = Table . generate ( params [ : scope] , params [ : definition] )
144+ filename = Table . generate ( scope , definition )
128145 render json : { 'filename' => filename }
129146 rescue Table ::NotFound => e
130147 render ( json : { status : 'error' , message : e . message } , status : 404 ) and
@@ -134,40 +151,32 @@ def generate
134151
135152 def lock
136153 return unless authorization ( 'system' )
137- Table . lock ( params [ :scope ] , params [ :name ] , username ( ) )
154+ scope , name = sanitize_params ( [ :scope , :name ] , require_params : true , allow_forward_slash : true )
155+ return unless scope
156+ Table . lock ( scope , name , username ( ) )
138157 render status : 200
139158 end
140159
141160 def unlock
142161 return unless authorization ( 'system' )
143- locked_by = Table . locked? ( params [ :scope ] , params [ :name ] )
144- Table . unlock ( params [ :scope ] , params [ :name ] ) if username ( ) == locked_by
162+ scope , name = sanitize_params ( [ :scope , :name ] , require_params : true , allow_forward_slash : true )
163+ return unless scope
164+ locked_by = Table . locked? ( scope , name )
165+ Table . unlock ( scope , name ) if username ( ) == locked_by
145166 render status : 200
146167 end
147168
148169 def destroy
149170 return unless authorization ( 'system' )
171+ scope , name = sanitize_params ( [ :scope , :name ] , require_params : true , allow_forward_slash : true )
172+ return unless scope
150173 # destroy returns no indication of success or failure so just assume it worked
151- Table . destroy ( params [ : scope] , params [ : name] )
174+ Table . destroy ( scope , name )
152175 OpenC3 ::Logger . info (
153- "Table destroyed: #{ params [ : name] } " ,
154- scope : params [ : scope] ,
176+ "Table destroyed: #{ name } " ,
177+ scope : scope ,
155178 user : username ( )
156179 )
157180 head :ok
158181 end
159-
160- private
161-
162- def sanitize_scope
163- # scope is passed as a parameter and we use it to create paths in local_mode,
164- # thus we have to sanitize it or the code scanner detects:
165- # "Uncontrolled data used in path expression"
166- # This method is taken directly from the Rails source:
167- # https://api.rubyonrails.org/v5.2/classes/ActiveStorage/Filename.html#method-i-sanitized
168- scope = params [ :scope ] . encode ( Encoding ::UTF_8 , invalid : :replace , undef : :replace , replace : "�" ) . strip . tr ( "\u{202E} %$|:;/\t \r \n \\ " , "-" )
169- if scope != params [ :scope ]
170- render ( json : { status : 'error' , message : "Invalid scope: #{ params [ :scope ] } " } , status : 400 )
171- end
172- end
173182end
0 commit comments