Sending request to reCAPTCHA Enterprise API fails - python

I am trying to create ReCaptcha assessment using their REST API in my backend server.
From reading the documentation, I understand that the request body contains an instance of Assesment, but when I try to send a request, I receive the following error:
TypeError: Object of type Assessment is not JSON serializable
My code:
import requests
from google.cloud import recaptchaenterprise_v1
from google.cloud.recaptchaenterprise_v1 import Assessment
def create_assessment(project_id: str, recaptcha_site_key: str, token: str, recaptcha_action: str, apiKey:str):
# Create event object
event = recaptchaenterprise_v1.Event()
event.site_key = recaptcha_site_key
event.token = token
# Create assesment object
assessment = recaptchaenterprise_v1.Assessment()
assessment.event = event
# Set project name
project_name = "projects/"+project_id
response = requests.post(url="https://recaptchaenterprise.googleapis.com/v1/"+project_name+"/assessments?key="+apiKey, json=assessment)
return response
I tried to convert the assesment to JSON using dumps(), but I had no success.
I've also tried to write it as "skinny JSON" like so:
assessment = {
'event': {
'token': token,
'siteKey': recaptcha_site_key,
'expectedAction': 'LOGIN'
}
}
Even though I receive status code 200, it indicates that my request is MALFORMED, probably because I don't include some recaptchaenterprise_v1 objects that should be on the assesment.

Try to use the CreateAssessmentRequest to create the request instead, like so:
client = recaptchaenterprise_v1.RecaptchaEnterpriseServiceClient()
project_name = "projects/"+project_id
# Build the assessment request.
request = recaptchaenterprise_v1.CreateAssessmentRequest()
request.assessment = assessment
request.parent = project_name
response = client.create_assessment(request)
You can find a more complete code sample in GCP's documentation.

Related

How to get the status of the pull request of an issue in jira via python

I am not able to understand how to fetch the status of the pull request via Python jira API.
I have gone through https://jira.readthedocs.io/en/latest/examples.html,
and searched the internet for it. But I was not able to link the jira issue with the pull request, I saw that the pull request is linked to jira issue id, but was not able to understand how to implement it.
I am using python 3.7
from jira import JIRA
issue = auth_jira.issue('XYZ-000')
pull_request = issue.id.pullrequest
I am getting this error:
AttributeError: 'str' object has no attribute 'pullrequest'
I am not sure how to access pullrequest data in jira.
Any leads would help.
I did something similar with another python wrapper for the jira-API: atlassian-python-api.
Look if it works in your case:
from atlassian import Jira
from pprint import pprint
import json
jira = Jira(
url='https://your.jira.url',
username=user,
password=pwd)
issue = jira.get_issue(issue_key)
# get the custom field ref of the "Development" field (I don't know if it's always the same):
dev_field_string = issue["fields"]["customfield_13900"]
# the value of this field is a huge string containing a json, that we must parse ourselves:
json_str = dev_field_string.split("devSummaryJson=")[1][:-1]
# we load it with the json module (this ensures json is converted as dict, i.e. 'true' is interpreted as 'True'...)
devSummaryJson = json.loads(json_str)
# the value of interest are under cachedValue/summary:
dev_field_dic = devSummaryJson["cachedValue"]["summary"]
pprint(dev_field_dic)
# you can now access the status of your pull requests (actually only the last one):
print(dev_field_dic['pullrequest']['overall']['state'])

How to design api implementation for web using flask restplus?

