PopufareAPI.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. #!/usr/bin/python3
  2. #
  3. # Copyright (c) 2019 Clementine Computing LLC.
  4. #
  5. # This file is part of PopuFare.
  6. #
  7. # PopuFare is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # PopuFare is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
  19. #
  20. ## WORK IN PROGRESS
  21. import json
  22. import mysql.connector
  23. import time
  24. import datetime
  25. import copy
  26. import hashlib
  27. #conn = mysql.connector.connect(user='bus', password='bus', host='localhost', database='busdb', port=3306)
  28. _USER = 'busapi'
  29. _PASSWORD = 'bus'
  30. _HOST = 'localhost'
  31. _DATABASE = 'busdb'
  32. _PORT = 5506
  33. Function = [
  34. "User",
  35. "Card",
  36. "Pass",
  37. "Log",
  38. "PricePoints",
  39. "AdminGetCard", "AdminGetCards", "AdminGetPass", "AdminGetUser",
  40. "AdminGetAdmin", "AdminGetPassesOnCard", "AdminGetPendingQueue", "AdminProcessPendingQueue",
  41. "AdminRemovePendingQueue", "AdminCreateCardBlock", "AdminCreateCard", "AdminSetUser",
  42. "AdminSetAdmin", "AdminAddPass", "AdminAddCard", "AdminAddUser",
  43. "AdminAddAdmin", "AdminRemovePass", "AdminRemovePasses", "AdminRemoveCard",
  44. "AdminRemoveUser", "AdminRemoveAdmin", "AdminTransferCard", "AdminTransferPass",
  45. "AdminGetPassOptions", "AdminAddCardToUser", "AdminRemoveCardFromUser", "AdminGetAdminPermissions",
  46. "AdminAddAdminPermissions", "AdminRemoveAdminPermissions", "AdminAddAdminApiPermissions", "AdminRemoveAdminApiPermissions",
  47. "AdminSetAdminApiPermissions", "AdminGetCustomCard", "AdminGetAdmins", "AdminSearchCards",
  48. "AdminSearchUsers", "AdminSearchAdmins"]
  49. PASS_FIELDS = ["logical_card_id", "issued", "activated", "deactivated", "firstused", "lastused",
  50. "nrides_orig", "nrides_remain", "nday_orig", "nday_expiration",
  51. "active", "expired", "queue_order",
  52. "rule", "comment", "paytype" ]
  53. CARD_FIELDS = ["mag_token", "rfid_token", "comment", "userid", "issued", "deactivated", "lastused",
  54. "firstused", "group_id", "issuetype"]
  55. USER_FIELDS = ["username", "comment", "first_name", "last_name", "phone",
  56. "email", "address", "city", "state", "zip", "passwordhash",
  57. "shipping_address", "shipping_city", "shipping_state", "shipping_zip",
  58. "shipping_name", "shipping_country_code", "shipping_country_name"]
  59. GROUP_FIELDS = ["id", "group_id", "group_name"]
  60. RULECLASS_FIELDS = ["id", "group_id", "group_name"]
  61. def Request(ctx):
  62. _conn = mysql.connector.connect(user=_USER, password=_PASSWORD, host=_HOST, database=_DATABASE, port=_PORT)
  63. res = {}
  64. if "function" in ctx:
  65. if ctx["function"] == "CardInfo":
  66. res = CardInfo(_conn, ctx)
  67. elif ctx["function"] == "UserInfo":
  68. res = UserInfo(_conn, ctx)
  69. elif ctx["function"] == "User":
  70. res = User(_conn, ctx)
  71. elif ctx["function"] == "Card":
  72. res = Card(_conn, ctx)
  73. elif ctx["function"] == "Pass":
  74. res = Pass(_conn, ctx)
  75. elif ctx["function"] == "Group":
  76. res = Group(_conn, ctx)
  77. elif ctx["function"] == "Ruleclass":
  78. res = Ruleclass(_conn, ctx)
  79. elif ctx["function"] == "RecycleCard":
  80. res = RecycleCard(_conn, ctx)
  81. elif ctx["function"] == "AddCardBlock":
  82. res = AddCardBlock(_conn, ctx)
  83. _conn.close()
  84. return res
  85. ## _ _ __
  86. ## ___ __ _ _ __ __| (_)_ __ / _| ___
  87. ## / __/ _` | '__/ _` | | '_ \| |_ / _ \
  88. ## | (_| (_| | | | (_| | | | | | _| (_) |
  89. ## \___\__,_|_| \__,_|_|_| |_|_| \___/
  90. ##
  91. def CardInfo(db, ctx):
  92. card_res = {}
  93. action = "get"
  94. if "action" in ctx:
  95. action = ctx["action"]
  96. if action == "get":
  97. print("CardInfo:", ctx)
  98. cardid = -1
  99. if "logical_card_id" in ctx:
  100. cardid = ctx["logical_card_id"]
  101. card_res["logical_card_id"] = cardid
  102. card_res = Card(db, {"action":"get", "logical_card_id": cardid})
  103. card_res["pass"] = []
  104. if card_res["result"] == "success":
  105. ## through each of the passes on the card
  106. ##
  107. pass_query = "select user_pass_id from user_pass where logical_card_id = %s and expired = 0 order by queue_order asc"
  108. pass_cursor = db.cursor()
  109. pass_cursor.execute(pass_query, [card_res["logical_card_id"]])
  110. pass_rows = pass_cursor.fetchall()
  111. for pass_row in pass_rows:
  112. pass_res = Pass(db, {"action":"get", "user_pass_id":pass_row[0]})
  113. card_res["pass"].append(pass_res)
  114. card_res["user"] = {}
  115. if ((card_res["userid"] is not None) and (int(card_res["userid"]) >= 0)):
  116. card_res["user"] = User(db, {"action":"get", "userid": card_res["userid"] })
  117. elif action == "search":
  118. card_res["cards"] = []
  119. res_cardid = Card(db, ctx)
  120. for cid in res_cardid["logical_card_ids"]:
  121. _c = CardInfo(db, {"action":"get", "logical_card_id":cid})
  122. card_res["cards"].append(_c)
  123. card_res["result"] = "success"
  124. return card_res
  125. ## _ __
  126. ## _ _ ___ ___ _ __(_)_ __ / _| ___
  127. ## | | | / __|/ _ \ '__| | '_ \| |_ / _ \
  128. ## | |_| \__ \ __/ | | | | | | _| (_) |
  129. ## \__,_|___/\___|_| |_|_| |_|_| \___/
  130. ##
  131. def UserInfo(db, ctx):
  132. res = {}
  133. res["result"] = "fail"
  134. userid = -1
  135. if ("userid" in ctx):
  136. userid = ctx["userid"]
  137. pass_fields = PASS_FIELDS.copy()
  138. card_fields = CARD_FIELDS.copy()
  139. user_fields = USER_FIELDS.copy()
  140. res["userid"] = userid
  141. cursor = db.cursor()
  142. ## fill in user data
  143. ##
  144. res["user"] = {}
  145. fields = USER_FIELDS.copy()
  146. query = "select " + ",".join(fields) + " from users where userid = %s"
  147. cursor.execute(query, [userid])
  148. row = cursor.fetchone()
  149. if row is None:
  150. res["api_comment"] = "user not found"
  151. return res
  152. res["user"]["userid"] = userid
  153. for idx,f in enumerate(user_fields):
  154. res["user"][f] = row[idx]
  155. ## go through each card and fill in card data and pass data
  156. ##
  157. res["card"] = []
  158. query = "select logical_card_id from user_card where userid = %s and active = 1 order by logical_card_id asc"
  159. card_cursor = db.cursor()
  160. card_cursor.execute(query, [userid])
  161. rows = card_cursor.fetchall()
  162. for row in rows:
  163. card_res = CardInfo(db, {"logical_card_id":row[0]})
  164. res["card"].append(card_res)
  165. res["result"] = "success"
  166. return res
  167. def _update_pass_bits(cursor, passid):
  168. q = "select logical_card_id from user_pass where user_pass_id = %s"
  169. cursor.execute(q, [passid])
  170. rows = cursor.fetchall()
  171. print("\n\nupdating pass bits", passid, "\n\n")
  172. cardid = -1
  173. for row in rows:
  174. cardid = row[0]
  175. break
  176. print("\n\nupdating pass bits cardid:", cardid, "\n\n")
  177. if cardid < 0: return
  178. q = "update user_pass set active = 0 where logical_card_id = %s"
  179. cursor.execute(q, [cardid])
  180. q = "update user_pass set active = 1 where logical_card_id = %s and expired = 0 and queue_order = " + \
  181. "( select min(x.queue_order) from user_pass x where x.logical_card_id = %s and x.expired = 0 )"
  182. cursor.execute(q, [cardid,cardid])
  183. ## _ _
  184. ## _ __ _ _| | ___ ___| | __ _ ___ ___
  185. ## | '__| | | | |/ _ \/ __| |/ _` / __/ __|
  186. ## | | | |_| | | __/ (__| | (_| \__ \__ \
  187. ## |_| \__,_|_|\___|\___|_|\__,_|___/___/
  188. ##
  189. def Ruleclass(db, ctx):
  190. res = {}
  191. ruleclass_fields = RULECLASS_FIELDS.copy()
  192. cursor = db.cursor()
  193. fields = ruleclass_fields.copy()
  194. field_vals = []
  195. if ctx["action"] == "search":
  196. query = "select id, rulename, ruleclass from rule_class"
  197. cursor.execute(query)
  198. rows = cursor.fetchall()
  199. res["ruleclass"] = []
  200. for row in rows:
  201. res["ruleclass"].append({"id":row[0], "rulename":row[1], "ruleclass":row[2]})
  202. db.commit()
  203. return res
  204. ##
  205. ## _ __ __ _ ___ ___
  206. ## | '_ \ / _` / __/ __|
  207. ## | |_) | (_| \__ \__ \
  208. ## | .__/ \__,_|___/___/
  209. ## |_|
  210. def Pass(db, ctx):
  211. res = {}
  212. passid = -1
  213. if ("user_pass_id" in ctx):
  214. passid = ctx["user_pass_id"]
  215. pass_fields = PASS_FIELDS.copy()
  216. cursor = db.cursor()
  217. fields = pass_fields.copy()
  218. field_vals = []
  219. if (ctx["action"] == "get"):
  220. query = "select " + ",".join(pass_fields) + " from user_pass where user_pass_id = %s"
  221. cursor.execute(query, [passid])
  222. row = cursor.fetchone()
  223. if row is not None:
  224. res["result"] = "success"
  225. res["user_pass_id"] = passid
  226. for idx,f in enumerate(pass_fields):
  227. if isinstance(row[idx], datetime.datetime):
  228. res[f] = row[idx].strftime("%Y-%m-%d %H:%M:%S")
  229. else:
  230. res[f] = row[idx]
  231. else:
  232. res["result"] = "fail"
  233. res["api_comment"] = "pass not found"
  234. elif (ctx["action"] == "add"):
  235. if (not "logical_card_id" in ctx) or (ctx["logical_card_id"] == ''):
  236. res["result"] = "fail"
  237. res["api_comment"] = "must have logical_card_id to add pass"
  238. else:
  239. ## fill in some default values
  240. ##
  241. dt = time.strftime('%Y-%m-%d %H:%M:%S')
  242. if "issued" not in ctx: ctx["issued"] = dt
  243. if "expired" not in ctx: ctx["expired"] = 0
  244. if "active" not in ctx: ctx["active"] = 0
  245. if "logical_card_id" in ctx:
  246. cardid = ctx["logical_card_id"]
  247. _q = "select queue_order from user_pass where logical_card_id = %s and expired = 0 order by queue_order desc limit 1"
  248. _c = db.cursor()
  249. _c.execute(_q, [cardid])
  250. _r = _c.fetchone()
  251. if _r is not None:
  252. ctx["queue_order"] = int(_r[0])+1
  253. else:
  254. ctx["active"] = 1
  255. ctx["queue_order"] = 0
  256. else:
  257. ctx["queue_order"] = 0
  258. for f in pass_fields:
  259. if f in ctx: field_vals.append(ctx[f])
  260. else: field_vals.append(None)
  261. query = "insert into user_pass (" + ",".join(fields) + ") values (" + ",".join(["%s"]*len(fields)) + ")"
  262. print(query)
  263. print(fields, field_vals)
  264. cursor.execute(query, field_vals)
  265. res["user_pass_id"] = cursor.lastrowid
  266. res["result"] = "success"
  267. _update_pass_bits(cursor, passid);
  268. elif (ctx["action"] == "update"):
  269. update_field = []
  270. update_val = []
  271. for f in pass_fields:
  272. if f in ctx:
  273. update_field.append(f + "= %s")
  274. update_val.append(ctx[f])
  275. update_val.append(passid)
  276. query = "update user_pass set " + ",".join(update_field) + " where user_pass_id = %s"
  277. cursor.execute(query, update_val)
  278. res["user_pass_id"] = passid
  279. res["result"] = "success"
  280. _update_pass_bits(cursor, passid);
  281. elif (ctx["action"] == "deactivate"):
  282. update_field = []
  283. update_val = []
  284. for f in pass_fields:
  285. if f in ctx:
  286. update_field.append(f + "= %s")
  287. update_val.append(ctx[f])
  288. update_val.append(passid)
  289. query = "update user_pass set active = 0, expired = 1 where user_pass_id = %s"
  290. cursor.execute(query, [passid])
  291. _update_pass_bits(cursor, passid);
  292. res["user_pass_id"] = passid
  293. res["result"] = "success"
  294. elif (ctx["action"] == "delete"):
  295. query = "delete from user_pass where user_pass_id = %s"
  296. cursor.execute(query, [passid])
  297. _update_pass_bits(cursor, passid);
  298. res["result"] = "success"
  299. db.commit()
  300. return res
  301. ## _
  302. ## ___ __ _ _ __ __| |
  303. ## / __/ _` | '__/ _` |
  304. ## | (_| (_| | | | (_| |
  305. ## \___\__,_|_| \__,_|
  306. ##
  307. def Card(db, ctx):
  308. card_fields = CARD_FIELDS.copy()
  309. res = {}
  310. cardid = -1
  311. if ("logical_card_id" in ctx):
  312. cardid = ctx["logical_card_id"]
  313. cursor = db.cursor()
  314. fields = card_fields.copy()
  315. field_vals = []
  316. if (ctx["action"] == "get"):
  317. query = "select " + ",".join(card_fields) + " from user_card where logical_card_id = %s"
  318. cursor.execute(query, [cardid])
  319. row = cursor.fetchone()
  320. if row is not None:
  321. res["logical_card_id"] = cardid
  322. for idx,f in enumerate(card_fields):
  323. if isinstance(row[idx], datetime.datetime):
  324. res[f] = row[idx].strftime("%Y-%m-%d %H:%M:%S")
  325. else:
  326. res[f] = row[idx]
  327. res["result"] = "success"
  328. else:
  329. res["result"] = "fail"
  330. res["api_comment"] = "card not found"
  331. elif (ctx["action"] == "add"):
  332. fields.append("active")
  333. for f in card_fields:
  334. if f in ctx: field_vals.append(ctx[f])
  335. else: field_vals.append(None)
  336. field_vals.append(1)
  337. query = "insert into user_card (" + ",".join(fields) + ") values (" + ",".join(["%s"]*len(fields)) + ")"
  338. cursor.execute(query, field_vals)
  339. res["logical_card_id"] = cursor.lastrowid
  340. res["result"] = "success"
  341. elif (ctx["action"] == "update"):
  342. if not "logical_card_id" in ctx:
  343. res["result"] = "fail"
  344. res["api_comment"] = "must supply a logical_card_id"
  345. else:
  346. update_field = []
  347. update_val = []
  348. query_card_id = ctx["logical_card_id"]
  349. cursor.execute("select logical_card_id from user_card where logical_card_id = %s", [query_card_id])
  350. rows = cursor.fetchall()
  351. if len(rows) == 0:
  352. res["result"] = "fail"
  353. res["api_comment"] = "card not found"
  354. else:
  355. print(">>>>", len(rows))
  356. for row in rows:
  357. logical_card_id = row[0]
  358. for f in card_fields:
  359. if f in ctx:
  360. update_field.append(f + "= %s")
  361. update_val.append(ctx[f])
  362. update_val.append(cardid)
  363. query = "update user_card set " + ",".join(update_field) + " where logical_card_id = %s"
  364. cursor.execute(query, update_val)
  365. res["logical_card_id"] = cardid
  366. res["result"] = "success"
  367. elif (ctx["action"] == "delete"):
  368. query = "delete from user_card where logical_card_id = %s"
  369. cursor.execute(query, [cardid])
  370. res["result"] = "success"
  371. elif (ctx["action"] == "search"):
  372. query = "select logical_card_id from user_card where "
  373. n_search = 0
  374. if "logical_card_id" in ctx:
  375. query += " logical_card_id = %s"
  376. field_vals.append( ctx["logical_card_id"])
  377. n_search += 1
  378. if "mag_token" in ctx:
  379. query += " mag_token like %s "
  380. field_vals.append( '%' + ctx["mag_token"] + '%')
  381. n_search += 1
  382. if "rfid_token" in ctx:
  383. if len(field_vals)>0: query += " and "
  384. query += " rfid_token like %s "
  385. field_vals.append( '%' + ctx["rfid_token"] + '%')
  386. n_search += 1
  387. query_limit = " "
  388. if "limit" in ctx:
  389. query_limit = " limit %s "
  390. search_vals.append(ctx["limit"])
  391. query += query_limit
  392. res["logical_card_ids"] = []
  393. if n_search > 0:
  394. cursor.execute(query, field_vals)
  395. rows = cursor.fetchall()
  396. for row in rows:
  397. res["logical_card_ids"].append(row[0])
  398. res["result"] = "success"
  399. db.commit()
  400. return res
  401. ##
  402. ## __ _ _ __ ___ _ _ _ __
  403. ## / _` | '__/ _ \| | | | '_ \
  404. ## | (_| | | | (_) | |_| | |_) |
  405. ## \__, |_| \___/ \__,_| .__/
  406. ## |___/ |_|
  407. def Group(db,ctx):
  408. group_res = { "result":"fail"}
  409. action = "get"
  410. if "action" in ctx:
  411. action = ctx["action"]
  412. cursor = db.cursor()
  413. if action == "get":
  414. group_res["group"] = []
  415. query = "select group_id, group_name from groups order by group_id asc"
  416. cursor.execute(query)
  417. rows = cursor.fetchall()
  418. for row in rows:
  419. group_res["group"].append({"group_id":row[0], "group_name":row[1]})
  420. group_res["result"] = "success"
  421. elif action == "getone":
  422. group_res["group"] = []
  423. query = "select group_id, group_name from groups where group_name = %s "
  424. cursor.execute(query, [ctx["group"]])
  425. row = cursor.fetchone()
  426. if not row:
  427. group_res["result"] = "fail"
  428. group_res["api_comment"] = "invalid group"
  429. else:
  430. group_res["result"] = "success"
  431. group_res["group_id"] = row[0]
  432. elif action == "default":
  433. return Group(db, {"action":"getone", "group":"TEST-ORG"})
  434. db.commit()
  435. return group_res
  436. ##
  437. ## _ _ ___ ___ _ __
  438. ## | | | / __|/ _ \ '__|
  439. ## | |_| \__ \ __/ |
  440. ## \__,_|___/\___|_|
  441. ##
  442. def User(db, ctx):
  443. user_fields = USER_FIELDS.copy()
  444. res = {}
  445. cursor = db.cursor()
  446. fields = user_fields.copy()
  447. user_vals = []
  448. userid = -1
  449. if "userid" in ctx: userid = ctx["userid"]
  450. print("cp.user")
  451. ## USER GET
  452. ##
  453. if (ctx["action"] == "get"):
  454. query = "select " + ",".join(user_fields) + " from users where userid = %s"
  455. cursor.execute(query, [userid])
  456. row = cursor.fetchone()
  457. if row is not None:
  458. res["userid"] = userid
  459. for idx,f in enumerate(user_fields):
  460. if isinstance(row[idx], datetime.datetime):
  461. res[f] = row[idx].strftime("%Y-%m-%d %H:%M:%S")
  462. else:
  463. res[f] = row[idx]
  464. res["result"] = "success"
  465. else:
  466. res["result"] = "fail"
  467. res["api_comment"] = "user not found"
  468. ## USER ADD
  469. ##
  470. elif (ctx["action"] == "add"):
  471. if ((not "password" in ctx) or
  472. (not "username" in ctx) ):
  473. res["api_comment"] = "invalid parameters, need username and password to create account"
  474. res["result"] = "fail"
  475. else:
  476. uname = ctx["username"]
  477. pword = ctx["password"]
  478. fields.append("active")
  479. fields.append("created")
  480. for f in user_fields:
  481. if f in ctx: user_vals.append(ctx[f])
  482. elif f == "passwordhash":
  483. ha = hashlib.sha256()
  484. ha.update(str.encode(uname))
  485. ha.update(str.encode(pword))
  486. user_vals.append(ha.hexdigest())
  487. else: user_vals.append(None)
  488. user_vals.append(1)
  489. user_vals.append(time.strftime('%Y-%m-%d %H:%M:%S'))
  490. query = "insert into users (" + ",".join(fields) + ") values (" + ",".join(["%s"]*len(fields)) + ")"
  491. cursor.execute(query, user_vals)
  492. res["userid"] = cursor.lastrowid
  493. res["result"] = "success"
  494. ## USER UPDATE
  495. ##
  496. elif (ctx["action"] == "update"):
  497. if not "userid" in ctx:
  498. res["result"] = "fail"
  499. res["api_comment"] = "no userid specified"
  500. else:
  501. uname = ''
  502. query = "select username from users where userid = %s";
  503. cursor.execute(query, [userid])
  504. rows = cursor.fetchall()
  505. for row in rows:
  506. uname = row[0]
  507. if uname == '':
  508. res["result"] = "fail"
  509. res["api_comment"] = "could not find username"
  510. else:
  511. update_field = []
  512. update_val = []
  513. print("user_field:", user_fields)
  514. print("ctx:", ctx)
  515. for f in user_fields:
  516. if (f == "passwordhash") and ("password" in ctx):
  517. update_field.append(" passwordhash = %s ")
  518. ha = hashlib.sha256()
  519. ha.update(str.encode(uname))
  520. ha.update(str.encode(ctx["password"]))
  521. update_val.append(ha.hexdigest())
  522. elif f in ctx:
  523. update_field.append(f + "= %s")
  524. update_val.append(ctx[f])
  525. else:
  526. pass
  527. #update_val.append(None)
  528. update_val.append(userid)
  529. if len(update_field) == 0:
  530. print("NOPE")
  531. print("manage_user.update>>>", userid, ":".join(update_field), ":".join(update_val), len(update_field))
  532. query = "update users set " + ",".join(update_field) + " where userid = %s"
  533. print("WTFFF???", query)
  534. cursor.execute(query, update_val)
  535. res["userid"] = userid
  536. res["result"] = "success"
  537. ## USER DELETE
  538. ##
  539. elif (ctx["action"] == "delete"):
  540. query = "delete from users where userid = %s"
  541. cursor.execute(query, [userid])
  542. ## USER SEARCH
  543. ##
  544. elif (ctx["action"] == "search"):
  545. res["userids"] = []
  546. res["userid"] = userid
  547. res["result"] = "success"
  548. search_field = []
  549. search_val = []
  550. for f in user_fields:
  551. if f in ctx:
  552. search_field.append(f + " like %s")
  553. search_val.append('%' + ctx[f] + '%')
  554. query_limit = " "
  555. if "limit" in ctx:
  556. query_limit = " limit %s "
  557. search_val.append(ctx["limit"])
  558. query = "select userid from users where " + " and ".join(search_field) + query_limit
  559. cursor.execute(query, search_val)
  560. rows = cursor.fetchall()
  561. for row in rows:
  562. res["userids"].append(row[0])
  563. db.commit()
  564. return res
  565. ## _ _
  566. ## _ __ ___ ___ _ _ ___| | ___ ___ __ _ _ __ __| |
  567. ## | '__/ _ \/ __| | | |/ __| |/ _ \ / __/ _` | '__/ _` |
  568. ## | | | __/ (__| |_| | (__| | __/ | (_| (_| | | | (_| |
  569. ## |_| \___|\___|\__, |\___|_|\___| \___\__,_|_| \__,_|
  570. ## |___/
  571. def RecycleCard(db, ctx):
  572. res = {"result":"fail"}
  573. cursor = db.cursor()
  574. fields = ["logical_card_id", "rfid_token", "mag_token", "group",
  575. "userid",
  576. "rule", "pass_class", "nrides_remain", "nrides_orig", "nday_orig" ]
  577. val = {}
  578. for f in fields:
  579. if f in ctx:
  580. if ctx[f] and len(ctx[f]) > 0:
  581. val[f] = ctx[f]
  582. if ((not ("logical_card_id" in val)) and
  583. (not ("rfid_token" in val)) and
  584. (not ("mag_token" in val))):
  585. return res
  586. logical_card_id = -1
  587. if not ("logical_card_id" in val):
  588. if "mag_token" in val:
  589. query = "select logical_card_id from user_card where mag_token = %s and active = 1"
  590. cursor.execute(query, [val["mag_token"]])
  591. cid = cursor.fetchone()
  592. if cid is not None:
  593. val["logical_card_id"] = cid[0]
  594. else:
  595. return res
  596. elif "rfid_token" in val:
  597. query = "select logical_card_id from user_card where rfid_token = %s and active = 1"
  598. cursor.execute(query, [val["rfid_token"]])
  599. cid = cursor.fetchone()
  600. if cid is not None:
  601. val["logical_card_id"] = cid[0]
  602. else:
  603. return res
  604. group_info = Group(db, {"action":"default"})
  605. if "group" in val:
  606. group_info = Group(db, {"action":"getone", "group":val["group"]})
  607. if group_info["result"] != "success":
  608. res["api_comment"] = "invalid group"
  609. return res
  610. query = "update user_card set active = 0 where logical_card_id = %s"
  611. cursor.execute(query, [val["logical_card_id"]])
  612. card_info = {"action":"add", "group_id":group_info["group_id"], "active":1}
  613. if "mag_token" in val: card_info["mag_token"] = val["mag_token"]
  614. if "rfid_token" in val: card_info["rfid_token"] = val["rfid_token"]
  615. card_res = Card(db, card_info)
  616. if card_res["result"] != "success":
  617. res["result"] = "fail"
  618. res["api_comment"] = "failed to find card"
  619. return res
  620. res["logical_card_id"] = card_res["logical_card_id"]
  621. if "pass_class" in val:
  622. pass_opt = {"action":"add", "logical_card_id": res["logical_card_id"] }
  623. if val["pass_class"] == "OTHER":
  624. pass_opt["rule"] = val["rule"]
  625. Pass(db, pass_opt)
  626. elif val["pass_class"] == "NRIDE":
  627. pass_opt["rule"] = val["rule"]
  628. pass_opt["nrides_orig"] = val["nrides_orig"]
  629. pass_opt["nrides_remain"] = val["nrides_remain"]
  630. Pass(db, pass_opt)
  631. elif val["pass_class"] == "NDAY":
  632. pass_opt["rule"] = val["rule"]
  633. pass_opt["nday_orig"] = val["nday_orig"]
  634. Pass(db, pass_opt)
  635. return res
  636. ## _ _ _ _ _ _
  637. ## __ _ __| | __| | ___ __ _ _ __ __| | | |__ | | ___ ___| | __
  638. ## / _` |/ _` |/ _` | / __/ _` | '__/ _` | | '_ \| |/ _ \ / __| |/ /
  639. ## | (_| | (_| | (_| | | (_| (_| | | | (_| | | |_) | | (_) | (__| <
  640. ## \__,_|\__,_|\__,_| \___\__,_|_| \__,_| |_.__/|_|\___/ \___|_|\_\
  641. ##
  642. def AddCardBlock(db, ctx):
  643. res = {"result":"fail"}
  644. cursor = db.cursor()
  645. fields = ["mag_token", "rfid_token", "group_id",
  646. "rule", "nday_orig", "nrides_remain", "nrides_orig",
  647. "count",
  648. "pass_rule", "pass_nrides_remain", "pass_nrides_orig",
  649. "pass_nday_orig", "pass_class"]
  650. val = {}
  651. for f in fields:
  652. if f in ctx:
  653. if ctx[f] and len(ctx[f]) > 0:
  654. val[f] = ctx[f]
  655. if not ("count" in val):
  656. res["result"] = "fail"
  657. res["api_comment"] = "count must be positive"
  658. return res
  659. if ((not ("mag_token" in val)) and
  660. (not ("rfid_token" in val))):
  661. res["result"] = "fail"
  662. res["api_comment"] = "mag_token and/or rfid_token must be specified"
  663. return res
  664. use_mag = False
  665. use_rfid = False
  666. if "mag_token" in val:
  667. use_mag = True
  668. pfx_mag_cred = val["mag_token"].split(":")[0]
  669. base_mag_cred = int(val["mag_token"].split(":")[-1])
  670. if "rfid_token" in val:
  671. use_rfid = True
  672. pfx_rfid_cred = ":".join(val["rfid_token"].split(":")[0:2])
  673. base_rfid_cred = int(val["rfid_token"].split(":")[-1])
  674. logical_card_ids = []
  675. for idx in range(int(val["count"])):
  676. card_info = {"action":"add", "group_id":val["group_id"], "active":1}
  677. if "mag_token" in val: card_info["mag_token"] = val["mag_token"]
  678. if "rfid_token" in val: card_info["rfid_token"] = val["rfid_token"]
  679. if use_mag:
  680. card_info["mag_token"] = pfx_mag_cred + ":" + str(base_mag_cred + idx)
  681. if use_rfid:
  682. card_info["rfid_token"] = pfx_rfid_cred + ":" + str(base_rfid_cred + idx)
  683. card_res = Card(db, card_info)
  684. if card_res["result"] != "success":
  685. res["result"] = "fail"
  686. res["api_comment"] = "failed to add card"
  687. return res
  688. logical_card_id = card_res["logical_card_id"]
  689. if "pass_rule" in val:
  690. pass_info = {"action":"add", "logical_card_id":logical_card_id, "active":1,
  691. "rule" : val["pass_rule"] }
  692. if val["pass_class"] == "OTHER":
  693. pass
  694. elif val["pass_class"] == "NRIDE":
  695. pass_info["nrides_remain"] = val["pass_nrides_remain"]
  696. pass_info["nrides_orig"] = val["pass_nrides_orig"]
  697. elif val["pass_class"] == "NDAY":
  698. pass_info["nday_orig"] = val["pass_nday_orig"]
  699. pass_res = Pass(db, pass_info)
  700. logical_card_ids.append(logical_card_id)
  701. res["result"] = "success"
  702. res["logical_card_ids"] = logical_card_ids
  703. return res
  704. ## _
  705. ## _ __ ___ __ _(_)_ __
  706. ## | '_ ` _ \ / _` | | '_ \
  707. ## | | | | | | (_| | | | | |
  708. ## |_| |_| |_|\__,_|_|_| |_|
  709. ##
  710. def main(db):
  711. print("main")
  712. print("---------")
  713. print("---------")
  714. print("---------")
  715. res = User(db, {"action":"add", "username":"abe" })
  716. print("user.add:", res)
  717. res = User(db, {"action":"update", "username":"abeabe", "userid":res["userid"]})
  718. print("user.update:", res)
  719. res = User(db, {"action":"get", "userid":res["userid"]})
  720. print("user.get:", res)
  721. res = User(db, {"action":"delete", "userid": res["userid"]})
  722. print("user.delete:", res)
  723. print("---------")
  724. print("---------")
  725. print("---------")
  726. res = Card(db, {"action":"get", "logical_card_id":1})
  727. print("card.get:", res)
  728. res = Card(db, {"action":"add", "mag_token":"2:1234", "rfid_token":"26:20:415", "comment":"testing api", "userid":1})
  729. print("card.add:", res)
  730. res = Card(db, {"action":"update", "mag_token":"2:9234", "logical_card_id":res["logical_card_id"]})
  731. print("card.update:", res)
  732. res = Card(db, {"action":"delete", "logical_card_id":res["logical_card_id"]})
  733. print("card.delete:", res)
  734. print("---------")
  735. print("---------")
  736. print("---------")
  737. res = Pass(db, {"action":"get", "user_pass_id":11})
  738. print("pass.get:", res)
  739. res = Pass(db, {"action":"add", "logical_card_id":1, "queue_order":9, "rule":"TEST-ORG-NDAY", "nday_orig":3})
  740. print("pass.add:", res)
  741. res = Pass(db, {"action":"update", "user_pass_id":res["user_pass_id"], "queue_order":10, "rule":"TEST-ORG-NDAY", "nday_orig":5})
  742. print("pass.update:", res)
  743. res = Pass(db, {"action":"delete", "user_pass_id":res["user_pass_id"]})
  744. print("pass.delete:", res)
  745. print("---------")
  746. print("---------")
  747. print("---------")
  748. res = UserInfo(db, {"userid":348})
  749. print("userinfo:", json.dumps(res, indent=2))
  750. print("---------")
  751. print("---------")
  752. print("---------")
  753. res = Request({"function":"CardInfo", "action":"search", "logical_card_id":1})
  754. print("request.card.search:", res)
  755. if __name__ == "__main__":
  756. conn = mysql.connector.connect(user=_USER, password=_PASSWORD, host=_HOST, database=_DATABASE, port=_PORT)
  757. main(conn)
  758. conn.close()