List databases return no results - python

I have a workspace with 2 databases shared with my integration, basically it works and I get 200 OK code.
That's the function I have, the headers contain the authentication token:
def listDatabases(self):
r = requests.get('https://api.notion.com/v1/databases', headers=self.headers)
if r.status_code == 200:
return r.json()
else:
return r.reason
And this is the result:

I think maybe those database permissions held by integration are inherited from the parent page.
From Notion API Reference (List databases):
Search pages for more details
This endpoint is no longer recommended, use search instead. This endpoint will only return explicitly shared pages, while search will also return child pages within explicitly shared pages.
An easy way to verify is to confirm if "based on xxx" is included under integration in the share option on the database page (not its parent page or inline database). if was, then that database will not return in "list databases" endpoint.

I believe it's because you are not sending the database id in the url
https://api.notion.com/v1/databases/**database_id**
if you don't specify the database_id it will take the first database which I assume is without any records.

Related

Create Ebay Connector using Syncari SDk

i'm trying to create a connector inside Syncari SDK to get Orders from Ebay using this SDK
https://pypi.org/project/syncari-sdk/
in ebay am using Production environment using Auth'n'Auth
and with this Token am using:
1. Trading API
2.API CALL : GetOrders
3.API VERSION : 967
HTTP headers
X-EBAY-API-SITEID:0
X-EBAY-API-COMPATIBILITY-LEVEL:967
X-EBAY-API-CALL-NAME:GetOrders
Request Body
<?xml version="1.0" encoding="utf-8"?>
<GetOrdersRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<RequesterCredentials>
<eBayAuthToken></eBayAuthToken>
</RequesterCredentials>
<ErrorLanguage>en_US</ErrorLanguage>
<WarningLevel>High</WarningLevel>
<OrderIDArray>
<!-- Enter one or more of the seller's Order IDs in separate OrderID fields. Only legacy Order IDs are supported in GetOrders and not the ExtendedOrderIDs that are supported in eBay REST APIs calls like the Fulfillment API. The legacy Order ID values are actually the concatenation of ItemID and TransactionID, with a hyphen in between these two values. In legacy API calls, the OrderLineItemID and OrderID values are the same for single line item orders. Note that the TransactionID for an auction listing is always '0', which is demonstrated below -->
<OrderID>XXXXXXXXXXXX-XXXXXXXXXXXXX</OrderID>
<OrderID>XXXXXXXXXXXX-0</OrderID>
</OrderIDArray>
<OrderRole>Seller</OrderRole>
</GetOrdersRequest>
Inside SDK we have a method called : synapse_Info() to connect to ebay using token
Read the document here : https://support.syncari.com/hc/en-us/articles/4580013102868-Custom-Synapse-SDK-Documentation
i want to know how to add Headers, Toekn , Body to get Orders From Ebay API and add all of this here
def synapse_info(self):
return SynapseInfo(
name='lysiSynapse', category='other',
metadata=UIMetadata(displayName='Lysi Synapse'),
supportedAuthTypes=[AuthMetadata(authType=AuthType.BASIC_TOKEN, label='API Key', fields=[AuthField(name='token', label='API Key', dataType=DataType.PASSWORD)])],
configuredFields=[AuthField(name='endpoint', label='Endpoint URL', dataType=DataType.STRING)])
we can see response usning Method : Test() in the SDK
def test(self, connection: Connection):
self.client.get("/users",headers=self.__auth_headers())
if not connection.metaConfig:
connection.metaConfig={}
return connection
The synapse_info info method is meant to be used to declare the Synapse’s UI elements and authentication options and not to add headers and tokens directly. The method returns a SynapseInfo object that defines fields in the Syncari’s UI. It is possible later in the framework to access those defined fields from the connection object, which persist through the framework.
We recommend first is to define the Syncari rest client in the Synapse class:
def __init__(self, request: Request) -> None:
super().__init__(request)
self.client = SyncariRestClient(self.connection.authConfig.endpoint, self.connection.authConfig)
This way it’s possible to use the Syncari client that will have access to the endpoint and authentication data that the user inputs in the UI of Syncari.
Since Ebay's API uses XML queries we’d recommend creating helper methods to assist with constructing the queries. For this particular example:
def xmlQueryConstructorGetOrderByID(eBayAuthToken, Orders):
return f"<?xml version=\"1.0\" encoding=\"utf-8\"?><GetOrderRequest xmlns=\"urn:ebay:apis:eBLBaseComponents\"><RequesterCredentials><eBayAuthToken>{eBayAuthToken}</eBayAuthToken></RequesterCredentials><ErrorLanguage>en_US</ErrorLanguage><WarningLevel>High</WarningLevel><OrderIDArray>{Orders}</OrderIDArray><OrderRole>Seller</OrderRole></GetOrderRequest>""
Additionally, we recommend to hardcode the required headers in a constant:
HEADERS = {"Content-Type":"application/xml", "x-ebay-api-call-name": "GetOrders", "x-ebay-api-compatibility-level" : "967", "X-EBAY-API-SITEID" : "0"}
We can now use all of this to make a call in the test method, which is used to test the credentials a user imputed in the UI of Syncari application:
def test(self, connection: Connection):
self.client.get("", headers=HEADERS, data=self.client.post("",headers=HEADERS,
data=xmlQueryConstructorGetOrderByID(self.connection.authConfig.token,"<OrderID>XXXXXXXXXXXX-XXXXXXXXXXXXX</OrderID>")))
return connection
In an actual use case the would be replaced with an actual existing order’s ID and the authentication data is accessed from the connection object.
We also recommend using a python library like xmltodict to convert the received XML data into JSON, so it is easier to pass it to Syncari.
We hope this answers the question but if you need any further assistance please reach out to our support at developers#syncari.com.

