I have a problem here in obtaining the Google+ profile-picture-url from the profile-picture-json. I'm quite a beginner and this is my first webapp so please take this into account.
My callback function:
def callback(self):
self.validate_oauth2callback()
oauth_session = self.service.get_auth_session(
data={'code': request.args['code'],
'grant_type': 'authorization_code',
'redirect_uri': self.get_callback_url()
},
decoder=jsondecoder
)
me = oauth_session.get('').json()
social_id = 'google$' + me['sub']
username = me.get('name', None) if me.get('name', None) else me['email'].split('#')[0]
email = me['email'] if me['email_verified'] == True else None
url = me.get('profile', None)
image_json = 'https://www.googleapis.com/plus/v1/people/' + me['sub'] + '?fields=image&key=AIz..yAl..juCqj..sjj9y..PuM..R..9..F8p..mo'
image = image_json['image'] # <-- THIS DOESN'T WORK
return social_id, username, email, url, image, me
My problem is that the variable image_json contains the following:
{
"image": {
"url": "https://lh6.googleusercontent.com/-f..i0..dl..Gc/AAAAAAAAAAI/AAAAAAAAABQ/iNw-IEz...o/photo.jpg?sz=50",
"isDefault": false
}
}
and I have to extract the profile-picture-url from that. A substring method doesn't work since in order to get that code I have to "run" the url saved in image_json.
What I need is something like image = image_json['image'] to retrieve the string:
"https://lh6.googleusercontent.com/-f..i0..dl..Gc/AAAAAAAAAAI/AAAAAAAAABQ/iNw-IEz...o/photo.jpg?sz=50"
and I would like to change that size in 256 instead of 50.
I have followed many posts but I didn't found a solution for this thing.
The view that will call this function is the following:
#auth.route('/callback/<provider>')
def oauth_callback(provider):
oauth = OAuthSignIn.get_provider(provider)
social_id, username, email, url, image, jsonme = oauth.callback()
if social_id is None:
flash('Authentication failed! Access to ' + provider + ' denied.')
return redirect(url_for('main.home'))
user = User.query.filter_by(email=email).first()
if not user:
user = User(social_id=social_id, username=username, email=email, social_page=url, social_image=image)
db.session.add(user)
db.session.commit()
else:
...
login_user(user, True)
return redirect(url_for('main.home'))
Related
i used Canvas api to call for information such as user ID, log in and log out time...but the APIs can only call for one user at a time, so i made this code to first call for a list of user IDs:
import requests
import json
def get_all_time_entries():
url_address = "mywebsite.com/api/v1/courses/1111/users?per_page=50"
headers = {"Authorization": "Bearer " + "this is my bearer"
}
all_time_entries = []
for page in range(1,15):
url = "mywebsite.com/api/v1/courses/1111/users?per_page=50&page="+str(page)
response = requests.get(url=url, headers=headers).json()
all_time_entries.append(response)
return all_time_entries
print(get_all_time_entries())
I've managed to call for a list of users like this:
{
"created_at": "time",
"email": "email",
"id": ID number, (***)
"integration_id": null,
"login_id": "email",
"name": "Name",
"short_name": "Name ",
"sis_import_id": 111,
"sis_user_id": "Name ",
"sortable_name": ", Name "
},
Now i want to use a new loop to call for API with this link: mywebsite.com/api/v1/audit/authentication/users/:user_id (:user_id are the IDs got in the last api call of mine, marked with (***)) and get all the information to a list. How should i use loop with all those IDs?
i've managed to find a solution for calling next APIs based on the value i got from the previous list with this code:
import requests
import json
def get_all_time_entries():
url = "mywebsite.com/api/v1/courses/1111/users?per_page=50"
headers = {
"Authorization": "Bearer " + "this is my bearer",}
uri = "mywebsite.com/api/v1/audit/authentication/users/"
result = []
all_time_entries = []
# loop through all pages and return list of users of certain pages
for page in range(1,15):
url = "mywebsite.com/api/v1/courses/1111/users?per_page=50&page="+str(page)
response = requests.get(url=url, headers=headers).json()
all_time_entries.append(response)
return all_time_entries
# Search for id value in all_time_entries
value = [res['id'] for res in all_time_entries]
# Loop through user log in api call by 'id'
for x in value:
url = "mywebsite.com/api/v1/audit/authentication/users/"+str(x)
callback = requests.get(url=url, headers=headers).json()
result.append(callback)
return result
print(get_all_time_entries())
Now the problem is this code keeps returning the value of the "all_time_entries" not the "result" one. i've also tried to add a certain value for the list "all_time_entries" (with no loops and calls):
all_time_entries = [{'id': 11, 'name': 'name', 'created_at': '2021-01-23T22:34:30+07:00', 'sortable_name': ', name', 'short_name': 'name', 'sis_user_id': 'name#email.com', 'integration_id': None, 'sis_import_id': 1, 'login_id': 'name#email.com', 'email': 'name#email.com'}, {'id': 22, 'name': 'name2', 'created_at': '2021-01-23T22:34:19+07:00', 'sortable_name': ', name2', 'short_name': 'name2', 'sis_user_id': 'name2#email.com', 'integration_id': None, 'sis_import_id': 1, 'login_id': 'name2#email.com', 'email': 'name2#email.com'}]
...and it worked
So i dont know if this method cannot work with a very long list or something, and is there a way to work with long list?
I have a rails app running alongside with a rails API, there is a constant value for DAYS_LIMIT in config/initializers/constants.rb
DAYS_LIMIT = 40
DEFAULT_PRICE = 1.29
but now in the app i added an input field so that the user decide his DAYS_LIMIT.
So i want to fetch that value from the database from inside the API models.
I have placed breakpoints and can see that inside the API controller, the data is transfered from the app but not to the models.
edited as a question requested , it's a React-on-Rails app , here is the code where the new input field is save to the database (i have removed the other fields so the question look shorter)
export const saveChannel = (files) => {
return async (dispatch, getState) => {
const { channel } = getState();
const {rss_podcast_days} = channel;
const { image } = files;
const save = id ? updateChannel : createChannel;
const sub_required = subscription_required !== undefined ? subscription_required : false;
const formData = new FormData();
formData.append('channel[rss_podcast_days]', rss_podcast_days || '');
if (Object.keys(image).length) {
formData.append('channel[image]', image);
}
const channelId = await dispatch(save(formData, id));
dispatch(fetchChannel(id));
return id;
};
};
from the app controller
podcast_list = RestClient.get("#{ENV['URL_API']}/api/#{#channel.id.as_json}/podcast/list")
#podcasts = JSON.parse(podcast_list.body)
#podcasts = #podcasts.sort.reverse.to_h
this is from the API controller witch the data is transfered from the app
def index
podcasts = #channel.podcasts.published.list(params[:page], params[:items_per_page], params[:ordered_in])
render json: Podcasts::Normalizer.normalize(podcasts, #channel.station.default_podcast_price)
end
and here from the API model that i want to fetch data instead of the constants.
scope :by_days_limit, -> {with_tags.more_recent_than(Date.today - DAYS_LIMIT.days).ordered}
it should take today date minus the value (DAYS_LIMIT) from user input, but for now i get undefined local variable or method if i try to fetch directly
Bro if your class has constant like DAYS_LIMIT you can access it using that class itself for example,
class Demo
DAYS_LIMIT = 5
end
you can access that constant by Demo.DAYS_LIMIT in controller or else wherever you need it.
good luck!
ok , so i finally got it, i don't know if i should delete this thread or just tell how i did it. If it's inapropriate just tell me and i will delete this entire thread.
So here is how i did it, in the API controller i had to add my fetch so that the arguments (list) knows what i am talking about. #channel.days_limit
def index
podcasts = #channel.podcasts.published.list(params[:page], params[:items_per_page], params[:ordered_in], #channel.days_limit)
render json: Podcasts::Normalizer.normalize(podcasts, #channel.station.default_podcast_price)
end
then in the def list of the models, i added days_limit has argument
def list(page = nil, nb_items_per_page = 40, ordered_in = 'desc', days_limit)
ordered_in = ordered_in.in?(['asc', 'desc']) ? ordered_in : 'desc'
page.blank? ? by_days_limit(days_limit) : by_page(page, nb_items_per_page, ordered_in)
end
and finally in the scope of the models, i pass in the new argument
scope :by_days_limit, -> (days_limit) {with_tags.more_recent_than(Date.today - days_limit.days).ordered}
Now the user input from the app is passing to the models via the controller.
In my application, I need to do API-call to a client in order to get information about a product (I do it by giving product_id).
Their API only allows 1 ID at a time which would make the job many times harder.
what have in mind is to run the API-call several times and add the results to the view.
I did a small test with merging 2 JSON together, which worked fine. Example:
#products = data_1['data'] + data_2['data']
This was, of course, doing them by hand and simple. What I thought I could do was to do an each do on them and run the code, as below:
### CONTROLLER
product_id = Array(params[:product_id].split(','))
product_id.each do |id|
uri = URI.parse("https://website.com/api?product_id=#{id}")
request = Net::HTTP::Get.new(uri)
request["Accept"] = "application/json"
req_options = { use_ssl: uri.scheme == "https", }
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
data = JSON.parse(response.body)
#products = data['data']
end
### VIEW
- #products.each do |product|
%p= product.name
%p= product.date
This doesn't give me any error, but in my view, I only see details for last product_id param. Same with if I move #products = data['data'] out of the each do.
In a desperate attempt, I also tried with this with no luck:
#products = id.as_json.merge(data['data'])
Any help is appreciated!
The answer was much closer to what I had in mind. I need to run map on the variable itself, like below:
### CONTROLLER
product_id = Array(params[:product_id].split(','))
#products = product_id.map { |id|
request = Net::HTTP::Get.new(uri)
request["Accept"] = "application/json"
req_options = { use_ssl: uri.scheme == "https", }
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
data = JSON.parse(response.body)
data['data']
}
hope it helps someone :)
I'm attempting to send an email our admin when new data is submitted to our website from the users. We are using a Django for the backend and Vue for the front end, even though that probably doesn't matter. Here is the code:
#receiver(post_save)
def send_update(sender, created, **kwargs):
if created:
data=kwargs['instance']
try:
if data.admin_approved == False:
print("point 1 reached")
name = data.submitted_by_name
body = data.body
content_type = str(sender).split(".")[2][:-2]
print("point 2 reached")
link = "https://link_to_website.com" + content_type.lower()
subject = "New " + content_type + " submitted"
print("point 3 reached")
from_email = "NoReply#web_site.com"
to_email = "my_email#address.com"
print("pre-html point reached")
html_message = get_template('./email/template.html')
text_message = get_template('./email/textplate.txt')
data = {
'user_name': name,
'submission': data.body,
'type': content_type,
'link': link,
'body': body
}
content_text = text_message.render(data)
content_html = html_message.render(data)
print("ready to send email!")
msg = EmailMultiAlternatives(subject, content_text, from_email, [to_email])
msg.attach_alternative(content_html, "text/html")
msg.send()
except:
print("Data was not submitted by an non-admin user.")
The try/except is included so that data that is submitted directly through the django admin page does not trigger the email function.
the function works up until "pre-html point reached", I'm guessing the issue is somewhere within the msg and msg.send() but I am not receiving any error functions.
Thanks for the help!
so I'm new to ruby on rails and I'm having a problem with this if statement, basically what I'm checking for is if the confirmation token in the sql database exists for the email address logging in. If it does kick back a message your email isn't verified. Once you click the link in the email, it deletes the token in the database. Then you can proceed to login. I cant get it working for the life of me. Everything else works but the verification check. Thank you for your help !!!
def authenticate(email, password)
command = AuthenticateUser.call(email, password)
user = User.find_by email:(email)
confirmationtoken =
User.find_by_confirmation_token(params[:confirmation_token].to_s)
if user.present? && confirmationtoken.present?
render json: {error: 'Email not verified' }, status: :unauthorized
elsif command.success?
render json: {
access_token: command.result,
message: 'Login Successful'
}
else
render json: { error: command.errors }, status: :unauthorized
end
end
You can simply check whether the user's confirmation_token attribute is set:
user = User.find_by(email: email)
if user && user.confirmation_token.present?
# ...
elsif command.success?
# ...
else
# ...
end
user.confirmation_token.present? can be shortened to user.confirmation_token?
I think this will help clean up your logic since theres no need to do a user lookup twice. And looking up the user and using the object could cause security concern .. let AuthenticateUser find the user and get success if they're in the system. When you send an email off just build a button in the email with a link to an endpoint that will verify the email and set the confirmation token to nil.
def authenticate(email, password)
command = AuthenticateUser.call(email, password)
has_confirmation_token =
User.find_by_confirmation_token(params[:confirmation_token]).present?
if !has_confirmation_token && !command.success?
render json: {error: 'Email not verified' }, status: :unauthorized
elsif command && command.success?
render json: {
access_token: command.result,
message: 'Login Successful'
}
else
render json: { error: command.errors }, status: :unauthorized
end
end