Files saved by carrierwave is being gotten visible to users not logged in - mysql

Current Detail
[Env]
nginx puma mysql
Rails == 5.1.5
I mounted carrierwave to upload pictures and files in a post.
[Case]
Users not logged in type the file URL in browser, then they can access and view the file.
[Ideal]
Only users logged in is accessible to the file.
The file path is "uploads/post/images/1234(post_id)/sample.png".
So far, I locate uploads directory under public, app/assets/, and root directory in vain.
Any answers or suggestions are appreciated.
Source
Rails.application.routes.draw do
get 'users/index'
get 'users/show'
get 'posts/index'
devise_for :users, module: :users
resources :users, :only => [:index, :show]
get "/" => "posts#index"
get "posts/like_ranking" => "posts#like_rank"
get "posts/post_count_ranking" => "posts#post_count"
get "posts/tags_search" => "posts#tags_search"
get "posts/new" => "posts#new"
get "posts/:id/reply" => "posts#new"
post "posts/create" => "posts#create"
get "posts/:id" => "posts#show"
get "posts/:id/edit" => "posts#edit"
post "posts/:id/update" => "posts#update"
post "posts/:id/destroy" => "posts#destroy"
get 'tags/:tag', to: 'posts#index', as: :tag
get "users/:id/likes" => "users#likes"
get "users/:id/reply" => "users#reply"
resources :posts, only: %w(index)
resources :posts, shallow: true do
resources :likes, only: [:create, :destroy]
end
end
"
class ImageUploader < CarrierWave::Uploader::Base
# Choose what kind of storage to use for this uploader:
storage :file
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end

All assets under the public folder is served by nginx. In order to make it available for logged users you can first upload files to other directory than public and create action which serve files by Rails app from that directory and check if users logged before serving.

Related

Nested controllers Form_with Devise Error

