Facebook app review getting auto rejected for manages_pages feature - ruby-on-rails

I had earlier been provided permission for the feature Manage_pages. However, Facebook has changed it policies and this feature has been depreciated, moreover, my application wasn't using much of the Facebook feature. For these 2 reasons, my app has been disabled.
SO, i submitted a review for the same. The feedback is as such:
The main purpose of my app is to take payments through the client's Facebook page , for which earlier used Manage_pages feature. Now, even if i hit the connect button, it says "The app is in dev mode" . Am stuck here, how can i get the button to work and display a screen cast if I keep getting the same error. this seems like an endless while loop :(
Now, when i am trying to re-submit an app review, it seems to be getting auto rejected.
Any insight would be appreciated!
Here is my Facebook controller code
class FacebookController < ApplicationController
skip_before_action :verify_authenticity_token
skip_before_action :authorize
def connect
# get array of facebook pages added
page_ids = params[:tabs_added].keys
# create or update connection for each facebook page added
page_ids.each do |page_id|
page = FacebookPage.where(page_id: page_id).first_or_initialize
page.update!(slug_id: params[:slug_id], form_type: params[:form_type])
end
head :created
end
def show
request = parse_signed_request(params[:signed_request]).try(:[], 'page')
facebook_page = FacebookPage.find_by(page_id: request.try(:[], 'id'))
facebook_admin = request.try(:[], 'admin')
if facebook_page
redirect_to contribution_form_url(
subdomain: facebook_page.account_type,
id: facebook_page.slug.name,
form_type: facebook_page.form_type,
iframe: true,
facebook: true,
facebook_admin: facebook_admin,
facebook_page: facebook_page
)
else
render nothing: true
end
end
def update
facebook_page = FacebookPage.find(params[:id])
slug = Slug.find_by!(name: page_params[:form_slug], account_type: facebook_page.account_type)
if facebook_page.update!(slug: slug, form_type: page_params[:form_type])
redirect_to contribution_form_url(
subdomain: facebook_page.account_type,
id: facebook_page.slug.name,
form_type: facebook_page.form_type,
iframe: true,
facebook: true,
facebook_admin: true,
facebook_page: facebook_page
)
end
end
private
def parse_signed_request(signed_request)
# We only care about the data after the '.'
payload = signed_request.split('.')[1]
# Facebook gives us a base64URL encoded string.
# Ruby only supports base64 out of the box, so we have to add padding to make it work
payload += '=' * (4 - payload.length.modulo(4))
decoded_json = Base64.decode64(payload)
JSON.parse(decoded_json)
end
def page_params
params.require(:facebook_page).permit(:form_type, :form_slug)
end
end
and i am also attaching the the script which opens the facebook tab
<script>
function move_to_top( value )
{
$(".fb_dialog").each(function(index) {
if($(this).css("top")!='-10000px') {
$(this).css("top", value + 'px' );
}
});
setTimeout( ('move_to_top("'+value+'");'), 1250);
}
window.addToFacebook = function() {
// make sure logged in as user; not page
FB.login(function(loginResponse) {
// if they are correctly logged in as user
if (loginResponse.authResponse) {
// popup modal to add form to page
FB.ui({
method: 'pagetab',
display: 'popup'
}, function(response) {
// if tabs were added, make the connection
if (Object.keys(response.tabs_added).length > 0) {
console.log("inside")
response.form_type = $('[name=form_type]:checked').val().slice(0,1);
response.slug_id = '<%= Slug.find_by(name: slug, account_type: candidate.account_type).try(:id) || candidate.account_slug.id %>';
$.post('/facebook/connect', response);
$.magnificPopup.open({
items: {
src: '<%=j render "form_settings/facebook_success" %>',
type: 'inline'
}
});
}
});
$(".fbProfileBrowserResult").ready( function(){
t = setTimeout ( ('move_to_top("'+50+'")'), 1250 );
});
}
});
};
</script>
<p><%= link_to 'Connect with Facebook', '#', onclick: 'addToFacebook()', class: 'button' %></p>

