#!/usr/bin/python3
#
# Copyright (c) 2019 Clementine Computing LLC.
#
# This file is part of PopuFare.
#
# PopuFare is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PopuFare is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with PopuFare. If not, see .
#
## WORK IN PROGRESS
import json
import mysql.connector
import time
import datetime
import copy
import hashlib
import sys
import getopt
POPUFARE_API_VERSION = "2.0.0"
#conn = mysql.connector.connect(user='bus', password='bus', host='localhost', database='busdb', port=3306)
_USER = 'busapi'
_PASSWORD = 'bus'
_HOST = 'localhost'
_DATABASE = 'busdb'
_PORT = 5506
Function = [
"User",
"Card",
"Pass",
"Log",
"PricePoints",
"AdminGetCard", "AdminGetCards", "AdminGetPass", "AdminGetUser",
"AdminGetAdmin", "AdminGetPassesOnCard", "AdminGetPendingQueue", "AdminProcessPendingQueue",
"AdminRemovePendingQueue", "AdminCreateCardBlock", "AdminCreateCard", "AdminSetUser",
"AdminSetAdmin", "AdminAddPass", "AdminAddCard", "AdminAddUser",
"AdminAddAdmin", "AdminRemovePass", "AdminRemovePasses", "AdminRemoveCard",
"AdminRemoveUser", "AdminRemoveAdmin", "AdminTransferCard", "AdminTransferPass",
"AdminGetPassOptions", "AdminAddCardToUser", "AdminRemoveCardFromUser", "AdminGetAdminPermissions",
"AdminAddAdminPermissions", "AdminRemoveAdminPermissions", "AdminAddAdminApiPermissions", "AdminRemoveAdminApiPermissions",
"AdminSetAdminApiPermissions", "AdminGetCustomCard", "AdminGetAdmins", "AdminSearchCards",
"AdminSearchUsers", "AdminSearchAdmins"]
PASS_FIELDS = ["logical_card_id", "issued", "activated", "deactivated", "firstused", "lastused",
"nrides_orig", "nrides_remain", "nday_orig", "nday_expiration",
"active", "expired", "queue_order",
"rule", "comment", "paytype" ]
CARD_FIELDS = ["mag_token", "rfid_token", "comment", "userid", "issued", "deactivated", "lastused",
"firstused", "group_id", "issuetype"]
USER_FIELDS = ["username", "comment", "first_name", "last_name", "phone",
"email", "address", "city", "state", "zip", "passwordhash",
"shipping_address", "shipping_city", "shipping_state", "shipping_zip",
"shipping_name", "shipping_country_code", "shipping_country_name"]
GROUP_FIELDS = ["id", "group_id", "group_name"]
RULECLASS_FIELDS = ["id", "group_id", "group_name"]
def Request(ctx, db_info = { "user":_USER, "pass":_PASSWORD, "host":_HOST, "db":_DATABASE, "port":_PORT}):
#_conn = mysql.connector.connect(user=_USER, password=_PASSWORD, host=_HOST, database=_DATABASE, port=_PORT)
_conn = mysql.connector.connect(user=db_info["user"], password=db_info["pass"], host=db_info["host"], database=db_info["db"], port=db_info["port"])
res = {}
if "function" in ctx:
if ctx["function"] == "CardInfo":
res = CardInfo(_conn, ctx)
elif ctx["function"] == "UserInfo":
res = UserInfo(_conn, ctx)
elif ctx["function"] == "User":
res = User(_conn, ctx)
elif ctx["function"] == "Card":
res = Card(_conn, ctx)
elif ctx["function"] == "Pass":
res = Pass(_conn, ctx)
elif ctx["function"] == "Group":
res = Group(_conn, ctx)
elif ctx["function"] == "Ruleclass":
res = Ruleclass(_conn, ctx)
elif ctx["function"] == "RecycleCard":
res = RecycleCard(_conn, ctx)
elif ctx["function"] == "AddCardBlock":
res = AddCardBlock(_conn, ctx)
elif ctx["function"] == "Search":
res = Search(_conn, ctx)
elif ctx["function"] == "Pending":
res = Pending(_conn, ctx)
elif ctx["function"] == "ping":
res["result"] = "success"
res["data"] = "pong"
_conn.close()
return res
## _ _ __
## ___ __ _ _ __ __| (_)_ __ / _| ___
## / __/ _` | '__/ _` | | '_ \| |_ / _ \
## | (_| (_| | | | (_| | | | | | _| (_) |
## \___\__,_|_| \__,_|_|_| |_|_| \___/
##
def CardInfo(db, ctx):
card_res = {}
action = "get"
if "action" in ctx:
action = ctx["action"]
if action == "get":
print("CardInfo:", ctx)
cardid = -1
if "logical_card_id" in ctx:
cardid = ctx["logical_card_id"]
card_res["logical_card_id"] = cardid
card_res = Card(db, {"action":"get", "logical_card_id": cardid})
card_res["pass"] = []
if card_res["result"] == "success":
## through each of the passes on the card
##
pass_query = "select user_pass_id from user_pass where logical_card_id = %s and expired = 0 order by queue_order asc"
pass_cursor = db.cursor()
pass_cursor.execute(pass_query, [card_res["logical_card_id"]])
pass_rows = pass_cursor.fetchall()
for pass_row in pass_rows:
pass_res = Pass(db, {"action":"get", "user_pass_id":pass_row[0]})
card_res["pass"].append(pass_res)
card_res["user"] = {}
if ((card_res["userid"] is not None) and (int(card_res["userid"]) >= 0)):
card_res["user"] = User(db, {"action":"get", "userid": card_res["userid"] })
elif action == "search":
card_res["cards"] = []
res_cardid = Card(db, ctx)
for cid in res_cardid["logical_card_ids"]:
_c = CardInfo(db, {"action":"get", "logical_card_id":cid})
card_res["cards"].append(_c)
card_res["result"] = "success"
return card_res
## _ __
## _ _ ___ ___ _ __(_)_ __ / _| ___
## | | | / __|/ _ \ '__| | '_ \| |_ / _ \
## | |_| \__ \ __/ | | | | | | _| (_) |
## \__,_|___/\___|_| |_|_| |_|_| \___/
##
def UserInfo(db, ctx):
res = {}
res["result"] = "fail"
userid = -1
if ("userid" in ctx):
userid = ctx["userid"]
pass_fields = PASS_FIELDS.copy()
card_fields = CARD_FIELDS.copy()
user_fields = USER_FIELDS.copy()
res["userid"] = userid
cursor = db.cursor()
## fill in user data
##
res["user"] = {}
fields = USER_FIELDS.copy()
query = "select " + ",".join(fields) + " from users where userid = %s"
cursor.execute(query, [userid])
row = cursor.fetchone()
if row is None:
res["api_comment"] = "user not found"
return res
res["user"]["userid"] = userid
for idx,f in enumerate(user_fields):
res["user"][f] = row[idx]
## go through each card and fill in card data and pass data
##
res["card"] = []
query = "select logical_card_id from user_card where userid = %s and active = 1 order by logical_card_id asc"
card_cursor = db.cursor()
card_cursor.execute(query, [userid])
rows = card_cursor.fetchall()
for row in rows:
card_res = CardInfo(db, {"logical_card_id":row[0]})
res["card"].append(card_res)
res["result"] = "success"
return res
def _update_pass_bits(cursor, passid):
q = "select logical_card_id from user_pass where user_pass_id = %s"
cursor.execute(q, [passid])
rows = cursor.fetchall()
print("\n\nupdating pass bits", passid, "\n\n")
cardid = -1
for row in rows:
cardid = row[0]
break
print("\n\nupdating pass bits cardid:", cardid, "\n\n")
if cardid < 0: return
q = "update user_pass set active = 0 where logical_card_id = %s"
cursor.execute(q, [cardid])
q = "update user_pass set active = 1 where logical_card_id = %s and expired = 0 and queue_order = " + \
"( select min(x.queue_order) from user_pass x where x.logical_card_id = %s and x.expired = 0 )"
cursor.execute(q, [cardid,cardid])
## _ _
## _ __ _ _| | ___ ___| | __ _ ___ ___
## | '__| | | | |/ _ \/ __| |/ _` / __/ __|
## | | | |_| | | __/ (__| | (_| \__ \__ \
## |_| \__,_|_|\___|\___|_|\__,_|___/___/
##
def Ruleclass(db, ctx):
res = {}
ruleclass_fields = RULECLASS_FIELDS.copy()
cursor = db.cursor()
fields = ruleclass_fields.copy()
field_vals = []
if ctx["action"] == "search":
query = "select id, rulename, ruleclass from rule_class"
cursor.execute(query)
rows = cursor.fetchall()
res["ruleclass"] = []
for row in rows:
res["ruleclass"].append({"id":row[0], "rulename":row[1], "ruleclass":row[2]})
db.commit()
return res
##
## _ __ __ _ ___ ___
## | '_ \ / _` / __/ __|
## | |_) | (_| \__ \__ \
## | .__/ \__,_|___/___/
## |_|
def Pass(db, ctx):
res = {}
passid = -1
if ("user_pass_id" in ctx):
passid = ctx["user_pass_id"]
pass_fields = PASS_FIELDS.copy()
cursor = db.cursor()
fields = pass_fields.copy()
field_vals = []
if (ctx["action"] == "get"):
query = "select " + ",".join(pass_fields) + " from user_pass where user_pass_id = %s"
cursor.execute(query, [passid])
row = cursor.fetchone()
if row is not None:
res["result"] = "success"
res["user_pass_id"] = passid
for idx,f in enumerate(pass_fields):
if isinstance(row[idx], datetime.datetime):
res[f] = row[idx].strftime("%Y-%m-%d %H:%M:%S")
else:
res[f] = row[idx]
else:
res["result"] = "fail"
res["api_comment"] = "pass not found"
elif (ctx["action"] == "add"):
if (not "logical_card_id" in ctx) or (ctx["logical_card_id"] == ''):
res["result"] = "fail"
res["api_comment"] = "must have logical_card_id to add pass"
else:
## fill in some default values
##
dt = time.strftime('%Y-%m-%d %H:%M:%S')
if "issued" not in ctx: ctx["issued"] = dt
if "expired" not in ctx: ctx["expired"] = 0
if "active" not in ctx: ctx["active"] = 0
if "logical_card_id" in ctx:
cardid = ctx["logical_card_id"]
_q = "select queue_order from user_pass where logical_card_id = %s and expired = 0 order by queue_order desc limit 1"
_c = db.cursor()
_c.execute(_q, [cardid])
_r = _c.fetchone()
if _r is not None:
ctx["queue_order"] = int(_r[0])+1
else:
ctx["active"] = 1
ctx["queue_order"] = 0
else:
ctx["queue_order"] = 0
for f in pass_fields:
if f in ctx: field_vals.append(ctx[f])
else: field_vals.append(None)
query = "insert into user_pass (" + ",".join(fields) + ") values (" + ",".join(["%s"]*len(fields)) + ")"
print(query)
print(fields, field_vals)
cursor.execute(query, field_vals)
res["user_pass_id"] = cursor.lastrowid
res["result"] = "success"
_update_pass_bits(cursor, passid);
elif (ctx["action"] == "update"):
update_field = []
update_val = []
for f in pass_fields:
if f in ctx:
update_field.append(f + "= %s")
update_val.append(ctx[f])
update_val.append(passid)
query = "update user_pass set " + ",".join(update_field) + " where user_pass_id = %s"
cursor.execute(query, update_val)
res["user_pass_id"] = passid
res["result"] = "success"
_update_pass_bits(cursor, passid);
elif (ctx["action"] == "deactivate"):
update_field = []
update_val = []
for f in pass_fields:
if f in ctx:
update_field.append(f + "= %s")
update_val.append(ctx[f])
update_val.append(passid)
query = "update user_pass set active = 0, expired = 1 where user_pass_id = %s"
cursor.execute(query, [passid])
_update_pass_bits(cursor, passid);
res["user_pass_id"] = passid
res["result"] = "success"
elif (ctx["action"] == "delete"):
query = "delete from user_pass where user_pass_id = %s"
cursor.execute(query, [passid])
_update_pass_bits(cursor, passid);
res["result"] = "success"
db.commit()
return res
## _
## ___ __ _ _ __ __| |
## / __/ _` | '__/ _` |
## | (_| (_| | | | (_| |
## \___\__,_|_| \__,_|
##
def Card(db, ctx):
card_fields = CARD_FIELDS.copy()
res = {}
cardid = -1
if ("logical_card_id" in ctx):
cardid = ctx["logical_card_id"]
cursor = db.cursor()
fields = card_fields.copy()
field_vals = []
if (ctx["action"] == "get"):
query = "select " + ",".join(card_fields) + " from user_card where logical_card_id = %s"
cursor.execute(query, [cardid])
row = cursor.fetchone()
if row is not None:
res["logical_card_id"] = cardid
for idx,f in enumerate(card_fields):
if isinstance(row[idx], datetime.datetime):
res[f] = row[idx].strftime("%Y-%m-%d %H:%M:%S")
else:
res[f] = row[idx]
res["result"] = "success"
else:
res["result"] = "fail"
res["api_comment"] = "card not found"
elif (ctx["action"] == "add"):
fields.append("active")
for f in card_fields:
if f in ctx: field_vals.append(ctx[f])
else: field_vals.append(None)
field_vals.append(1)
query = "insert into user_card (" + ",".join(fields) + ") values (" + ",".join(["%s"]*len(fields)) + ")"
cursor.execute(query, field_vals)
res["logical_card_id"] = cursor.lastrowid
res["result"] = "success"
elif (ctx["action"] == "update"):
if not "logical_card_id" in ctx:
res["result"] = "fail"
res["api_comment"] = "must supply a logical_card_id"
else:
update_field = []
update_val = []
query_card_id = ctx["logical_card_id"]
cursor.execute("select logical_card_id from user_card where logical_card_id = %s", [query_card_id])
rows = cursor.fetchall()
if len(rows) == 0:
res["result"] = "fail"
res["api_comment"] = "card not found"
else:
print(">>>>", len(rows))
for row in rows:
logical_card_id = row[0]
for f in card_fields:
if f in ctx:
update_field.append(f + "= %s")
update_val.append(ctx[f])
update_val.append(cardid)
query = "update user_card set " + ",".join(update_field) + " where logical_card_id = %s"
cursor.execute(query, update_val)
res["logical_card_id"] = cardid
res["result"] = "success"
elif (ctx["action"] == "delete"):
query = "delete from user_card where logical_card_id = %s"
cursor.execute(query, [cardid])
res["result"] = "success"
elif (ctx["action"] == "search"):
query = "select logical_card_id from user_card where "
n_search = 0
if "logical_card_id" in ctx:
query += " logical_card_id = %s"
field_vals.append( ctx["logical_card_id"])
n_search += 1
if "mag_token" in ctx:
query += " mag_token like %s "
field_vals.append( '%' + ctx["mag_token"] + '%')
n_search += 1
if "rfid_token" in ctx:
if len(field_vals)>0: query += " and "
query += " rfid_token like %s "
field_vals.append( '%' + ctx["rfid_token"] + '%')
n_search += 1
query_limit = " "
if "limit" in ctx:
query_limit = " limit %s "
search_vals.append(ctx["limit"])
query += query_limit
res["logical_card_ids"] = []
if n_search > 0:
cursor.execute(query, field_vals)
rows = cursor.fetchall()
for row in rows:
res["logical_card_ids"].append(row[0])
res["result"] = "success"
db.commit()
return res
##
## __ _ _ __ ___ _ _ _ __
## / _` | '__/ _ \| | | | '_ \
## | (_| | | | (_) | |_| | |_) |
## \__, |_| \___/ \__,_| .__/
## |___/ |_|
def Group(db,ctx):
group_res = { "result":"fail"}
action = "get"
if "action" in ctx:
action = ctx["action"]
cursor = db.cursor()
if action == "get":
group_res["group"] = []
query = "select group_id, group_name from groups order by group_id asc"
cursor.execute(query)
rows = cursor.fetchall()
for row in rows:
group_res["group"].append({"group_id":row[0], "group_name":row[1]})
group_res["result"] = "success"
elif action == "add":
if "group_name" not in ctx:
group_res["result"] = "fail"
group_res["api_comment"] = "must provide group name to add"
return res
group_name = ctx["group_name"]
group_id = -1
cursor.execute("select max(group_id) from groups")
x = cursor.fetchone()
if x[0] is None:
group_id = 1
else:
group_id = int(x[0]) + 1
cursor.execute("insert into groups (group_id, group_name) values (%s, %s)", [group_id, group_name])
group_res["result"] = "success"
group_res["group_id"] = group_id
group_res["group_name"] = group_name
elif action == "getone":
group_res["group"] = []
query = "select group_id, group_name from groups where group_name = %s "
cursor.execute(query, [ctx["group"]])
row = cursor.fetchone()
if not row:
group_res["result"] = "fail"
group_res["api_comment"] = "invalid group"
else:
group_res["result"] = "success"
group_res["group_id"] = row[0]
elif action == "default":
return Group(db, {"action":"getone", "group":"TEST-ORG"})
db.commit()
return group_res
##
## _ _ ___ ___ _ __
## | | | / __|/ _ \ '__|
## | |_| \__ \ __/ |
## \__,_|___/\___|_|
##
def User(db, ctx):
user_fields = USER_FIELDS.copy()
res = {}
cursor = db.cursor()
fields = user_fields.copy()
user_vals = []
userid = -1
if "userid" in ctx: userid = ctx["userid"]
print("cp.user")
## USER GET
##
if (ctx["action"] == "get"):
query = "select " + ",".join(user_fields) + " from users where userid = %s"
cursor.execute(query, [userid])
row = cursor.fetchone()
if row is not None:
res["userid"] = userid
for idx,f in enumerate(user_fields):
if isinstance(row[idx], datetime.datetime):
res[f] = row[idx].strftime("%Y-%m-%d %H:%M:%S")
else:
res[f] = row[idx]
res["result"] = "success"
else:
res["result"] = "fail"
res["api_comment"] = "user not found"
## USER ADD
##
elif (ctx["action"] == "add"):
if ((not "password" in ctx) or
(not "username" in ctx) ):
res["api_comment"] = "invalid parameters, need username and password to create account"
res["result"] = "fail"
else:
uname = ctx["username"]
pword = ctx["password"]
fields.append("active")
fields.append("created")
for f in user_fields:
if f in ctx: user_vals.append(ctx[f])
elif f == "passwordhash":
ha = hashlib.sha256()
ha.update(str.encode(uname))
ha.update(str.encode(pword))
user_vals.append(ha.hexdigest())
else: user_vals.append(None)
user_vals.append(1)
user_vals.append(time.strftime('%Y-%m-%d %H:%M:%S'))
query = "insert into users (" + ",".join(fields) + ") values (" + ",".join(["%s"]*len(fields)) + ")"
cursor.execute(query, user_vals)
res["userid"] = cursor.lastrowid
res["result"] = "success"
## USER UPDATE
##
elif (ctx["action"] == "update"):
if not "userid" in ctx:
res["result"] = "fail"
res["api_comment"] = "no userid specified"
else:
uname = ''
query = "select username from users where userid = %s";
cursor.execute(query, [userid])
rows = cursor.fetchall()
for row in rows:
uname = row[0]
if uname == '':
res["result"] = "fail"
res["api_comment"] = "could not find username"
else:
update_field = []
update_val = []
print("user_field:", user_fields)
print("ctx:", ctx)
for f in user_fields:
if (f == "passwordhash") and ("password" in ctx):
update_field.append(" passwordhash = %s ")
ha = hashlib.sha256()
ha.update(str.encode(uname))
ha.update(str.encode(ctx["password"]))
update_val.append(ha.hexdigest())
elif f in ctx:
update_field.append(f + "= %s")
update_val.append(ctx[f])
else:
pass
#update_val.append(None)
update_val.append(userid)
if len(update_field) == 0:
print("NOPE")
print("manage_user.update>>>", userid, ":".join(update_field), ":".join(update_val), len(update_field))
query = "update users set " + ",".join(update_field) + " where userid = %s"
print("WTFFF???", query)
cursor.execute(query, update_val)
res["userid"] = userid
res["result"] = "success"
## USER DELETE
##
elif (ctx["action"] == "delete"):
query = "delete from users where userid = %s"
cursor.execute(query, [userid])
## USER SEARCH
##
elif (ctx["action"] == "search"):
res["userids"] = []
res["userid"] = userid
res["result"] = "success"
search_field = []
search_val = []
for f in user_fields:
if f in ctx:
search_field.append(f + " like %s")
search_val.append('%' + ctx[f] + '%')
query_limit = " "
if "limit" in ctx:
query_limit = " limit %s "
search_val.append(ctx["limit"])
query = "select userid from users where " + " and ".join(search_field) + query_limit
cursor.execute(query, search_val)
rows = cursor.fetchall()
for row in rows:
res["userids"].append(row[0])
db.commit()
return res
## _ _
## _ __ ___ ___ _ _ ___| | ___ ___ __ _ _ __ __| |
## | '__/ _ \/ __| | | |/ __| |/ _ \ / __/ _` | '__/ _` |
## | | | __/ (__| |_| | (__| | __/ | (_| (_| | | | (_| |
## |_| \___|\___|\__, |\___|_|\___| \___\__,_|_| \__,_|
## |___/
def RecycleCard(db, ctx):
res = {"result":"fail"}
cursor = db.cursor()
fields = ["logical_card_id", "rfid_token", "mag_token", "group",
"userid",
"rule", "pass_class", "nrides_remain", "nrides_orig", "nday_orig" ]
val = {}
for f in fields:
if f in ctx:
if ctx[f] and len(ctx[f]) > 0:
val[f] = ctx[f]
if ((not ("logical_card_id" in val)) and
(not ("rfid_token" in val)) and
(not ("mag_token" in val))):
return res
logical_card_id = -1
if not ("logical_card_id" in val):
if "mag_token" in val:
query = "select logical_card_id from user_card where mag_token = %s and active = 1"
cursor.execute(query, [val["mag_token"]])
cid = cursor.fetchone()
if cid is not None:
val["logical_card_id"] = cid[0]
else:
return res
elif "rfid_token" in val:
query = "select logical_card_id from user_card where rfid_token = %s and active = 1"
cursor.execute(query, [val["rfid_token"]])
cid = cursor.fetchone()
if cid is not None:
val["logical_card_id"] = cid[0]
else:
return res
group_info = Group(db, {"action":"default"})
if "group" in val:
group_info = Group(db, {"action":"getone", "group":val["group"]})
if group_info["result"] != "success":
res["api_comment"] = "invalid group"
return res
query = "update user_card set active = 0 where logical_card_id = %s"
cursor.execute(query, [val["logical_card_id"]])
card_info = {"action":"add", "group_id":group_info["group_id"], "active":1}
if "mag_token" in val: card_info["mag_token"] = val["mag_token"]
if "rfid_token" in val: card_info["rfid_token"] = val["rfid_token"]
card_res = Card(db, card_info)
if card_res["result"] != "success":
res["result"] = "fail"
res["api_comment"] = "failed to find card"
return res
res["logical_card_id"] = card_res["logical_card_id"]
if "pass_class" in val:
pass_opt = {"action":"add", "logical_card_id": res["logical_card_id"] }
if val["pass_class"] == "OTHER":
pass_opt["rule"] = val["rule"]
Pass(db, pass_opt)
elif val["pass_class"] == "NRIDE":
pass_opt["rule"] = val["rule"]
pass_opt["nrides_orig"] = val["nrides_orig"]
pass_opt["nrides_remain"] = val["nrides_remain"]
Pass(db, pass_opt)
elif val["pass_class"] == "NDAY":
pass_opt["rule"] = val["rule"]
pass_opt["nday_orig"] = val["nday_orig"]
Pass(db, pass_opt)
return res
## _
## ___ ___ __ _ _ __ ___| |__
## / __|/ _ \/ _` | '__/ __| '_ \
## \__ \ __/ (_| | | | (__| | | |
## |___/\___|\__,_|_| \___|_| |_|
##
def Search(db, ctx):
res = {"result":"fail"}
cursor = db.cursor()
fields = ["search_type", "search_string", "start", "count"]
start = "0"
count = "100"
val = {}
for f in fields:
if f in ctx:
if ctx[f] and len(ctx[f]) > 0:
val[f] = ctx[f]
if "start" in val: start = val["start"]
if "count" in val: count = val["count"]
if val["search_type"] == "card":
t = val["search_string"]
p = '%' + t + '%'
query = "select logical_card_id, mag_token, rfid_token, userid, issued, firstused, lastused, group_id, issuetype"
query += " from user_card where mag_token like %s "
query += " or rfid_token like %s "
query += " or comment like %s "
query += " or issuetype like %s "
query += " and active = 1 "
query += " order by logical_card_id desc"
query += " limit %s,%s "
_v = [p,p, p, p, int(start), int(start) + int(count)]
#cursor.execute(query, [p, p, p, p])
cursor.execute(query, _v)
rows = cursor.fetchall()
res["data"] = []
for row in rows:
_d = {
"iscard": 1,
"logical_card_id": row[0],
"mag_token": row[1],
"rfid_token": row[2],
"userid": row[3],
"issued": row[4],
"firstused": row[5],
"lastused": row[6],
"group_id": row[7],
"issuetype": row[8]
}
res["data"].append( _d )
res["result"] = "success"
elif val["search_type"] == "user":
t = val["search_string"]
p = '%' + t + '%'
fields = [ "username", "first_name", "last_name", "phone", "email", "address", "city","state", "zip", "created",
"shipping_address", "shipping_city", "shipping_state", "shipping_zip", "shipping_name",
"shipping_country_code", "shipping_country_name" ]
query = "select userid, " + ", ".join(fields)
query += " from users "
query += " where " + " like %s or ".join(fields) + " like %s "
query += " and active = 1 "
query += " order by userid desc"
query += " limit %s,%s "
print("user query:", query)
_v = [p]*len(fields)
_v.append(int(start))
_v.append(int(start) + int(count))
#cursor.execute(query, [p]*len(fields))
cursor.execute(query, _v)
rows = cursor.fetchall()
res["data"] = []
for row in rows:
_d = { "userid": row[0], "isuser": 1 }
for idx,f in enumerate(fields):
_d[f] = row[idx+1]
res["data"].append( _d )
res["result"] = "success"
elif val["search_type"] == "admin":
t = val["search_string"]
p = '%' + t + '%'
fields = [ "username", "comment" ]
query = "select userid, group_id, " + ", ".join(fields)
query += " from admins "
query += " where " + " like %s or ".join(fields) + " like %s "
query += " and active = 1 "
query += " order by userid desc"
query += " limit %s,%s "
print("user query:", query)
_v = [p]*len(fields)
_v.append(int(start))
_v.append(int(start) + int(count))
cursor.execute(query, _v)
rows = cursor.fetchall()
res["data"] = []
for row in rows:
_d = { "userid": row[0], "group_id": row[1], "isadmin": 1 }
for idx,f in enumerate(fields):
_d[f] = row[idx+2]
res["data"].append( _d )
res["result"] = "success"
return res
## _ _ _ _ _ _
## __ _ __| | __| | ___ __ _ _ __ __| | | |__ | | ___ ___| | __
## / _` |/ _` |/ _` | / __/ _` | '__/ _` | | '_ \| |/ _ \ / __| |/ /
## | (_| | (_| | (_| | | (_| (_| | | | (_| | | |_) | | (_) | (__| <
## \__,_|\__,_|\__,_| \___\__,_|_| \__,_| |_.__/|_|\___/ \___|_|\_\
##
def AddCardBlock(db, ctx):
res = {"result":"fail"}
cursor = db.cursor()
fields = ["mag_token", "rfid_token", "group_id",
"rule", "nday_orig", "nrides_remain", "nrides_orig",
"count",
"pass_rule", "pass_nrides_remain", "pass_nrides_orig",
"pass_nday_orig", "pass_class"]
val = {}
for f in fields:
if f in ctx:
if ctx[f] and len(ctx[f]) > 0:
val[f] = ctx[f]
if not ("count" in val):
res["result"] = "fail"
res["api_comment"] = "count must be positive"
return res
if ((not ("mag_token" in val)) and
(not ("rfid_token" in val))):
res["result"] = "fail"
res["api_comment"] = "mag_token and/or rfid_token must be specified"
return res
use_mag = False
use_rfid = False
if "mag_token" in val:
use_mag = True
pfx_mag_cred = val["mag_token"].split(":")[0]
base_mag_cred = int(val["mag_token"].split(":")[-1])
if "rfid_token" in val:
use_rfid = True
pfx_rfid_cred = ":".join(val["rfid_token"].split(":")[0:2])
base_rfid_cred = int(val["rfid_token"].split(":")[-1])
logical_card_ids = []
for idx in range(int(val["count"])):
card_info = {"action":"add", "group_id":val["group_id"], "active":1}
if "mag_token" in val: card_info["mag_token"] = val["mag_token"]
if "rfid_token" in val: card_info["rfid_token"] = val["rfid_token"]
if use_mag:
card_info["mag_token"] = pfx_mag_cred + ":" + str(base_mag_cred + idx)
if use_rfid:
card_info["rfid_token"] = pfx_rfid_cred + ":" + str(base_rfid_cred + idx)
card_res = Card(db, card_info)
if card_res["result"] != "success":
res["result"] = "fail"
res["api_comment"] = "failed to add card"
return res
logical_card_id = card_res["logical_card_id"]
if "pass_rule" in val:
pass_info = {"action":"add", "logical_card_id":logical_card_id, "active":1,
"rule" : val["pass_rule"] }
if val["pass_class"] == "OTHER":
pass
elif val["pass_class"] == "NRIDE":
pass_info["nrides_remain"] = val["pass_nrides_remain"]
pass_info["nrides_orig"] = val["pass_nrides_orig"]
elif val["pass_class"] == "NDAY":
pass_info["nday_orig"] = val["pass_nday_orig"]
pass_res = Pass(db, pass_info)
logical_card_ids.append(logical_card_id)
res["result"] = "success"
res["logical_card_ids"] = logical_card_ids
return res
## ____ _ _
## | _ \ ___ _ __ __| (_)_ __ __ _
## | |_) / _ \ '_ \ / _` | | '_ \ / _` |
## | __/ __/ | | | (_| | | | | | (_| |
## |_| \___|_| |_|\__,_|_|_| |_|\__, |
## |___/
def Pending(db, ctx):
res = {"result":"fail"}
cursor = db.cursor()
fields = ["org_card_order_queue_id", "userid", "logical_card_id", "created", "processed", "comment" ]
val = {}
for f in fields:
if f in ctx:
if (type(ctx[f]) == int) or (ctx[f] and ((type(ctx[f]) != int) and (len(ctx[f]) > 0))):
val[f] = ctx[f]
if (ctx["action"] == "getall"):
query = "select org_card_order_queue_id, userid, logical_card_id, "
query += " date_format(created, '%Y-%m-%d %H:%i:%S'), "
query += " date_format(processed,'%Y-%m-%d %H:%i:%S'), comment, pending "
query += " from org_card_order_queue "
query += " where pending = 1 "
query += " order by org_card_order_queue_id asc"
cursor.execute(query)
rows = cursor.fetchall()
res["data"] = []
for row in rows:
_c = Card(db, {"action":"get", "logical_card_id":row[2]})
mag_token = ""
if "mag_token" in _c: mag_token = _c["mag_token"]
rfid_token = ""
if "rfid_token" in _c: rfid_token = _c["rfid_token"]
_r = {"org_card_order_queue_id":row[0], "userid":row[1], "logical_card_id":row[2], "created": row[3],
"processed":row[4], "comment":row[5], "pending":row[6],
"mag_token":mag_token, "rfid_token":rfid_token}
res["data"].append(_r)
res["result"] = "success"
if (ctx["action"] == "get"):
query = "select org_card_order_queue_id, userid, logical_card_id, "
query += " date_format(created, '%Y-%m-%d %H:%i:%S'), "
query += " date_format(processed,'%Y-%m-%d %H:%i:%S'), comment, pending "
query += " from org_card_order_queue "
query += " where pending = 1 and org_card_order_queue_id = %s"
cursor.execute(query, [val["org_card_order_queue_id"]])
row = cursor.fetchone()
if row is None:
res["api_comment"] = "pending card not found"
return res
cols = ["org_card_order_queue_id", "userid", "logical_card_id", "created", "processed", "comment", "pending" ]
res["pending_card"] = {}
for idx,f in enumerate(cols):
res["pending_card"][f] = row[idx]
cid = res["pending_card"]["logical_card_id"]
_r = CardInfo(db, {"action":"get", "logical_card_id":cid})
if _r["result"] == "fail":
return _r
res["cardinfo"] = _r
res["result"] = "success"
elif (ctx["action"] == "add"):
query = "insert into org_card_order_queue (userid, logical_card_id, comment, pending, created) values (%s,%s,%s,1,now())"
cursor.execute(query, [val["userid"], val["logical_card_id"], val["comment"]])
res["org_card_order_queue_id"] = cursor.lastrowid
res["result"] = "success"
elif (ctx["action"] == "process"):
query = "update org_card_order_queue set pending = 0, processed = now() where org_card_order_queue_id = %s"
cursor.execute(query, [val["org_card_order_queue_id"]])
res["result"] = "success"
db.commit()
return res
## _
## _ __ ___ __ _(_)_ __
## | '_ ` _ \ / _` | | '_ \
## | | | | | | (_| | | | | |
## |_| |_| |_|\__,_|_|_| |_|
##
def __test(db):
print("main")
print("---------")
print("---------")
print("---------")
res = User(db, {"action":"add", "username":"abe" })
print("user.add:", res)
res = User(db, {"action":"update", "username":"abeabe", "userid":res["userid"]})
print("user.update:", res)
res = User(db, {"action":"get", "userid":res["userid"]})
print("user.get:", res)
res = User(db, {"action":"delete", "userid": res["userid"]})
print("user.delete:", res)
print("---------")
print("---------")
print("---------")
res = Card(db, {"action":"get", "logical_card_id":1})
print("card.get:", res)
res = Card(db, {"action":"add", "mag_token":"2:1234", "rfid_token":"26:20:415", "comment":"testing api", "userid":1})
print("card.add:", res)
res = Card(db, {"action":"update", "mag_token":"2:9234", "logical_card_id":res["logical_card_id"]})
print("card.update:", res)
res = Card(db, {"action":"delete", "logical_card_id":res["logical_card_id"]})
print("card.delete:", res)
print("---------")
print("---------")
print("---------")
res = Pass(db, {"action":"get", "user_pass_id":11})
print("pass.get:", res)
res = Pass(db, {"action":"add", "logical_card_id":1, "queue_order":9, "rule":"TEST-ORG-NDAY", "nday_orig":3})
print("pass.add:", res)
res = Pass(db, {"action":"update", "user_pass_id":res["user_pass_id"], "queue_order":10, "rule":"TEST-ORG-NDAY", "nday_orig":5})
print("pass.update:", res)
res = Pass(db, {"action":"delete", "user_pass_id":res["user_pass_id"]})
print("pass.delete:", res)
print("---------")
print("---------")
print("---------")
res = UserInfo(db, {"userid":348})
print("userinfo:", json.dumps(res, indent=2))
print("---------")
print("---------")
print("---------")
res = Request({"function":"CardInfo", "action":"search", "logical_card_id":1})
print("request.card.search:", res)
def show_version(ofp):
ofp.write("PopufareAPI version " + POPUFARE_API_VERSION + "\n")
ofp.flush()
def show_help(ofp):
show_version(ofp)
ofp.write("\nusage:\n")
ofp.write("\n")
ofp.write(" PopufareAPI [-h] [-v] [-c config] [-u dbuser] [-p dbpass] [-H dbhost] [-D db] [-P dbport] \n")
ofp.write("\n")
ofp.write(" -c config file\n")
ofp.write(" -u db user\n")
ofp.write(" -p db pass\n")
ofp.write(" -H db host\n")
ofp.write(" -D db name\n")
ofp.write(" -P db port\n")
ofp.write(" -h help (this screen)\n")
ofp.write(" -v show version\n")
ofp.write("\n")
ofp.write("example:\n")
ofp.write("\n")
ofp.write(" PopufareAPI -d '{\"function\":\"ping\"}\n")
ofp.write("\n")
ofp.flush()
if __name__ == "__main__":
api_opt = {
"db_info": {
"user":"busapi",
"pass":"bus",
"host":"localhost",
"db":"busdb",
"port":5506
},
"config":"",
"data":""
}
data = {}
opts,args = getopt.getopt(sys.argv[1:], "hd:u:p:H:D:P:c:")
for o,a in opts:
if o == "-h":
show_help(sys.stdout)
sys.exit(0)
elif o == "-c":
api_opt["config"] = a
elif o == "-u":
api_opt["db_info"]["user"] = a
elif o == "-p":
api_opt["db_info"]["pass"] = a
elif o == "-H":
api_opt["db_info"]["host"] = a
elif o == "-D":
api_opt["db_info"]["db"] = a
elif o == "-P":
api_opt["db_info"]["port"] = int(a)
#elif o == "-d":
# api_opt["data"] = json.loads(a)
else:
show_help(sys.stderr)
sys.exit(-1)
if len(args) < 1:
sys.stderr.write("no data request\n")
show_help(sys.stderr)
sys.exit(-1)
api_opt["data"] = json.loads(args[0])
res = Request(api_opt["data"], api_opt["db_info"])
print(json.dumps(res,indent=2))
#conn = mysql.connector.connect(user=_USER, password=_PASSWORD, host=_HOST, database=_DATABASE, port=_PORT)
#conn = mysql.connector.connect(user=api_opt["dbuser"], password=api_opt["dbpass"], host=api_opt["dbhost"], database=api_opt["db"], port=api_opt["dbport"])
#main(conn)
#conn.close()