diff --git a/README.org b/README.org index 8225f4f..c0546bc 100644 --- a/README.org +++ b/README.org @@ -1,3 +1,3 @@ * odapi -Collection of APIs needed for Odyfo's mobile apps +Odyfo RESTful API to serve the mobile apps and web services. diff --git a/src/Pipfile b/src/Pipfile index c377e73..607073a 100644 --- a/src/Pipfile +++ b/src/Pipfile @@ -7,6 +7,10 @@ verify_ssl = true [packages] twilio = "*" +flask = "*" +pymysql = "*" +flask-praetorian = "*" +flask-sqlalchemy = "*" [requires] python_version = "3.8" diff --git a/src/Pipfile.lock b/src/Pipfile.lock index 6f82f4a..c0a6b29 100644 --- a/src/Pipfile.lock +++ b/src/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "6e5fe7005bbfd900bf7dd3c4a0858830cdf9cfe46eae017d3d27378e0588dd74" + "sha256": "5bee56bdc672b4d2c8c3450c852221d2dbe8b5d15840a0fafa5643c87b03ce3a" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,12 @@ ] }, "default": { + "blinker": { + "hashes": [ + "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6" + ], + "version": "==1.4" + }, "certifi": { "hashes": [ "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", @@ -30,6 +36,50 @@ ], "version": "==3.0.4" }, + "click": { + "hashes": [ + "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", + "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" + ], + "version": "==7.1.1" + }, + "flask": { + "hashes": [ + "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", + "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6" + ], + "index": "pypi", + "version": "==1.1.1" + }, + "flask-buzz": { + "hashes": [ + "sha256:b3347ae16b0716c4beab40fa4722771080c31e3c25925afc1c974d0df8382e48", + "sha256:eb2d4dbb42bfa9a46f174a026caa0b49b9cc582fb79377b52425551e586d4e1c" + ], + "version": "==0.1.14" + }, + "flask-mail": { + "hashes": [ + "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41" + ], + "version": "==0.9.1" + }, + "flask-praetorian": { + "hashes": [ + "sha256:107086455f57935432700dab2611aecdaf3825421196cf6c8e812700e43b37a3", + "sha256:292ff803eca223fa0e72571d95c3c93b61798b395c9c9755af7943364a04fc31" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "flask-sqlalchemy": { + "hashes": [ + "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327", + "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d" + ], + "index": "pypi", + "version": "==2.4.1" + }, "idna": { "hashes": [ "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", @@ -37,6 +87,96 @@ ], "version": "==2.9" }, + "itsdangerous": { + "hashes": [ + "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", + "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" + ], + "version": "==1.1.0" + }, + "jinja2": { + "hashes": [ + "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", + "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" + ], + "version": "==2.11.1" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "version": "==1.1.1" + }, + "passlib": { + "hashes": [ + "sha256:68c35c98a7968850e17f1b6892720764cc7eed0ef2b7cb3116a89a28e43fe177", + "sha256:8d666cef936198bc2ab47ee9b0410c94adf2ba798e5a84bf220be079ae7ab6a8" + ], + "version": "==1.7.2" + }, + "pendulum": { + "hashes": [ + "sha256:093cab342e10516660e64b935a6da1a043e0286de36cc229fb48471415981ffe", + "sha256:0cbbd4f30c69a283690d9ed8e58e44a990e067e59ee05b5ef55d022b38659aeb", + "sha256:2788945a0111d5325fd27ae3e3b18b741e440d20bdb7d4ea22fce7c9a4fbbf40", + "sha256:4420e058110740a8193fb0709350dfc6ac790a99c345fc4e92e24df0f834ddcb", + "sha256:575934b65b298eeb99c5a5b1673c945fc5c99e2b56caff772a91bc4b1eba7b82", + "sha256:6cf0f876cd088ee1578266f4231121376747aa90c3ed3b8e212a8344a9920061", + "sha256:70007aebc4494163f8705909a1996ce21ab853801b57fba4c2dd53c3df5c38f0", + "sha256:701127e1f0ff7c253cc0c07f29becc5f9210547914e0bbe59ffd9fa064d7c3c8", + "sha256:75a62e3f98499283fafe8ef4b44f81052e84825b00a0b64609dd8a06985382b9", + "sha256:816e01dcb0ba4ffcf2ceaafe4d644174fea680361e909f6f8ba0a4fdb2ccae24", + "sha256:9eda38ff65b1f297d860d3f562480e048673fb4b81fdd5c8c55decb519b97ed2", + "sha256:a79a72a7fd1092a7c69ddd8580a0be5365ded40c9f9c865623c7665742e3b888", + "sha256:aa13ddea12fd871d3191f633f08090b91ea2e80fb0ed50a7a149add7f680b12d", + "sha256:aa560bd39d94f3889646422f1e65b8dfd025bf6288d43e5c2e31d4f972aaf2e4", + "sha256:ac3c6a992beeb4c9bd90c317a1bb2a6cba159b49a49b6dd3c86b5bacb86f3d50", + "sha256:d42d1e870541eeaf3fe0500aac0c76a85bd4bd53ebed74f9a7daf8f01ac77374", + "sha256:eb7e349bb2d1b2b418d094e2179d6768561e8242fd8cb640b5aaba735f3e91d1", + "sha256:edd00e6b43698762e10bfda508cc9c06bad88c0703a9b37e412aec1189e06e23", + "sha256:ff7f3420de0c0cf21c1fc813d581fcfa4a1fb6d87f09485880b3e1204eb9cdd7" + ], + "version": "==2.1.0" + }, + "py-buzz": { + "hashes": [ + "sha256:4b7a89bebad927c69e069ca43399a1b965c15f3b08998cf0d68101cc059efad8", + "sha256:d5147db6aab9ff52060f2810648003a6b4bdc91b8b16b50c23668ece632e15c2" + ], + "version": "==0.3.7" + }, "pyjwt": { "hashes": [ "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e", @@ -44,6 +184,21 @@ ], "version": "==1.7.1" }, + "pymysql": { + "hashes": [ + "sha256:3943fbbbc1e902f41daf7f9165519f140c4451c179380677e6a848587042561a", + "sha256:d8c059dcd81dedb85a9f034d5e22dcb4442c0b201908bede99e306d65ea7c8e7" + ], + "index": "pypi", + "version": "==0.9.3" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "version": "==2.8.1" + }, "pytz": { "hashes": [ "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", @@ -51,6 +206,13 @@ ], "version": "==2019.3" }, + "pytzdata": { + "hashes": [ + "sha256:84c52b9a47d097fcd483f047a544979de6c3a86e94c845e3569e9f8acd0fa071", + "sha256:fac06f7cdfa903188dc4848c655e4adaee67ee0f2fe08e7daf815cf2a761ee5e" + ], + "version": "==2019.3" + }, "requests": { "hashes": [ "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", @@ -65,12 +227,18 @@ ], "version": "==1.14.0" }, + "sqlalchemy": { + "hashes": [ + "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445" + ], + "version": "==1.3.15" + }, "twilio": { "hashes": [ - "sha256:c7d99b87a1d3ed5d49638e45509edad7fe10d030d4b5239c5af805b0a2043ad9" + "sha256:284040aa4cd504d67e95cde17db38d4d11454ac8bd43cab94f66694241b962af" ], "index": "pypi", - "version": "==6.36.0" + "version": "==6.37.0" }, "urllib3": { "hashes": [ @@ -78,6 +246,13 @@ "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" ], "version": "==1.25.8" + }, + "werkzeug": { + "hashes": [ + "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096", + "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16" + ], + "version": "==1.0.0" } }, "develop": {} diff --git a/src/app/__init__.py b/src/app/__init__.py new file mode 100644 index 0000000..0ff7bf4 --- /dev/null +++ b/src/app/__init__.py @@ -0,0 +1,9 @@ +from flask import Flask +from config import Config +from flask_sqlalchemy import SQLAlchemy + +app = Flask(__name__) +app.config.from_object(Config) +db = SQLAlchemy(app) + +from app import routes diff --git a/src/app/routes.py b/src/app/routes.py new file mode 100644 index 0000000..41ae7f1 --- /dev/null +++ b/src/app/routes.py @@ -0,0 +1,12 @@ +from flask import request, jsonify +from database import register_user +from external.twilio import send_otp +from app import app + + +@app.route("/users", methods=["POST"]) +def create_user(self): + data = request.get_json() + register_user(data) + send_otp(data["mobile"]) + return jsonify("User created, pending OTP verification") diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..e8aa69d --- /dev/null +++ b/src/config.py @@ -0,0 +1,7 @@ +from constants import CONNECTION_URI + + +class Config(object): + SQLALCHEMY_DATABASE_URI = CONNECTION_URI + SQLALCHEMY_TRACK_MODIFICATIONS = False + SECRET_KEY = "trolaso" diff --git a/src/database/__init__.py b/src/database/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/twilio.py b/src/external/twilio.py similarity index 57% rename from src/twilio.py rename to src/external/twilio.py index a3bb12c..9ca5ac5 100644 --- a/src/twilio.py +++ b/src/external/twilio.py @@ -1,6 +1,6 @@ from twilio.rest import Client from secrets import randbits -from constants import account_id, token +from constants import account_id, token, sms_sender def connect_api(): @@ -12,21 +12,12 @@ def connect_api(): def generate_code(): bits = 16 - code = randbits(range) + code = randbits(bits) return code -def create_otp(receiver): +def send_otp(receiver): client = connect_api() code = generate_code() - sender = "+18555345401" message = "Your OTP code is {0}".format(code) - call = client.calls.create(to=receiver, from_=sender, body=message) - - -def main(): - create_otp("") - - -if __name__ == "__main__": - main() + sms = client.messages.create(to=receiver, from_=sms_sender, body=message)