Setting HttpReferrer In Unit Tests

In my view.py I have the following check on several consecutive pages:
if(request.META.get('HTTP_REFERER') != request.build_absolute_uri(reverse('page1'))):
return redirect('page1')
This is performed on every page, checking that the user was redirected from the previous page, so (for example), if a user tries to enter the url for page4 in the address bar, the test will fail and he will be sent to page3, then that pages test will fail and he will fall back to page2, and so on.
Im doing this because I have several pages linked together which users must visit consecutively.
The problem comes when I want to unit test. The following test would throw an error because it fails the redirect test and therefore cannot test the logic of the page which im trying to test:
def test_user_information_updated_on_validation_success(self):
user = User.objects.create_superuser('username')
self.client.force_login(user)
self.client.post(reverse('page_4'), {
'exampleQuestion': 'exampleAnswer'
})
user.refresh_from_db()
self.assertEqual(user.exampleform.somefield, 'exampleAnswer')
How can I access the page within a unit test as if it had been redirected.
Thank you.
A request in the test client accepts keywords that are mapped to WSGI environment variables. Environment variables that start with HTTP and are all uppercase, with dashes mapped to underscores - are Http headers, so the short version is that we can set HTTP headers as such:
# Wrong: Generates absolute paths without hosts
self.client.post(
reverse('page_4'), {'exampleQuestion': 'exampleAnswer'},
HTTP_REFERER=reverse('page_3')
)
Edit:
It's a little too simple, because HTTP referrers are fully qualified, so we need:
referer = 'http://testserver{}'.format(reverse('page_3'))
self.client.post(
reverse('page_4'), {'exampleQuestion': 'exampleAnswer'},
HTTP_REFERER=referer
)
FYI: The protocol (wsgi.scheme) and host name (HTTP_SERVER) come from djang.test.client.RequestFactory._base_environ(). If you use a modified client that changes servername and/or protocol, you should adjust accordingly. In that case it would be wise to override _base_environ in your modified test client and derive values from that.

Django beginners issue issues