So, I have a RailsApp and I decided to do a nested controller to my users called backoffice.
My routes to index are working fine, but when I try to edit or create a user, I get the following error:
NoMethodError in Backoffice::Users#new
undefined method `users_path' for #<#
<Class:0x007efc6d4fd1c8>:0x007efc6cd38708>
Did you mean? user_session_path
Here are my routes:
Rails.application.routes.draw do
resources :advertises
resources :categories
devise_for :users
namespace :backoffice do
resources :users, except: [:show]
end
end
I'm using Rails 5.1.4, so the 'form_tag' and 'form_for' are replaced for the 'form_with'
Here are my _form.html.erb where are my problem:
<%= form_with(model: user, root: true) do |form| %>
The structure of the controller is
class Backoffice::UsersController < BackofficeController
before_action :set_user, only: [:show, :edit, :update, :destroy]
before_action :pundit_user
....
Could the problem be with devise? Or it's just a nested controller error?
You should probably move the devise_for call into the :backoffice namespace as that is where the users resource is located.
If you run rails routes in the command line you will see the problem. Devise is trying to call users_path but that doesn't exist, what exists is backoffice_users_path

mysql Databases how can I fix this?

Hi Im trying to set up a database to store emails using ruby, sinatra, ActiveRecord, and mysql. Any suggestions on what im doing wrong? Im trying to output it to a seperate page that only i can see and then post it using a url on hostgator.
require 'sinatra'
require 'activerecord'
# require 'sinatra-activerecord'
get '/' do
erb :index
end
def save_email (email)
file.print(email)
end
get '/email' do
params[:email]
# # redirect '/'
end
post '/email' do
params[:email]
#email = params[:email]
erb :email, :locals => {:email => params[:email]}
end
# Change the following to reflect your database settings
ActiveRecord::Base.establish_connection(
adapter: 'mysql', # or 'postgresql'
host: 'localhost',
database: 'Stored_Emails',
)
class Stored_Emails < Sinatra::Application
end
class Stored_Emails < ActiveRecord::Base
end
ActiveRecord::Migration.create_table :email do |t|
t.string :emails
end
create_table :emails, force: true do |t|
t.string :email
t.belongs_to :email, index: true
end
get '/email' do
params[:email].all
end
Typically you break out your code into multiple files (we use folders named config, helpers, libraries, views, routes, models, migrations) and require them at the top of your app. However, if you want to put it in the same file and just use that and a Gemfile and Gemfile.lock that'll work too. Here's how it might look:
# Require your gems
require 'sinatra'
require 'activerecord'
# Libraries
# Models
class Stored_Emails < ActiveRecord::Base
end
# Configuration
# Change the following to reflect your database settings
ActiveRecord::Base.establish_connection(
adapter: 'mysql', # or 'postgresql'
host: 'localhost',
database: 'Stored_Emails'
)
ActiveRecord::Migration.create_table :email do |t|
t.string :emails
end
# Migrations
create_table :emails, force: true do |t|
t.string :email
end
# Helpers
def save_email (email)
file.print(email)
end
# Routes
get '/' do
# Load whatever you want to show in your index page into class variables
erb :index
end
get '/email' do
Stored_Emails.all.to_json
end
post '/email' do
#email = Stored_Emails.find_by(params[:email])
erb :email
end
Now you're going to have to do a good bit of work to get this running. Here's what I suggest you read:
1) Sinatra documentation - http://www.sinatrarb.com/intro.html
routes
running your sinatra app
views with ERB
2) Bundler documentation for gems - http://bundler.io/
3) ActiveRecord documentation - http://guides.rubyonrails.org/active_record_basics.html
Connecting to a database Creating your database with a migration -
this is a one time deal Querying the database
Good Luck!

rspec routing with subdomain

I'm having a Rails 5 api only app using rspec and versioned this way :
app
- controllers
- api
- v1
- users_controller.rb
My api/v1/users_controller.rb :
module Api::V1
class UsersController < ApiController
My config\routes.rb :
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
constraints subdomain: 'api' do
scope module: 'api' do
namespace :v1 do
resources :users
end
end
end
end
When I check the routes with rails routes it shows me.
Prefix Verb URI Pattern Controller#Action
v1_users GET /v1/users(.:format) api/v1/users#index {:subdomain=>"api"}
POST /v1/users(.:format) api/v1/users#create {:subdomain=>"api"}
v1_user GET /v1/users/:id(.:format) api/v1/users#show {:subdomain=>"api"}
PATCH /v1/users/:id(.:format) api/v1/users#update {:subdomain=>"api"}
PUT /v1/users/:id(.:format) api/v1/users#update {:subdomain=>"api"}
DELETE /v1/users/:id(.:format) api/v1/users#destroy {:subdomain=>"api"}
My spec file :
require "rails_helper"
RSpec.describe Api::V1::UsersController, type: :routing do
describe "routing" do
it "routes to #index" do
expect(:get => "/v1/users").to route_to("api/v1/users#index")
end
it "routes to #create" do
expect(:post => "/v1/users").to route_to("api/v1/users#create")
end
it "routes to #show" do
expect(:get => "/v1/users/1").to route_to("api/v1/users#show", :id => "1")
end
it "routes to #update via PUT" do
expect(:put => "/v1/users/1").to route_to("api/v1/users#update", :id => "1")
end
it "routes to #update via PATCH" do
expect(:patch => "/v1/users/1").to route_to("api/v1/users#update", :id => "1")
end
it "routes to #destroy" do
expect(:delete => "/v1/users/1").to route_to("api/v1/users#destroy", :id => "1")
end
end
end
But when I'm testing my routes with rspec it fails as it.
bundle exec rspec spec/routing/users_routing_spec.rb
FFFFF
Failures:
1) Api::V1::UsersController routing routes to #index
Failure/Error: expect(:get => "/v1/users").to route_to("api/v1/users#index")
No route matches "/v1/users"
# ./spec/routing/users_routing_spec.rb:7:in `block (3 levels) in <top (required)>'
I don't understand why. Any idea ?
You have to specify "subdomain" for your spec.
before do
Rails.application.routes.default_url_options[:host] = 'test.host'
end
it "routes to #index" do
expect(:get => v1_users_url).to route_to('v1/users#index', subdomain: 'api')
end

how to change name folder frontend and backend in yii2?