I am writing REST api in flask for the first time,
so now I have something like this:
import uuid
import pytz
from datetime import datetime
from flask_restplus import Resource, Api, fields
from ..models import publicip_schema
from ..controller import (
jsonified,
get_user_ip,
add_new_userIp,
get_specificIp,
get_all_publicIp
)
from flask import request, jsonify
from src import app
from src import db
from src import models
api = Api(app, endpoint="/api", versio="0.0.1", title="Capture API", description="Capture API to get, modify or delete system services")
add_userIp = api.model("Ip", {"ip": fields.String("An IP address.")})
get_userIp = api.model("userIp", {
"ipid": fields.String("ID of an ip address."),
"urlmap" : fields.String("URL mapped to ip address.")
})
class CaptureApi(Resource):
# decorator = ["jwt_required()"]
# #jwt_required()
#api.expect(get_userIp)
def get(self, ipid=None, urlmap=None):
"""
this function handles request to provide all or specific ip
:return:
"""
# handle request to get detail of site with specific location id.
if ipid:
ipobj = get_user_ip({"id": ipid})
return jsonified(ipobj)
# handle request to get detail of site based on site abbreviation
if urlmap:
locate = get_user_ip({"urlmap": urlmap})
return jsonified(locate)
return jsonify(get_all_publicIp())
# #jwt_required()
#api.expect(add_userIp)
def post(self, username=None):
"""
Add a new location.
URI /location/add
:return: json response of newly added location
"""
data = request.get_json(force=True)
if not data:
return jsonify({"status": "no data passed"}), 200
if not data["ip"]:
return jsonify({"status" : "please pass the new ip you want to update"})
if get_user_ip({"ipaddress": data["ip"]}):
return jsonify({"status": "IP: {} is already registered.".format(data["ip"])})
_capIpObj = get_user_ip({"user_name": username})
if _capIpObj:
# update existing ip address
if "ip" in data:
if _capIpObj.ipaddress == data["ip"]:
return jsonify({"status": "nothing to update."}), 200
else:
_capIpObj.ipaddress = data["ip"]
else:
return jsonify({
"status" : "please pass the new ip you want to update"
})
db.session.commit()
return jsonified(_capIpObj)
else:
device = ""
service = ""
ipaddress = data["ip"]
if "port" in data:
port = data["port"]
else:
port = 80
if "device" in data:
device = data["device"]
if "service" in data:
service = data["service"]
date_modified = datetime.now(tz=pytz.timezone('UTC'))
urlmap = str(uuid.uuid4().get_hex().upper()[0:8])
new_public_ip = add_new_userIp(username, ipaddress, port, urlmap, device, service, date_modified)
return publicip_schema.jsonify(new_public_ip)
api.add_resource(
CaptureApi,
"/getallips", # GET
"/getip/id/<ipid>", # GET
"/getip/urlmap/<urlmap>", # GET
"/updateip/username/<username>" # POST
)
I have faced two problems
if I specify
get_userIp = api.model("userIp", {
"ipid": fields.String("ID of an ip address."),
"urlmap" : fields.String("URL mapped to ip address.")
})
and add #api.expect(get_userIp) on get method above. I am forced to pass optional parameters with any value (even to get list of all ip's i.e. from "/getallips"): see screenshot below.
but these option parameters are not required tog et all IP's, but I do need to use those parameters to get ip based on ipid, or urlmap using the get method.
looking at swagger documentation generated by flask_restplus.Api I am seeing
get and post for all the endpoints, whereas I have defined endpoint get and post only. So technically updateip/username/<username> should not be listing get
How do I fix this ?
Good question! You can fix both problems by defining separate Resource subclasses for each of your endpoints. Here is an example where I split the endpoints for "/getallips", "/getip/id/", and "/getip/urlmap/".
Ip = api.model("Ip", {"ip": fields.String("An IP address.")})
Urlmap = api.model("UrlMap", {"urlmap": fields.String("URL mapped to ip address.")})
#api.route("/getallips")
class IpList(Resource):
def get(self):
return jsonify(get_all_publicIp())
#api.route("/getip/id/<ipid>")
class IpById(Resource):
#api.expect(Ip)
def get(self, ipid):
ipobj = get_user_ip({"id": ipid})
return jsonified(ipobj)
#api.route("/getip/urlmap/<urlmap>")
class IpByUrlmap(Resource):
#api.expect(Urlmap)
def get(self, urlmap):
ipobj = get_user_ip({"id": ipid})
return jsonified(ipobj)
Notice that you solve your expect problem for free - because each endpoint now fully defines its interface, it's easy to attach a clear expectation to it. You also solve your "get and post defined for endpoints that shouldn't", you can decide for each endpoint whether it should have a get or post.
I'm using the api.route decorator instead of calling api.add_resource for each class because of personal preference. You can get the same behavior by calling api.add_resource(<resource subclass>, <endpoint>) for each new Resource subclass (e.g. api.add_resource(IpList, "/getallips"))

How to add a new item using Python Etsy HTTP API methods?