I am new to web development just pieced together my first django web app and integrated with apache using mod_wsgi.
the app has some 15 parameters on which you could query multiple SQL server databases and the result can be downloaded as .xls file; have deployed the same on the company network.
the problem is when i access the web app on one machine and set query parameters, the same parameters get set in the web app when i try opening it from a different machine (web client) .
Its like there is just one global object which is being served to all the web client.
Am using django template tags to set values in the app's html pages.
not using any models in the django project as am querying SQL server DB which are already built.
the query function from my views.py looks like
def query(self,request):
"""
"""
print "\n\n\t inside QUERY PAGE:",request.method,"\n\n"
self.SummaryOfResults_list = []
if self.vmd_cursor != -1:
self.vmd_cursor.close()
if request.method == 'POST':
QueryPage_post_dic = request.POST
print "\n\nQueryPage_post_dic :",QueryPage_post_dic
self.err_list = []
self.err_list = db_qry.validate_entry(QueryPage_post_dic)
if len(self.err_list):
return HttpResponseRedirect('/error/')
else:
channel_numbers,JPEG_Over_HTTP,Codec,format,rate_ctrl,transport,img_sz,BuildInfo_versions, self.numspinner_values_dic = db_qry.process_postdata(QueryPage_post_dic, self.numspinner_values_dic)
return self.get_result(request,channel_numbers,JPEG_Over_HTTP,Codec,format,rate_ctrl,transport,img_sz,BuildInfo_versions)
else:
print "\nself.Cam_Selected_list inside qry :",self.Cam_Selected_list
if (len(self.Cam_Selected_list) != 1):
return HttpResponseRedirect('/error/')
self.tc_dic,self.chnl_dic,self.enbl_dic,self.frmt_dic,self.cdectyp_dic,self.imgsz_dic,self.rtctrl_dic,self.jpg_ovr_http_dic,self.trnsprt_dic,self.cdec_dic,self.typ_dic,self.resolution_dic, self.vmd_cursor = populate_tbls.Read_RefTbls(self.Cam_Selected_list[0])
c = self.get_the_choices(self.Cam_Selected_list[0])
c['camera_type']= self.Cam_Selected_list[0]
for k,v in self.numspinner_values_dic.items():
c[k] = v
self.vmd_cursor.execute("SELECT DISTINCT [GD Build Info] FROM MAIN")
res_versions = self.vmd_cursor.fetchall()
version_list = []
ver_list = ['',' ']
for version in res_versions:
tmp_ver = version[0].encode()
if (tmp_ver not in ver_list):
version_list.append(tmp_ver)
c['build_info'] = version_list
print "\n\n c dic :",c
c.update(csrf(request))
return render_to_response('DBQuery.html',c)
and the dictionary being passed to render_to_response holds the values that setting checkboxes and multiselect boxes (dojo)
thanks
Its like there is just one global object which is being served to all the web client.
What you're saying is probably exactly what's happening. Unless you're building whatever object that self in that example code is anew for each request, it will be practically randomly shared between clients.
You can store your global variable in SQL DB that you are using. This way you can retain the value/state of the variable across request -> response cycle.
If you need faster response time explore Key->Value Pair in memory datastore like redis.
To add to what's mentioned by AKX I suggest that you read up on HTTP Request -> HTTP Response cycle and How web applications work.

Understanding "runwithfriends" facebook-app sample code

