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.
252 lines
6.4 KiB
252 lines
6.4 KiB
from cashonly.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) |
|
|
|
if not s.has_key('userid'): |
|
raise ApiError(ERR_INVALID_SESSION) |
|
|
|
return s |
|
|
|
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) |
|
|
|
# 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': |
|
creds = {'username': data['user'], 'password': data['password']} |
|
retval['session_key'] = start_session(creds) |
|
|
|
elif action == 'start_session_pin': |
|
creds = {'card_number': data['card_number'], 'pin': data['pin']} |
|
retval['session_key'] = start_session(creds) |
|
|
|
elif action == 'close_session': |
|
s = check_session(data) |
|
s.delete |
|
|
|
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) |
|
|
|
if not item.active: |
|
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) |
|
|
|
elif action == 'modify_credit': |
|
s = check_session(data) |
|
|
|
treasurer = User.objects.get(pk=s['userid']) |
|
|
|
if not treasurer.has_perm('cashonly.change_account'): |
|
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) |
|
|
|
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))
|
|
|