Related

Server side Rails model validation in a React form

I am trying to validate User inputs on server side in a Rails Application with React as view. Basically I make axios calls to the Rails API like this:
const Script = props => {
const [script, setScript] = useState({})
const [scene, setScene] = useState({})
const [loaded, setLoaded] = useState(false)
useEffect(() => {
const scriptID = props.match.params.id
const url = `/api/v1/scripts/${scriptID}`
axios.get(url)
.then( resp => {
setScript(resp.data)
setLoaded(true)
})
.catch(resp => console.log(resp))
}, [])
const handleChange = (e) => {
e.preventDefault()
setScene(Object.assign({}, scene, {[e.target.name]: e.target.value}))
}
const handleSubmit = (e) => {
e.preventDefault()
const csrfToken = document.querySelector('[name=csrf-token]').content
axios.defaults.headers.common['X-CSRF-TOKEN'] = csrfToken
const script_id = script.data.id
axios.post('/api/v1/scenes', {scene, script_id})
.then(resp => {
const included = [...script.included, resp.data.data]
setScript({...script, included})
})
.catch(err => {
console.log(err.response.data.error)
})
.finally(() => {
setScene({name: '', description: ''})
})
}
All data gets passed into a react component with a form.
return (
<div className="wrapper">
{
loaded &&
<Fragment>
.
.
.
<SceneForm
handleChange={handleChange}
handleSubmit={handleSubmit}
attributes={script.data.attributes}
scene={scene}
/>
</Fragment>
}
</div>
)
In this form I have a name field and the corresponding name in Rails has a validation uniqueness: true. everything works fine if I enter a valid (unique) name.
I tried to implement a validation but I am not happy with the outcome. (It works in general: my no_errors? method does what is is supposed to do and I get a 403 status) This is the controller part:
def create
scene = script.scenes.new(scene_params)
if no_error?(scene)
if scene.save
render json: SceneSerializer.new(scene).serialized_json
else
render json: { error: scene.errors.messages }, status: 422
# render json: { error: scene.errors.messages[:name] }, status: 423
end
else
render json: { error: "name must be unique" }, status: 403
end
end
.
.
.
private
def no_error?(scene)
Scene.where(name: scene.name, script_id: scene.script_id).empty?
end
If I enter an existing name I get a console.log like this:
screenshot
Here is my concern: I am not happy with my approach of error handling in general. I do not want to get the 403 message logged to the console (I do want to avoid this message in the first place).
My idea is to take the "simple form" approach: Make the border of my field red and post an error message under the field, without any console output...
And on a side note: Is 403 the correct status? I was thinking about 422 but wasn't sure...
Thank you for your ideas in advance!
403 is the wrong status code. What you need is to return a 422 (unprocessable entity). 403 is more about policy and what you are authorized to do.
Then when you deal with http request it's a standard to have a request and status code printed in browser console. Not sur to get your issue here.
If it's about to display the error you could just have a function that colorize (or whatever fireworks you want) your input if the status code response is a 422.

jquery fileupload rails s3 shrine image upload error

I am sort of new to rails and I am trying to upload images directly to S3 with Shrine. I got direct uploads to S3 to work perfectly, however, when I introduced jquery file upload and upload an image, chrome console throws
this error
at me. I'm not sure what I'm doing wrong and I can't seem to find a solution anywhere online. I get that it's a presign error and it's probably not finding the cache link but I don't know how to resolve that.
EDIT: This was solved by including the presign code in the Routes file and altering the storage location in the uploads.js to the correct location. Now, however, I have an issue with the files being rolled back when they attempt to upload.
I'm using the cloud based ide C9,
This is my uploads.js file:
$(document).on("turbolinks:load", function(){
$("[type=file]").fileupload({
add: function(e, data) {
console.log("add", data);
data.progressBar = $('<div class="progress"><div class="determinate"
style="width: 70%"></div></div>').insertBefore("form")
var options = {
extension: data.files[0].name.match(/(\.\w+)?$/)[0], //set the
file extention
_: Date.now() //prevent caching
};
$.getJSON("/autos/upload/cache/presign", options, function(result) {
console.log("presign", result);
data.formData = result['fields'];
data.url = result['url'];
data.paramName = "file";
data.submit()
});
},
progress: function(e, data) {
console.log("progress", data);
var progress = parseInt(data.loaded / data.total * 100, 10);
var percentage = progress.toString() + '%'
data.progressBar.find(".progress-bar").css("width",
percentage).html(percentage);
},
done: function(e, data) {
console.log("done", data);
data.progressBar.remove();
var image = {
id: data.formData.key.match(/cache\/(.+)/)[1], // we have to
remove the prefix part
storage: 'cache',
metadata: {
size: data.files[0].size,
filename: data.files[0].name.match(/[^\/\\]+$/)[0], // IE return full
path
mime_type: data.files[0].type
}
}
form = $(this).closest("form");
form_data = new FormData(form[0]);
form_data.append($(this).attr("name"), JSON.stringify(image))
$.ajax(form.attr("action"), {
contentType: false,
processData: false,
data: form_data,
method: form.attr("method"),
dataType: "json"
}).done(function(data) {
console.log("done from rails", data);
});
}
});
});
My routes.rb file includes:
mount ImageUploader::UploadEndpoint => "/images/upload"
mount Shrine.presign_endpoint(:cache) => "/autos/upload/cache/presign"
I have a model which accepts these images as well as other fields called Autos, this is included in the Autos file:
include ImageUploader[:image]
My Autos Controller is:
class AutosController < ApplicationController
before_action :find_auto, only: [:show, :edit, :update, :destroy]
def index
#autos = Auto.all.order("created_at DESC")
end
def show
end
def new
#auto = current_user.autos.build
end
def create
#auto = current_user.autos.build(auto_params[:auto])
if #auto.save
flash[:notice] = "Successfully created post."
redirect_to autos_path
else
render 'new'
end
end
def edit
end
def update
if #auto.update(auto_params[:auto])
flash[:notice] = "Successfully updated post."
redirect_to auto_path(#auto)
else
render 'edit'
end
end
def destroy
#auto.destroy
redirect_to autos_path
end
private
def auto_params
params.require(:auto).permit(:title, :price, :description, :contact, :image, :remove_image)
end
def find_auto
#auto = Auto.find(params[:id])
end
end
Assuming your image_uploader.rb has the ImageUploader class defined and given that your presign endpoint is something like /autos/upload/cache/presign, your routes.rb should have the presign route defined like so:
mount ImageUploader.presign_endpoint(:cache) => '/autos/upload/cache/presign'
I hope this single change in the route file would make you able to get the presign object that should contain 3 keys: url, fields and headers
# GET /autos/upload/cache/presign
{
"url": "https://my-bucket.s3-eu-west-1.amazonaws.com",
"fields": {
"key": "cache/b7d575850ba61b44c8a9ff889dfdb14d88cdc25f8dd121004c8",
"policy": "eyJleHBpcmF0aW9uIjoiMjAxNS0QwMToxMToyOVoiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJzaHJpbmUtdGVzdGluZyJ9LHsia2V5IjoiYjdkNTc1ODUwYmE2MWI0NGU3Y2M4YTliZmY4OGU5ZGZkYjE2NTQ0ZDk4OGNkYzI1ZjhkZDEyMTAwNGM4In0seyJ4LWFtei1jcmVkZW50aWFsIjoiQUtJQUlKRjU1VE1aWlk0NVVUNlEvMjAxNTEwMjQvZXUtd2VzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotYWxnb3JpdGhtIjoiQVdTNC1ITUFDLVNIQTI1NiJ9LHsieC1hbXotZGF0ZSI6IjIwMTUxMDI0VDAwMTEyOVoifV19",
"x-amz-credential": "AKIAIJF55TMZYT6Q/20151024/eu-west-1/s3/aws4_request",
"x-amz-algorithm": "AWS4-HMAC-SHA256",
"x-amz-date": "20151024T001129Z",
"x-amz-signature": "c1eb634f83f96b69bd675f535b3ff15ae184b102fcba51e4db5f4959b4ae26f4"
},
"headers": {}
}
When upload starts, you will now find this object in developer console instead of the previous 404 not found error.
UPDATE
I think you are very close to the solution. In your create/update actions, use auto_params[:auto] instead of auto_params
You would also like to check the RoR guide on Association Basics for collection methods
I think you following the tutorial of gorails direct upload s3
in you gem file make sure you use the right roda version
gem 'roda', "~> 2.29.0"

Flash Message on Rails

this is my controller method
def purchase
if #item_point > current_user.points
flash.keep[:notice] = "You dont have enough points to buy this item"
else
flash.keep[:notice] = "You have successfully redeemed this items, Thanks for the purchase."
end
render :json => flash
p flash[:notice]
end
and in my javascript ajax function's success i have written
$(".purchaseBtm button").click(function() {
var button_id = this.id.split("-")[1];
$.ajax({
url: '/hhr/purchase',
data : {
button_id : button_id
},
success: function(response) {
console.log('message: <%= flash[:notice]%>');
$('.flash-msg').html('');
$('.flash-'+button_id).text('<%= flash[:notice]%>')
}
});
});
This ajax call goes on a button click which passes some values, with which #item_point is calculated.
Problem is in my terminal i'm getting the correct Flash message every time.
but in my Browser console sometimes i get the first flash message as correct and then the same flash message persists. I wont get the second flash message. But the terminal shows corectly(the p message.)
If this action is to only to render feedback message from server, then I would just render the hash containing the message, as there is no point to store it in special flash container.
if #item_point > current_user.points
message = "You dont have enough points to buy this item"
else
message = "You have successfully redeemed this items, Thanks for the purchase." }
end
render json: { notice: message }
Edit:
Then in your json use
success: function(response) {
console.log('message: ' + response.notice);
$('.flash-msg').html('');
$('.flash-'+button_id).text(response.notice)
}
Also remember to set type of ajax request to dataType: 'json'

Check username availability

I have a form to user login:
<%= form_tag(#action, :method => "post", :name => 'signup' ,:onSubmit => 'return validate();') do %>
<%= label_tag(:user, "Username:") %>
<%= text_field_tag(:user) %>
I want to check if there is the username in the database immediately after :user-field lost focus. I can override this event on the form with javascript, but I can not send Ruby-AJAX request from javascipt code.
Is there any way to check username without adding additional controls (buttons, links) on the form?
You can use some JavaScript (this one written with jQuery) for AJAX cheking:
$(function() {
$('[data-validate]').blur(function() {
$this = $(this);
$.get($this.data('validate'), {
user: $this.val()
}).success(function() {
$this.removeClass('field_with_errors');
}).error(function() {
$this.addClass('field_with_errors');
});
});
});
This JavaScript will look for any fields with attribute data-validate. Then it assings onBlur event handler (focus lost in JavaScript world). On blur handler will send AJAX request to the URL specified in data-validate attribute and pass parameter user with input value.
Next modify your view to add attribute data-validate with validation URL:
<%= text_field_tag(:user, :'data-validate' => '/users/checkname') %>
Next add route:
resources :users do
collection do
get 'checkname'
end
end
And last step create your validation:
class UsersController < ApplicationController
def checkname
if User.where('user = ?', params[:user]).count == 0
render :nothing => true, :status => 200
else
render :nothing => true, :status => 409
end
return
end
#... other controller stuff
end
For what reason can you not send an ajax request from javascript code?
The best way would be to send a GET ajax request when the focus is lost. The get request could then return true or false and your javascript could then reflect this on the page.
I answered this in another post.
It is a friendly way for validating forms if you do not want to write it all from scratch using an existing jquery plugin. Check it out and if you like it let me know!
Check username availability using jquery and Ajax in rails
The solution that #Viacheslav has, works fine and my answer is a combination of his and my own changes (especially JS) part.
We will be using Ajax in order to achieve this.
Lets first create our function in the controller
def checkname
if !User.find_by_display_name(params[:dn])
render json: {status: 200}
else
render json: {status: 409}
end
return
end
and then adding our routes in routes.rb
resources :yourcontroller do
collection do
get 'checkname'
end
end
Now lets gets our hand on the view. Below you'll see the input:
.field
= f.text_field :display_name, onblur: "checkDisplayName.validate(this.value)"
%p.error-name.disp-none username exists
And now by help of JSwe get the magic rolling. Blow JS has few functions. validate does the actually validation. getStatus is our Ajax call to get the status and we use showError & disableSubmitButton to our form a bit more production ready to show errors and disabling the submit button.
var checkDisplayName = {
validate: function(dn){
checkDisplayName.getStatus(dn).then(function(result) {
if (!!result){
if (result.status != 200){
checkDisplayName.disableSubmitButton(true);
checkDisplayName.showError();
} else{
checkDisplayName.disableSubmitButton(false);
}
}
});
return false;
},
getStatus: async (dn) => {
const data = await fetch("/pages/checkname?dn=" + dn)
.then(response => response.json())
.then(json => {
return json;
})
.catch(e => {
return false
});
return data;
},
showError: function() {
let errEl = document.getElementsByClassName('error-name')[0];
if (!!errEl) {
errEl.classList.remove("disp-none");
window.setTimeout(function() { errEl.classList.add("disp-none"); },3500);
}
},
disableSubmitButton: function(status){
let button = document.querySelector('[type="submit"]');
button.disabled = status;
}
};

Why is AJAX in Rails 3 so hard? Or, what am I doing wrong?

None of the tutorials I seem do what I'm trying to do. Very simply, I want a user to be able to submit a POST request to a controller (to "LIKE" a video) and have the controller respond back with a JSON object. Any help would be appreciated.
Thanks
EDIT Because SO is messing the formatting up, here is a gist of my code too:
https://gist.github.com/813503
Here is my controller:
class LikesController < ApplicationController
before_filter :get_ids
respond_to :json, :js
def videolink
results = {}
# check to see if the user has liked this videolink before
if current_user
liked = Like.video?(current_user, #vid_id)
results["status"] = "OK"
results["liked"] = liked
else
results["status"] = "Error"
results["message"] = "User not logged in"
end
respond_with( results.to_json )
end
def update
results = {}
if current_user
results["status"] = "OK"
else
results["status"] = "Error"
results["message"] = "User not logged in"
end
respond_with( results.to_json )
end
private
def get_ids
#vid_id = params[:videolink_id]
end
end
Here is my JS file:
$("#likeVideo").click(function() {
$.ajax({
contentType: "application/json",
data: { game_id: game_id, videolink_id: current_video["videolink"]["id"] },
dataType: "json",
type: "POST",
url: "/likes/" + game_id,
success: function(data) {
console.log("Success", data);
}
});
return false;
});
My routes:
resources :likes do
collection do
get "videolink"
end
member do
post :update
end
end
And here is the error I get:
NoMethodError
in LikesController#update
undefined method `{"status":"OK"}_url' for #<LikesController:0x0000010178be58>
If you want to send back custom JSON, Instead of respond_with(results.to_json)... just render the text
render :text=>results.to_json
The responds_with is a way for you to easily send back objects, with their location (url). So that's why your error is telling you that that '_url' is invalid.
More info on responds_with, courtesy of http://ryandaigle.com/articles/2009/8/10/what-s-new-in-edge-rails-default-restful-rendering
If another format was requested, (i.e.
:xml or :json)
If it was a GET request, invoke the :to_format method on the resource and
send that back
If the resource has validation errors, send back the errors in the
requested format with the
:unprocessable_entity status code
If it was a POST request, invoke the :to_format method on the resource
and send that back with the :created
status and the :location of the new
created resource
Else, send back the :ok response with no body

Resources