307 def internal_request(route, opts={}, &block)
308 opts = opts.dup
309
310 env = {
311 'REQUEST_METHOD'=>'POST',
312 'PATH_INFO'=>'/'.dup,
313 "SCRIPT_NAME" => "",
314 "HTTP_HOST" => INVALID_DOMAIN,
315 "SERVER_NAME" => INVALID_DOMAIN,
316 "SERVER_PORT" => 443,
317 "CONTENT_TYPE" => "application/x-www-form-urlencoded",
318 "rack.input"=>StringIO.new(''),
319 "rack.url_scheme"=>"https"
320 }
321 env.merge!(opts.delete(:env)) if opts[:env]
322
323 session = {}
324 session.merge!(opts.delete(:session)) if opts[:session]
325
326 params = {}
327 params.merge!(opts.delete(:params)) if opts[:params]
328
329 scope = roda_class.new(env)
330 rodauth = new(scope)
331 rodauth.session = session
332 rodauth.params = params
333 rodauth.internal_request_block = block
334
335 unless account_id = opts.delete(:account_id)
336 if (account_login = opts.delete(:account_login))
337 if (account = rodauth.send(:_account_from_login, account_login))
338 account_id = account[rodauth.account_id_column]
339 else
340 raise InternalRequestError, "no account for login: #{account_login.inspect}"
341 end
342 end
343 end
344
345 if account_id
346 session[rodauth.session_key] = account_id
347 unless authenticated_by = opts.delete(:authenticated_by)
348 authenticated_by = case route
349 when :otp_auth, :sms_request, :sms_auth, :recovery_auth, :webauthn_auth, :webauthn_auth_params, :valid_otp_auth?, :valid_sms_auth?, :valid_recovery_auth?
350 ['internal1']
351 else
352 ['internal1', 'internal2']
353 end
354 end
355 session[rodauth.authenticated_by_session_key] = authenticated_by
356 end
357
358 opts.keys.each do |k|
359 meth = :"#{k}_param"
360 params[rodauth.public_send(meth).to_s] = opts.delete(k) if rodauth.respond_to?(meth)
361 end
362
363 unless opts.empty?
364 warn "unhandled options passed to #{route}: #{opts.inspect}"
365 end
366
367 rodauth.handle_internal_request(:"_handle_#{route}")
368 end