Browse Source

First, basic implementation of the API that suffices for buying. Testing and improvements needed

master
Niklas Brachmann 11 years ago
parent
commit
01aab632ec
  1. 211
      cash/api.py
  2. 2
      cash/urls.py

211
cash/api.py

@ -0,0 +1,211 @@ @@ -0,0 +1,211 @@
from cash.models import *
from django.http import HttpResponse
from django.contrib.auth import authenticate
from django.views.decorators.csrf import csrf_exempt
from django.contrib.sessions.backends.db import SessionStore
import json
import hashlib
API_VERSION = 2
err_msgs = {}
#Global errors
ERR_DATABASE = 1
ERR_PARSE_REQUEST = 2
ERR_UNKNOWN_ACTION = 3
ERR_PARAM = 4
ERR_INVALID_SESSION = 5
err_msgs[ERR_DATABASE] = 'Can\'t connect to database'
err_msgs[ERR_PARSE_REQUEST] = 'Error while parsing request'
err_msgs[ERR_UNKNOWN_ACTION] = 'Unknown action specified'
err_msgs[ERR_PARAM] = 'Given parameters don\'t match the actions requirements'
err_msgs[ERR_INVALID_SESSION] = 'The session key is invalid'
#Auth key errors
ERR_INVALID_AUTH_KEY = 6
ERR_AUTH_KEY_LOCKED = 7
ERR_AUTH_KEY_NOT_PERMITTED = 8
err_msgs[ERR_INVALID_AUTH_KEY] = 'The given authentication key is invalid'
err_msgs[ERR_AUTH_KEY_LOCKED] = 'The given authentication key is locked'
err_msgs[ERR_AUTH_KEY_NOT_PERMITTED] = 'The given authentication key has insufficient permissions for this action'
#Errors for get_user_info
ERR_USER_NOT_FOUND = 11
ERR_INCORRECT_PIN = 12
err_msgs[ERR_USER_NOT_FOUND] = 'Unknown user'
err_msgs[ERR_INCORRECT_PIN] = 'Pin/Password is not valid'
#Errors for get_item_infos
ERR_ITEM_NOT_FOUND = 31
err_msgs[ERR_ITEM_NOT_FOUND] = 'Can\'t find the given item'
#Errors for buy_items
ERR_ITEM_NOT_FOUND_ = 41
ERR_INSUFFICIENT_CREDIT = 42
err_msgs[ERR_ITEM_NOT_FOUND_] = 'At least one of the items to buy could not be found'
err_msgs[ERR_INSUFFICIENT_CREDIT] = 'The user has not enough money left to buy the specified items'
#Errors for cash_prepaid_card
ERR_CASH_CODE_NOT_VALID = 51
err_msgs[ERR_CASH_CODE_NOT_VALID] = 'Given code can\'t be found or has already been used'
#Errors for cash_[gs]et_config_key
ERR_CONFIG_TYPE_MISMATCH = 61
ERR_CONFIG_UNKNOWN_TYPE = 62
err_msgs[ERR_CONFIG_TYPE_MISMATCH] = 'Value in database doesn\'t match the datatype for that key'
err_msgs[ERR_CONFIG_UNKNOWN_TYPE] = 'Given value is neither int, bool, string nor float'
#Errors for cash_modify_credit
ERR_USER_NOT_FOUND__ = 71
ERR_USER_NOT_AUTHORIZED = 72
err_msgs[ERR_USER_NOT_FOUND] = 'User not found'
err_msgs[ERR_USER_NOT_AUTHORIZED] = 'User not authorized to change another user\'s credit'
class ApiError(Exception):
def __init__(self, code):
self.code = code
def check_session(data):
try:
key = data['session_key']
except KeyError:
raise ApiError(ERR_PARAM)
s = SessionStore(session_key = key)
if not s.exists(key):
raise ApiError(ERR_INVALID_SESSION)
return s
# Disable CSRF, because clients don't do cookies
@csrf_exempt
def cashapi(request):
retval = {}
error = {'code': 0, 'msg': None}
try:
try:
req = json.loads(request.body)
except:
raise ApiError(ERR_PARSE_REQUEST)
print req
action = req['action']
data = req['data']
if action == 'start_session_password':
try:
user = authenticate(username = data['user'], password = data['password'])
except KeyError:
raise ApiError(ERR_PARAM)
if user is not None:
# Credentials are valid, so save user id in session
s = SessionStore()
s['userid'] = user.id
s.save()
retval['session_key'] = s.session_key
else:
apierror(ERR_INCORRECT_PIN)
elif action == 'start_session_pin':
try:
if not (data['card_number'].isnumeric()): # and (data['pin'].isnumeric() or data['pin'] == '')):
raise ApiError(ERR_PARAM)
except KeyError:
raise ApiError(ERR_PARAM)
try:
user = User.objects.get(account__card_number = data['card_number'])
if hashlib.md5(user.account.pin).hexdigest() != data['pin']:
raise ApiError(ERR_INCORRECT_PIN)
except User.DoesNotExist:
raise ApiError(ERR_USER_NOT_FOUND)
if user is not None:
# Credentials are valid, so save user id in session
s = SessionStore()
s['userid'] = user.id
s.save()
retval['session_key'] = s.session_key
else:
raise ApiError(ERR_INCORRECT_PIN)
elif action == 'get_user_info':
s = check_session(data)
user = User.objects.get(pk = s['userid'])
retval['id'] = user.id
retval['name'] = user.first_name + ' ' + user.last_name
retval['nick'] = user.username
retval['mail'] = user.email
retval['card_number'] = user.account.card_number
retval['credit'] = int(user.account.credit * 100)
elif action == 'get_item_info':
try:
try:
item = Product.objects.get(pk = data['id'])
except KeyError:
try:
item = Product.objects.get(productbarcode__barcode = data['ean'])
except KeyError:
raise ApiError(ERR_PARAM)
except Product.DoesNotExist:
raise ApiError(ERR_ITEM_NOT_FOUND)
retval['id'] = item.id
retval['name'] = item.name
retval['ean'] = str(item.productbarcode_set.all()[0])
retval['price'] = int(item.price * 100)
elif action == 'buy_items':
s = check_session(data)
shopping_list = {}
try:
for item in data['items']:
try:
p = Product.objects.get(pk = item[0])
shopping_list[p] = int(item[1])
except Product.DoesNotExist:
raise ApiError(ERR_ITEM_NOT_FOUND_)
except ValueError:
raise ApiError(ERR_PARAM)
except KeyError:
raise ApiError(ERR_PARAM)
user = User.objects.get(pk = s['userid'])
try:
if user.account.buy_products(shopping_list):
retval['new_credit'] = int(user.account.credit * 100)
else:
raise ApiError(ERR_INSUFFICIENT_CREDIT)
except ValueError:
raise ApiError(ERR_PARAM)
except ApiError as e:
error = {'code': e.code, 'msg': err_msgs[e.code]}
# Generate return object
ret = {'err_code': error['code'], 'err_msg': error['msg'], 'return_values': retval, 'api_version': API_VERSION}
print ret
return HttpResponse(json.dumps(ret))

2
cash/urls.py

@ -21,6 +21,8 @@ urlpatterns = patterns('', @@ -21,6 +21,8 @@ urlpatterns = patterns('',
url(r'usersettings(/(?P<submit>\w+))?/$', 'cash.views.usersettings',
name='usersettings'),
url(r'api/?$', 'cash.api.cashapi'),
)

Loading…
Cancel
Save