I am trying to use Etsy API to add a new listing on my store. In the documents section it says (below section how to do it). First fyi I have never used HTTP Method before so I am not sure how to setup the code so that it adds a new item.
(Link to the Etsy API page https://www.etsy.com/developers/documentation/reference/listing).
Method Name createListing
Synopsis Creates a new Listing.
HTTP Method POST
URI /listings
Parameters
Name Required Default Type
quantity Y int
title Y string
description Y text
price Y float
materials N array(string)
shipping_template_id N int
shop_section_id N int
image_ids N array(int)
is_customizable N boolean
non_taxable N boolean
image N image
state N active enum(active, draft)
processing_min N int
processing_max N int
category_id N int
taxonomy_id N int
tags N array(string)
who_made Y enum(i_did, collective, someone_else)
is_supply Y boolean
when_made Y enum(made_to_order, 2010_2017, 2000_2009, 1998_1999, before_1998, 1990_1997, 1980s, 1970s, 1960s, 1950s, 1940s, 1930s, 1920s, 1910s, 1900s, 1800s, 1700s, before_1700)
recipient N enum(men, women, unisex_adults, teen_boys, teen_girls, teens, boys, girls, children, baby_boys, baby_girls, babies, birds, cats, dogs, pets, not_specified)
occasion N enum(anniversary, baptism, bar_or_bat_mitzvah, birthday, canada_day, chinese_new_year, cinco_de_mayo, confirmation, christmas, day_of_the_dead, easter, eid, engagement, fathers_day, get_well, graduation, halloween, hanukkah, housewarming, kwanzaa, prom, july_4th, mothers_day, new_baby, new_years, quinceanera, retirement, st_patricks_day, sweet_16, sympathy, thanksgiving, valentines, wedding)
style N array(string)
Requires OAuth Y
Permission Scope listings_w
Notes
A shipping_template_id is required when creating a listing.
All listings created on www.etsy.com must be actual items for sale. Please see our guidelines for testingwith live listings.
Creating a listing creates a single inventory products with the supplied price and quantity. Use updateInventory to add more products.
The code I have right know looks like this
import urllib
import requests
url = 'https://openapi.etsy.com/v2/listings/active?api_key={YOUR KEY HERE)' # I put my API key here
r = requests.get(url)
payload = {'quantity': '1', 'title': 'testdfsdfdfs0','description': 'dfsdfsdfsdfdsf','price': '2.55','who_made': 'i_did','is_supply': '0','when_made': '2010_2017'}
rrr = requests.post(url,payload)
print rrr # I get an error 404
How can I add an item for sale on Etsy through Python HTTP method?
Update
from requests_oauthlib import OAuth1Session
import requests
from requests_oauthlib import OAuth1
import json
tempory_token_url = []
oauth_response_bucket = []
client_key = '.......'
client_secret = '......'
oauth = OAuth1Session(client_key, client_secret=client_secret)
request_token_url = 'https://openapi.etsy.com/v2/oauth/request_token?scope=email_r%20listings_r'
fetch_response = oauth.fetch_request_token(request_token_url)
resource_owner_key = fetch_response.get('oauth_token') # Have it
resource_owner_secret = fetch_response.get('oauth_token_secret')
oauth_url_temp = tempory_token_url[0]['login_urI']
base_authorization_url = oauth_url_temp
authorization_url = oauth.authorization_url(base_authorization_url)
redirect_response = raw_input('Paste the full redirect URL here: ')
oauth_response = oauth.parse_authorization_response(redirect_response)
verifier = oauth_response.get('oauth_verifier')
access_token_url = redeirect_response
oauth = OAuth1Session(client_key=client_secret=client_secret,resource_owner_key=resource_owner_key,resource_owner_secret=resource_owner_secret,verifier=verifier)
oauth_tokens = oauth.fetch_access_token(access_token_url)
resource_owner_key = oauth_tokens.get('oauth_token')
resource_owner_secret = oauth_tokens.get('oauth_token_secret')
Any ideas how to make this work? There is very little info regarding Etsy API and most of the stuff is in PHP which I have no clue how to work.
Image Uploading API
Everything looks the same like above this time I just changed the payload but I am getting a 403 Error. I am not sure what is causing it. My best guess would be something with oauth1.0 i think on their website it says you need oauth 1.1.
Here is how I set it up but I am getting 403 error:
url = 'https://openapi.etsy.com/v2/listings'
payload = {'listing_id':'342434342', 'image': ("test1.jpg", open('C:\\Users\\abc\\test1.jpg'),'image/jpeg'),'type':'image/jpeg'}
result = etsy.put(url, params=payload)
print result
Comment: ... at this point I am lost I have no idea where to put the pin# that etsy gave me
etsy oauth#reference
The token credentials you receive for a account do not expire,
and can be used over and over again to make authenticated API requests.
You should keep the token secret in a secure location and never send it as a plaintext parameter
(it's only used for signing your requests, and never needs to be sent in an API request on its own.)
You will not need to step through the OAuth authorization again,
unless you decides to revoke access, or unless you add features that require additional permission scopes.
Note: Didn't find a equivalent Replacement for PHP OAUTH_AUTH_TYPE_URI.
OAuth1Session Defaults to signature_type=u'AUTH_HEADER', so this could be wrong.
If this fails, you could try:
from oauthlib.oauth1 import SIGNATURE_TYPE_QUERY, SIGNATURE_TYPE_BODY
OAuth1Session(..., signature_type=SIGNATURE_TYPE_QUERY)
Create etsy OAuth1Session to reuse for Requests:
etsy = OAuth1Session(client_key,
client_secret=client_secret,
resource_owner_key=resource_owner_key,
resource_owner_secret=resource_owner_secret)
etsy Making an Authorized Request to the API:
response = etsy.get("https://openapi.etsy.com/v2/users/__SELF__")
user_data = json.loads(response.body_as_unicode())
etsy Checking Permission Scopes After Authentication:
response = etsy.get("https://openapi.etsy.com/v2/oauth/scopes")
meta = json.loads(response.body_as_unicode())
etsy Creates a new Listing
url = 'https://openapi.etsy.com/v2/listings'
payload = {'quantity': '1', 'title':...}
result = etsy.post(url, params=payload)
Comment: for api key do I need to import oauth2
According to Reference, Yes.
For write access and for accessing private user data, an OAuth access
token is required. Your application key is required to start the OAuth
authentication process.
Requires OAuth Y
Also your url should end with
URI /listings
url = 'https://openapi.etsy.com/v2/listings'
Your url should only up to the Question mark, for example:
url = 'https://openapi.etsy.com/v2/listings/active'
payload = {'api_key':YOUR KEY HERE, 'quantity': '1', ...
rrr = requests.post(url, params=payload)
Requests Quickstart: Passing Parameters In URLs
You often want to send some sort of data in the URL's query string.
If you were constructing the URL by hand,
this data would be given as key/value pairs in the URL after a question mark, e.g. \http://bin.org/get?key=val.
Requests allows you to provide these arguments as a dictionary of strings, using the params keyword argument.
Question: I am trying to upload a picture ... getting a 403 error
Your url Endpoint and payload isn't correct.
url = 'https://openapi.etsy.com/v2/listings'
payload = {'listing_id':'342434342', 'image': ("test1.jpg", open('C:\\Users\\abc\\test1.jpg'),'image/jpeg'),'type':'image/jpeg'}
Steps to do a etsy Request(uploadListingImage):
Read the Reference for your Method Name
Method Name uploadListingImage
HTTP Method POST
URI /listings/:listing_id/images
Parameters Name Required Default Type
listing_id Y int
listing_image_id N int
image N imagefile
...
Requires OAuth Y
Respect Supported Sizes Working with Images
Note: For me, it's unclear what the image Parameter is for.
And as it's NOT required makes no sense.
I assume its a Placeholder for the Parameter at Point 4 below: {'image':...
Build the URI
uri = 'https://openapi.etsy.com/v2/listings/342434342/images'
Create the Params Dict according to the above Reference
I recommend to use a listing_image_id, as this seems the only way to delete a Image afterwards.
params = {'listing_id':'342434342', 'listing_image_id': 1}
Create Multipart-Encoded File Dict
Image uploads can be performed using a POST request with the Content-Type: multipart/form-dataheader, following RFC1867
# PHP example from Reference:
# $params = array('#image' => '#'.$source_file.';type='.$mimetype);
files = {'image': ("test1.jpg", open('C:\\Users\\abc\\test1.jpg', 'rb'), 'image/jpeg')}
Do the Request, according the Reference, you have to use OAuth and POST
result = etsy.post(uri, params=params, files=files)
Please Comment if this is working for you or why not.

Passing a Facebook Oauth2 object while using Tornado

I am trying to implement oauth manually on my website which is being implemented using tornado. My url (localhost/form) contains a button which when clicked brings up a facebook login and then if the login is successful redirects back to the same site with a token (localhost/form?code=XXX) where I collect the token/code and begins taking requests from facebook.
My issue is that upon redirecting back to localhost/form with a given code, it appears that I reinitialize a brand new oauth2session object which does not match up with the token and I receive a GET request error. How should I correctly pass this oauth2session object or correctly reinitialize it? Is this reinitialization causing my error or something else? My current code which does not work is:
class FormHandler (BaseHandler):
def get(self):
client_id =XXX
client_secret =XXX
authorization_base_url = 'https://www.facebook.com/dialog/oauth'
token_url = 'https://graph.facebook.com/oauth/access_token'
facebook = OAuth2Session(client_id, redirect_uri='http://localhost/form')
facebook = facebook_compliance_fix(facebook)
authorization_url, state = facebook.authorization_url(authorization_base_url)
self.write('<button id="FacebookManual" type="button">Facebook Manual</button><br><script> document.getElementById("FacebookManual").onclick = function () {location.href ="'+authorization_url+'";};</script>')
#Check to see if I get redirected with a code
authorization_code=self.get_argument("code", default=None, strip=False)
if authorization_code is not None:
redirect_response='https://localhost/form/?code='+authorization_code
facebook.fetch_token(token_url, client_secret=client_secret, authorization_response=redirect_response)
r = facebook.get('https://graph.facebook.com/me?')
self.write('Hello'+r.content)
#Roughly how my tornado is set up
def make_app():
return Application(
[
url('/', BaseHandler, { "var":"nothing" }, name="root"), # this is for the root! :)
url('/form', FormHandler, { "var":"initialize this!" }, name = "forlorn"),
],
# settings:
debug = True,
)
Edit: A friend advised me to include the error that I was receiving. The error that I get is a oauthlib.oauth2.rfc6749.errors.MismatchingStateError: (mismatching_state) CSRF Warning! State not equal in request and response.
ERROR:tornado.access:500 GET /form?code=XxX

How to process JSON in Flask?

I have asked a few questions about this before, but still haven't solved my problem.
I am trying to allow Salesforce to remotely send commands to a Raspberry Pi via JSON (REST API). The Raspberry Pi controls the power of some RF Plugs via an RF Transmitter called a TellStick. This is all setup, and I can use Python to send these commands. All I need to do now is make the Pi accept JSON, then work out how to send the commands from Salesforce.
Someone kindly forked my repo on GitHub, and provided me with some code which should make it work. But unfortunately it still isn't working.
Here is the previous question: How to accept a JSON POST?
And here is the forked repo: https://github.com/bfagundez/RemotePiControl/blob/master/power.py
What do I need to do? I have sent test JSON messages n the Postman extension and in cURL but keep getting errors.
I just want to be able to send various variables, and let the script work the rest out.
I can currently post to a .py script I have with some URL variables, so /python.py?power=on&device=1&time=10&pass=whatever and it figures it out. Surely there's a simple way to send this in JSON?
Here is the power.py code:
# add flask here
from flask import Flask
app = Flask(__name__)
app.debug = True
# keep your code
import time
import cgi
from tellcore.telldus import TelldusCore
core = TelldusCore()
devices = core.devices()
# define a "power ON api endpoint"
#app.route("/API/v1.0/power-on/<deviceId>",methods=['POST'])
def powerOnDevice(deviceId):
payload = {}
#get the device by id somehow
device = devices[deviceId]
# get some extra parameters
# let's say how long to stay on
params = request.get_json()
try:
device.turn_on()
payload['success'] = True
return payload
except:
payload['success'] = False
# add an exception description here
return payload
# define a "power OFF api endpoint"
#app.route("/API/v1.0/power-off/<deviceId>",methods=['POST'])
def powerOffDevice(deviceId):
payload = {}
#get the device by id somehow
device = devices[deviceId]
try:
device.turn_off()
payload['success'] = True
return payload
except:
payload['success'] = False
# add an exception description here
return payload
app.run()
Your deviceID variable is a string, not an integer; it contains a '1' digit, but that's not yet an integer.
You can either convert it explicitly:
device = devices[int(deviceId)]
or tell Flask you wanted an integer parameter in the route:
#app.route("/API/v1.0/power-on/<int:deviceId>", methods=['POST'])
def powerOnDevice(deviceId):
where the int: part is a URL route converter.
Your views should return a response object, a string or a tuple instead of a dictionary (as you do now), see About Responses. If you wanted to return JSON, use the flask.json.jsonify() function:
# define a "power ON api endpoint"
#app.route("/API/v1.0/power-on/<int:deviceId>", methods=['POST'])
def powerOnDevice(deviceId):
device = devices[deviceId]
# get some extra parameters
# let's say how long to stay on
params = request.get_json()
try:
device.turn_on()
return jsonify(success=True)
except SomeSpecificException as exc:
return jsonify(success=False, exception=str(exc))
where I also altered the exception handler to handle a specific exception only; try to avoid Pokemon exception handling; do not try to catch them all!
To retrieve the Json Post values you must use request.json
if request.json and 'email' in request.json:
request.json['email']

Categories