this is my first web-programming experience so I hope my questions doesn't sound very dumb. I have been stucked on this for many days.
I am trying to understand a sample code:
https://github.com/facebook/runwithfriends
However I am not understanding very well how the information flow works and how can I modify that sample (i.e. how the code works).
For example, in the following section of the code:
class RecentRunsHandler(BaseHandler):
"""Show recent runs for the user and friends"""
def get(self):
if self.user:
friends = {}
for friend in select_random(
User.get_by_key_name(self.user.friends), 30):
friends[friend.user_id] = friend
self.render(u'runs',
friends=friends,
user_recent_runs=Run.find_by_user_ids(
[self.user.user_id], limit=5),
friends_runs=Run.find_by_user_ids(friends.keys()),
)
else:
self.render(u'welcome')
As I understand (along with HTML) is useful for showing friends that are using the same app, and if I understand correctly, here is the essential part:
*friends_runs=Run.find_by_user_ids(friends.keys())*
But what if I want to show any given friend. How can I do it?
Summarizing, I would like to know:
1- How the flow of the code works? (I don't fully understand the explanation here)
2- How can I manipulate the code so to get, for example, to show a list of friends of the user (not necessary that use the same app)?
Moreover, Can I show friends filtered by some characteristic (for example, gender)?
Thanks a lot!
The python "SDK" for facebook I use I took from https://gist.github.com/1190267
and combined it with the code from the example app to achieve the functionality I wanted both for a canvas app and for website usage.
It depends whether you're using facebook with websites or a canvas application. For a canvas application you probably could do well with the javascript SDK but for a "login with facebook" I required serverside logic that should work with javascript turned off so I've completed that solution with details you might have help to know. You can try make small changes of that specific app 'runwithfriends' to get an understanding which code does what. The project you're looking at contains some outdated practice though:
getting and setting cookies is likely preferable now doing with webapp2's builtin functions for this instead of the code that comes with the FB example app
logging in and out is now done with OAuth 2.0 so it's likely that the login system you're looking at is outdated and you need to use OAuth 2.0 which is described here. I much rather do login/logout serverside so I did an OAuth 2.0 pure python solution to login / logout following the authentication steps mentioned in the tutorial from FB. I had to clear the cookie to log a user out which was not documented.
To upgrade to python 2.7 I had to also modify so that HTTP header did not cast to unicode. I don't know why but otherwise it complained that headers were "not strings"
To more elaborately answer your specific questions:
1) The requesthandler class you posted is a subclass of a BaseHandler so to fully understand what it does you can look at the BaseHandler class since what you are posting is a BAseHandler. The BaseHandler uses django templates for rendering and if you want to can switch the template engine to jinja2 which is remmended. Further the code accesses the user object inherited from the BaseHandler and does some operations on it and renders it to a template. You can try make a requesthandler of your own, subclass BaseHandler and do what you want.
2) I could manipulate the code and I'm not an expert so you should be able to do it too. I wanted a simple FB app to display random images and I could manipulate it to select random images via blobs and render to to a template while keeping the facebook base functions. A function to use for getting the user using the Graph API I do this:
def parse_signed_request(signed_request, secret):
"""
Parse signed_request given by Facebook (usually via POST),
decrypt with app secret.
Arguments:
signed_request -- Facebook's signed request given through POST
secret -- Application's app_secret required to decrpyt signed_request
"""
if '.' in signed_request:
(esig, payload) = signed_request.split('.')
else:
return {}
sig = urlsafe_b64decode(str(esig))
data = _parse_json(urlsafe_b64decode(str(payload)))
if not isinstance(data, dict):
raise SignedRequestError('Pyload is not a json string!')
return {}
if data['algorithm'].upper() == 'HMAC-SHA256':
if hmac.new(secret, payload, hashlib.sha256).digest() == sig:
return data
else:
raise SignedRequestError('Not HMAC-SHA256 encrypted!')
return {}
def get_user_from_cookie(cookies, app_id, app_secret):
"""Parses the cookie set by the official Facebook JavaScript SDK.
cookies should be a dictionary-like object mapping cookie names to
cookie values.
If the user is logged in via Facebook, we return a dictionary with the
keys "uid" and "access_token". The former is the user's Facebook ID,
and the latter can be used to make authenticated requests to the Graph API.
If the user is not logged in, we return None.
Download the official Facebook JavaScript SDK at
http://github.com/facebook/connect-js/. Read more about Facebook
authentication at http://developers.facebook.com/docs/authentication/.
"""
cookie = cookies.get('fbsr_' + app_id, '')
if not cookie:
return None
response = parse_signed_request(cookie, app_secret)
if not response:
return None
args = dict(code=response['code'], client_id=app_id,
client_secret=app_secret, redirect_uri='')
file = \
urllib.urlopen('https://graph.facebook.com/oauth/access_token?'
+ urllib.urlencode(args))
try:
token_response = file.read()
finally:
file.close()
access_token = cgi.parse_qs(token_response)['access_token'][-1]
logging.debug('returning cookie')
return dict(uid=response['user_id'], access_token=access_token)
See http://developers.facebook.com/docs/api for complete documentation for the API. And you can get the the official Facebook JavaScript SDK at http://github.com/facebook/connect-js/
I'm now writing code to sync a webapp2_extras.auth account with facebook so that custom accounts and facebook accounts can co-exist and we're discussing solutions for this in the webapp2 groups and categories. The current way I do it is adding the recommended current_user to a basehandler and using that as the FB identity while working on "merging" my class FBUser that is a custom class for facebook users that autheorized my website and/or canvas application to sync with webapp2_extras.auth.models.User which is an expando model so it can just add the properties it doesn't have such as facebookid, firstname, lastname, etc.
#property
def current_user(self):
if not hasattr(self, '_current_user'):
self._current_user = None
cookie = get_user_from_cookie(self.request.cookies,
facebookconf.FACEBOOK_APP_ID,
facebookconf.FACEBOOK_APP_SECRET)
if cookie:
# Store a local instance of the user data so we don't need
# a round-trip to Facebook on every request
user = FBUser.get_by_key_name(cookie['uid'])
if not user:
graph = GraphAPI(cookie['access_token'])
profile = graph.get_object('me')
user = FBUser(key_name=str(profile['id']),
id=str(profile['id']),
name=profile['name'],
profile_url=profile['link'],
access_token=cookie['access_token'])
user.put()
elif user.access_token != cookie['access_token']:
user.access_token = cookie['access_token']
user.put()
self._current_user = user
return self._current_user
You can also solve your authentication with session objects and build your authentication system around that. That is what I do when using both custom accounts and facebook accounts and you're welcome to have a lok at my repository for more code examples how to intregrate facebook with google app engine using python 2.7.

