Commit 413d7ce1 by Raphael Lullis

Adding authentication methods, and figured out that Parse does return…

Adding authentication methods, and figured out that Parse does return sessionToken info if requests are made with master key set, so I'm adding a new way to setup the connection. Before any interaction with Parse, simply call ParseBase.register(app_id, rest_key, **optional_keys) and it will save them. So the library now becomes usable for applications both with or without the master key.
parent c54dd05f
...@@ -44,17 +44,26 @@ class ResourceRequestNotFound(ParseError): ...@@ -44,17 +44,26 @@ class ResourceRequestNotFound(ParseError):
'''Request returns a 404''' '''Request returns a 404'''
pass pass
def master_key_required(func):
'''decorator describing methods that require the master key'''
def ret(obj, *args, **kw):
conn = ParseBase.CONNECTION
if not (conn and conn.get('master_key')):
message = '%s requires the master key' % func.__name__
raise ParseError(message)
func(obj, *args, **kw)
return ret
class ParseBase(object): class ParseBase(object):
ENDPOINT_ROOT = API_ROOT ENDPOINT_ROOT = API_ROOT
@classmethod @classmethod
def register(cls, app_id, rest_key, master_key, **kw): def register(cls, app_id, rest_key, **kw):
ParseBase.CONNECTION = { ParseBase.CONNECTION = {
'APPLICATION_ID': app_id, 'app_id': app_id,
'REST_API_KEY':rest_key, 'rest_key': rest_key
'MASTER_KEY': master_key
} }
ParseBase.CONNECTION.update(**kw)
@classmethod @classmethod
...@@ -63,8 +72,9 @@ class ParseBase(object): ...@@ -63,8 +72,9 @@ class ParseBase(object):
raise ParseError('Missing connection credentials') raise ParseError('Missing connection credentials')
app_id = ParseBase.CONNECTION.get('APPLICATION_ID') app_id = ParseBase.CONNECTION.get('app_id')
rest_key = ParseBase.CONNECTION.get('REST_API_KEY') rest_key = ParseBase.CONNECTION.get('rest_key')
master_key = ParseBase.CONNECTION.get('master_key')
headers = extra_headers or {} headers = extra_headers or {}
url = uri if uri.startswith(API_ROOT) else cls.ENDPOINT_ROOT + uri url = uri if uri.startswith(API_ROOT) else cls.ENDPOINT_ROOT + uri
...@@ -75,20 +85,23 @@ class ParseBase(object): ...@@ -75,20 +85,23 @@ class ParseBase(object):
request = urllib2.Request(url, data, headers) request = urllib2.Request(url, data, headers)
request.add_header('Content-type', 'application/json') request.add_header('Content-type', 'application/json')
request.add_header("X-Parse-Application-Id", app_id) request.add_header('X-Parse-Application-Id', app_id)
request.add_header("X-Parse-REST-API-Key", rest_key) request.add_header('X-Parse-REST-API-Key', rest_key)
if master_key: request.add_header('X-Parse-Master-Key', master_key)
request.get_method = lambda: http_verb request.get_method = lambda: http_verb
try: try:
response = urllib2.urlopen(request) response = urllib2.urlopen(request)
except urllib2.HTTPError, e: except urllib2.HTTPError, e:
raise { exc = {
400: ResourceRequestBadRequest, 400: ResourceRequestBadRequest,
401: ResourceRequestLoginRequired, 401: ResourceRequestLoginRequired,
403: ResourceRequestForbidden, 403: ResourceRequestForbidden,
404: ResourceRequestNotFound 404: ResourceRequestNotFound
}.get(e.code, ParseError) }.get(e.code, ParseError)
raise exc(e.read())
return json.loads(response.read()) return json.loads(response.read())
......
...@@ -24,9 +24,11 @@ except ImportError: ...@@ -24,9 +24,11 @@ except ImportError:
sys.exit('You must create a settings_local.py file with APPLICATION_ID, ' \ sys.exit('You must create a settings_local.py file with APPLICATION_ID, ' \
'REST_API_KEY, MASTER_KEY variables set') 'REST_API_KEY, MASTER_KEY variables set')
parse_rest.APPLICATION_ID = getattr(settings_local, 'APPLICATION_ID', '') parse_rest.ParseBase.register(
parse_rest.REST_API_KEY = getattr(settings_local, 'REST_API_KEY', '') getattr(settings_local, 'APPLICATION_ID'),
parse_rest.MASTER_KEY = getattr(settings_local, 'MASTER_KEY', '') getattr(settings_local, 'REST_API_KEY'),
master_key=getattr(settings_local, 'MASTER_KEY')
)
GLOBAL_JSON_TEXT = """{ GLOBAL_JSON_TEXT = """{
"applications": { "applications": {
......
...@@ -39,15 +39,17 @@ class User(ParseResource): ...@@ -39,15 +39,17 @@ class User(ParseResource):
'username', 'sessionToken'] 'username', 'sessionToken']
def is_authenticated(self): def is_authenticated(self):
return self.authenticate(self.sessionToken) return self.sessionToken is not None
def authenticate(self, session_token): def authenticate(self, password=None, session_token=None):
self.sessionToken = session_token if self.is_authenticated(): return
try:
self.save() if password is not None:
return True self = User.login(self.username, password)
except:
return False user = User.retrieve(self.objectId)
if user.objectId == self.objectId and user.sessionToken == session_token:
self.sessionToken = session_token
@login_required @login_required
def save(self): def save(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment