You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
6.4 KiB
253 lines
6.4 KiB
9 years ago
|
from cashonly.models import *
|
||
11 years ago
|
from django.http import HttpResponse
|
||
|
from django.contrib.auth import authenticate
|
||
11 years ago
|
from django.views.decorators.csrf import csrf_exempt
|
||
11 years ago
|
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'
|
||
11 years ago
|
err_msgs[ERR_AUTH_KEY_NOT_PERMITTED] = 'The given authentication key \
|
||
|
has insufficient permissions for this action'
|
||
11 years ago
|
|
||
|
#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
|
||
|
|
||
11 years ago
|
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'
|
||
11 years ago
|
|
||
|
#Errors for cash_prepaid_card
|
||
|
ERR_CASH_CODE_NOT_VALID = 51
|
||
|
|
||
11 years ago
|
err_msgs[ERR_CASH_CODE_NOT_VALID] = 'Given code can\'t be found or has \
|
||
|
already been used'
|
||
11 years ago
|
|
||
|
#Errors for cash_[gs]et_config_key
|
||
|
ERR_CONFIG_TYPE_MISMATCH = 61
|
||
|
ERR_CONFIG_UNKNOWN_TYPE = 62
|
||
|
|
||
11 years ago
|
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'
|
||
11 years ago
|
|
||
|
#Errors for cash_modify_credit
|
||
|
ERR_USER_NOT_FOUND__ = 71
|
||
|
ERR_USER_NOT_AUTHORIZED = 72
|
||
|
|
||
|
err_msgs[ERR_USER_NOT_FOUND] = 'User not found'
|
||
11 years ago
|
err_msgs[ERR_USER_NOT_AUTHORIZED] = 'User not authorized to change another \
|
||
|
user\'s credit'
|
||
11 years ago
|
|
||
|
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)
|
||
|
|
||
11 years ago
|
if not s.has_key('userid'):
|
||
|
raise ApiError(ERR_INVALID_SESSION)
|
||
|
|
||
11 years ago
|
return s
|
||
|
|
||
11 years ago
|
def start_session(credentials):
|
||
|
try:
|
||
|
user = authenticate(**credentials)
|
||
|
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()
|
||
|
|
||
|
return s.session_key
|
||
|
else:
|
||
|
raise ApiError(ERR_INCORRECT_PIN)
|
||
|
|
||
11 years ago
|
# 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':
|
||
11 years ago
|
creds = {'username': data['user'], 'password': data['password']}
|
||
|
retval['session_key'] = start_session(creds)
|
||
11 years ago
|
|
||
|
elif action == 'start_session_pin':
|
||
11 years ago
|
creds = {'card_number': data['card_number'], 'pin': data['pin']}
|
||
|
retval['session_key'] = start_session(creds)
|
||
11 years ago
|
|
||
11 years ago
|
elif action == 'close_session':
|
||
|
s = check_session(data)
|
||
|
s.delete
|
||
|
|
||
11 years ago
|
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:
|
||
11 years ago
|
item = Product.objects.get(productbarcode__barcode =
|
||
|
data['ean'])
|
||
11 years ago
|
except KeyError:
|
||
|
raise ApiError(ERR_PARAM)
|
||
|
except Product.DoesNotExist:
|
||
|
raise ApiError(ERR_ITEM_NOT_FOUND)
|
||
|
|
||
11 years ago
|
if not item.active:
|
||
|
raise ApiError(ERR_ITEM_NOT_FOUND)
|
||
|
|
||
11 years ago
|
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)
|
||
9 years ago
|
|
||
11 years ago
|
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)
|
||
|
|
||
11 years ago
|
elif action == 'modify_credit':
|
||
|
s = check_session(data)
|
||
|
|
||
|
treasurer = User.objects.get(pk=s['userid'])
|
||
|
|
||
9 years ago
|
if not treasurer.has_perm('cashonly.change_account'):
|
||
11 years ago
|
raise ApiError(ERR_USER_NOT_AUTHORIZED)
|
||
|
|
||
|
try:
|
||
|
user = User.objects.get(pk=data['user_id'])
|
||
|
except User.DoesNotExist:
|
||
|
raise ApiError(ERR_USER_NOT_FOUND__)
|
||
|
except KeyError:
|
||
|
raise ApiError(ERR_PARAM)
|
||
|
|
||
|
try:
|
||
|
amount = int(data['amount'])
|
||
|
except (KeyError, ValueError):
|
||
|
raise ApiError(ERR_PARAM)
|
||
|
|
||
|
# TODO: Auslagern
|
||
|
PAYOUT_SUBJECT = ugettext_noop('Payout')
|
||
|
DEPOSIT_SUBJECT = ugettext_noop('Deposit')
|
||
|
DESCRIPTION = ugettext_noop('Authorized by %(first)s %(last)s')
|
||
|
|
||
|
if amount > 0:
|
||
|
subject = DEPOSIT_SUBJECT
|
||
|
else:
|
||
|
subject = PAYOUT_SUBJECT
|
||
|
|
||
|
desc = DESCRIPTION % {'first': treasurer.first_name,
|
||
|
'last': treasurer.last_name}
|
||
|
|
||
|
user.account.change_credit(amount/100, subject, desc)
|
||
|
|
||
|
retval['new_credit'] = int(user.account.credit*100)
|
||
11 years ago
|
|
||
|
except ApiError as e:
|
||
|
error = {'code': e.code, 'msg': err_msgs[e.code]}
|
||
|
|
||
|
# Generate return object
|
||
11 years ago
|
ret = {'err_code': error['code'],
|
||
|
'err_msg': error['msg'],
|
||
|
'return_values': retval,
|
||
|
'api_version': API_VERSION}
|
||
11 years ago
|
|
||
|
print ret
|
||
9 years ago
|
|
||
11 years ago
|
return HttpResponse(json.dumps(ret))
|