Currently my url is http://localhost/halodocnew/frontend/web/index.php?r=site%2Flogin I want to change name folder frontend to client for all action.
Please help me
Thank all so much
Suppose you want to rename backend to admin the follow the following steps
1)Rename backend folder to admin
2)Update Bootstrap.php under common/config/Bootstrap.php
Yii::setAlias('#backend', dirname(dirname(__DIR__)) . '/backend');
To
Yii::setAlias('#admin', dirname(dirname(__DIR__)) . '/admin');
3)Update site controller namespace under admin/controller/siteController.php backend\controllers; to namespace admin\controllers;
4) Update main.php ubder admin/config
'controllerNamespace' => 'backend\controllers' to 'controllerNamespace' => 'admin\controllers'
For Quick solution:
Copy and Paste your frontend folder in same directory and rename it to client
Open halodocnew\common\config\bootstrap.php
Add alias: Yii::setAlias('client', dirname(dirname(__DIR__)) . '/client');
Access in browser:
http://localhost/halodocnew/client/web/index.php
Another Solution:
Go into halodocnew\environments\dev\
Copy & Paste frontend in this folder and rename it to client.
Then go to halodocnew\environments\prod\
Copy & Paste frontend in this folder and rename it to client.
Open halodocnew\environments\index.php
Find 'Development' => [
'path' => 'dev',
'setWritable' => [
'backend/runtime',
'backend/web/assets',
Add 'Development' => [
'path' => 'dev',
'setWritable' => [
'backend/runtime',
'backend/web/assets',
'client/runtime',
'client/web/assets',
Do same above for 'Production' => [
'path' => 'prod',
Go into your project root directory and run php init
Copy web and veiws folder from frontend to client
Open halodocnew\common\config\bootstrap.php
Add alias: Yii::setAlias('client', dirname(dirname(__DIR__)) . '/client');
Open browser and access your desired directory http://localhost/halodocnew/client/web/index.php
I don't think it is sooper dooper solution but I used these methods =:)

How to use multiple databases for one rails 3.1 app in Heroku?

My Rails 3.1 application connects to 2 databases, one is the default, the other is an Amazon RDS MYSQL instance.
The current database.yml contains two production database connections. The models that need to pull from the second database simply use
establish_connection "production_on_amazon"
Unfortunately Heroku overwrites your database.yml, and only seems to inlcude one database connection. Does anyone know how I can add or configure my second?
Running "heroku config" I can see there are 2 DB's listed but cant seem to configure to connect to both. Perhaps somehow set my default to the SHARED_DATABASE_URL db on Heroku and set the alternate to the DATABASE_URL which points to Amazon...
Working off of the previous responses, but incorporating some Rails 3 advantages with the configuration and simplifying the parsing...
# config/application.rb
module MyApp
class Application < Rails::Application
... other configs
config.secondary_database_url = ENV['SECONDARY_DB_URL']
end
end
We may want to override this in development / test
# config/environments/development.rb
module MyApp
class Application < Rails::Application
... other configs
config.secondary_database_url = 'SOME_CONNECTION_STRING'
end
end
Now to setup the class we'll have our models inherit from...
# lib/active_record/secondary.rb
module ActiveRecord
class Secondary < ActiveRecord::Base
self.abstract_class = true
# prior to AR 3.2.1
url = URI.parse( MyApp::Application.config.secondary_database_url )
establish_connection(
:adapter => 'mysql',
:host => url.host,
:username => url.userinfo.split(':')[0],
:password => url.userinfo.split(':')[1],
:database => url.path[1..-1],
:port => url.port || 3306
)
# as of AR 3.2.1
establish_connection(MyApp::Application.config.secondary_database_url)
end
class SecondaryMigration < ActiveRecord::Migration
def connection
ActiveRecord::Secondary.connection
end
end
end
Heroku will always connect your app to the production DB that they create for you. If you want to make an additional connection you'll need to do this in your code manually, and create a ENV var that the code can use as a connection string.
Anything in the production segment of database.yml is binned by Heroku and replaced.
Regarding Neil's answer, here is a way to do it. Not an out-of-box solution, but might give you an idea...
/lib/active_record_extensions.rb
module ActiveRecordExtensions
class Shard < ActiveRecord::Base
#need to switch to the shard database connection from heroku config
primary_database_url = ENV['PRIMARY_DATABASE_URL']
if(!primary_database_url.nil?)
parsed_connection_string = primary_database_url.split("://")
adapter = parsed_connection_string[0]
parsed_connection_string = parsed_connection_string[1].split(":")
username = parsed_connection_string[0]
parsed_connection_string = parsed_connection_string[1].split("#")
password = parsed_connection_string[0]
parsed_connection_string = parsed_connection_string[1].split("/")
host = parsed_connection_string[0]
database = parsed_connection_string[1]
establish_connection(
:adapter => adapter,
:host => host,
:username => username,
:password => password,
:database => database,
:port => 3306,
:pool => 5,
:timeout => 5000
)
else
self.establish_connection "shard_#{Rails.env}"
end
end
class ShardMigration < ActiveRecord::Migration
def connection
ActiveRecord::Shard.connection
end
end
end
So your model should just extend ActiveRecord::Shard instead of Base