How to set a cookie in a django test case?

I'm struggling to figure this one out, sessions work when i run my application normally but i can't figure out how to set data in the session in my test case.
The docs say in a test case you have to save the session to apply the changes before making the request. https://docs.djangoproject.com/en/1.2/topics/testing/#persistent-state
e.g.
from django.test import TestCase
class TestLogin(TestCase):
def test_processuser(self):
redirect = '/processuser/'
session = self.client.session
session["id"] = '1234'
session.save()
response = self.client.get(redirect)
However the session object returned from self.client.session is just a normal python dict?
Diging into the code the Client.session call is this:
def _session(self):
"""
Obtains the current session variables.
"""
if 'django.contrib.sessions' in settings.INSTALLED_APPS:
engine = import_module(settings.SESSION_ENGINE)
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
if cookie:
return engine.SessionStore(cookie.value)
return {}
session = property(_session)
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None) returns None so it just returns a dict in stead of a session store.
It looks like i have to do some more preparation in the test client before i save a session? Not really got much experience in this any help would be appreciated.
Django 1.2.5
Python 2.6.5
Cheers,
Asim.
Edit: this answer is now outdated; as of at least Django 1.7, you can just set the cookie directly on the test client.
See e.g. this answer to this question or the comments on this answer to another, similar, question.
Old outdated answer follows...
Adding this for people who really do need to set a cookie, e.g. because they need to do something which isn't covered by the Django auth mechanism...
You can't set cookies directly on TestClient objects but if you use the RequestFactory class you can do it. So instead of (say):
response = Client().post('/foo')
you do:
request = RequestFactory().post('/foo')
request.COOKIES['blah'] = 'hello'
response = foo_view(request)
where foo_view is the view corresponding to the '/foo' path, i.e. the view you're looking to test.
HTH somebody.
The simplest thing would be to login as someone, so the test client would set the cookie for you.
self.client.login(username,password)
should do. Refer the documentation for more.
Contrary to the most upvoted answer, you CAN set cookies directly on the test client.
Remember everything is an object, you just have to know where/what to patch
so it goes like this:
client.cookies[key] = data
client.cookies is an instance of http.cookies.SimpleCookie from the standard library and it behaves like a dict. so you can use .update for bulk updates to a cookies value. This can be useful if you want to alter other cookie values like max-age, path domain etc.
Finally, if you want to set a signed_cookie, You can reuse the helpers from django like this:
from django.core.signing import get_cookie_signer
signed_cookie_value = get_cookie_signer(salt=key).sign(data)
client.cookies[key] = signed_cookie_value
Pay attention to the salt. It has to match on both ends (Signing and retrieval). A Different salt value for signing would generate a different cookie that cannot be retrieved when you call response.get_signed_cookie(key)
For other people who are running into this problem please be aware that the Client.logout() function will throw away your cookies. For example:
response = self.client.post(self.url, self.data)
print response.client.cookies.items() # Displays the cookie you just set
self.client.logout()
response = self.client.post(reverse('loginpage'), {'username': 'username', 'password': 'password'}, follow=True)
print response.client.cookies.items() # Does not display the cookie you set before since it got destroyed by logout()
To make sure your cookies stay alive during testing make a call to your logout page in stead of using the Client.logout() function, like so:
response = self.client.post(self.url, self.data)
print response.client.cookies.items() # Displays the cookie you just set
self.client.get(reverse('logoutpage'))
response = self.client.post(reverse('loginpage'), {'username': 'username', 'password': 'password'}, follow=True)
print response.client.cookies.items() # Does display the cookie you set before since it did not get destroyed by client.logout()

Categories

Resources