diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/errors.py b/resources/errors.py
new file mode 100644
index 0000000..334ca5f
--- /dev/null
+++ b/resources/errors.py
@@ -0,0 +1,82 @@
+class InternalServerError(Exception):
+ pass
+
+
+class SchemaValidationError(Exception):
+ pass
+
+
+class MovieAlreadyExistsError(Exception):
+ pass
+
+
+class UpdatingMovieError(Exception):
+ pass
+
+
+class DeletingMovieError(Exception):
+ pass
+
+
+class MovieNotExistsError(Exception):
+ pass
+
+
+class EmailAlreadyExistsError(Exception):
+ pass
+
+
+class UnauthorizedError(Exception):
+ pass
+
+
+class EmailDoesnotExistsError(Exception):
+ pass
+
+
+class BadTokenError(Exception):
+ pass
+
+
+errors = {
+ "InternalServerError": {
+ "message": "Algo va mal en el servidor",
+ "status": 500
+ },
+ "SchemaValidationError": {
+ "message": "Faltan campos por enviar",
+ "status": 400
+ },
+ "MovieAlreadyExistsError": {
+ "message": "El registro ya existe en base de datos",
+ "status": 400
+ },
+ "UpdatingMovieError": {
+ "message": "No tienes los suficientes permisos para actualizar el registro",
+ "status": 403
+ },
+ "DeletingMovieError": {
+ "message": "No tienes los suficientes permisos para eliminar el registro",
+ "status": 403
+ },
+ "MovieNotExistsError": {
+ "message": "El registro no existe en base de datos",
+ "status": 400
+ },
+ "EmailAlreadyExistsError": {
+ "message": "El usuario ya existe en base de datos",
+ "status": 400
+ },
+ "UnauthorizedError": {
+ "message": "Usuario y/o contraseña inválida",
+ "status": 401
+ },
+ "EmailDoesnotExistsError": {
+ "message": "No se pudó encontrar un usuarios con el correo ingresado",
+ "status": 400
+ },
+ "BadTokenError": {
+ "message": "Token Inválido",
+ "status": 403
+ }
+}
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/errors.py b/resources/errors.py
new file mode 100644
index 0000000..334ca5f
--- /dev/null
+++ b/resources/errors.py
@@ -0,0 +1,82 @@
+class InternalServerError(Exception):
+ pass
+
+
+class SchemaValidationError(Exception):
+ pass
+
+
+class MovieAlreadyExistsError(Exception):
+ pass
+
+
+class UpdatingMovieError(Exception):
+ pass
+
+
+class DeletingMovieError(Exception):
+ pass
+
+
+class MovieNotExistsError(Exception):
+ pass
+
+
+class EmailAlreadyExistsError(Exception):
+ pass
+
+
+class UnauthorizedError(Exception):
+ pass
+
+
+class EmailDoesnotExistsError(Exception):
+ pass
+
+
+class BadTokenError(Exception):
+ pass
+
+
+errors = {
+ "InternalServerError": {
+ "message": "Algo va mal en el servidor",
+ "status": 500
+ },
+ "SchemaValidationError": {
+ "message": "Faltan campos por enviar",
+ "status": 400
+ },
+ "MovieAlreadyExistsError": {
+ "message": "El registro ya existe en base de datos",
+ "status": 400
+ },
+ "UpdatingMovieError": {
+ "message": "No tienes los suficientes permisos para actualizar el registro",
+ "status": 403
+ },
+ "DeletingMovieError": {
+ "message": "No tienes los suficientes permisos para eliminar el registro",
+ "status": 403
+ },
+ "MovieNotExistsError": {
+ "message": "El registro no existe en base de datos",
+ "status": 400
+ },
+ "EmailAlreadyExistsError": {
+ "message": "El usuario ya existe en base de datos",
+ "status": 400
+ },
+ "UnauthorizedError": {
+ "message": "Usuario y/o contraseña inválida",
+ "status": 401
+ },
+ "EmailDoesnotExistsError": {
+ "message": "No se pudó encontrar un usuarios con el correo ingresado",
+ "status": 400
+ },
+ "BadTokenError": {
+ "message": "Token Inválido",
+ "status": 403
+ }
+}
diff --git a/resources/movie.py b/resources/movie.py
new file mode 100644
index 0000000..b7c3e51
--- /dev/null
+++ b/resources/movie.py
@@ -0,0 +1,81 @@
+from flask import Response, request
+from flask_restful import Resource
+from database.models import Movie, User
+from flask_jwt_extended import jwt_required, get_jwt_identity
+
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist, ValidationError, InvalidQueryError
+
+from resources.errors import SchemaValidationError, MovieAlreadyExistsError, InternalServerError, UpdatingMovieError, \
+ DeletingMovieError, MovieNotExistsError
+
+
+class MoviesApi(Resource):
+ @staticmethod
+ def get():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
+ @staticmethod
+ @jwt_required
+ def post():
+
+ try:
+ user_id = get_jwt_identity()
+ body = request.get_json()
+ user = User.objects.get(id=user_id)
+ movie = Movie(**body, added_by=user)
+ movie.save()
+ user.update(push__movies=movie)
+ user.save()
+ id = movie.id
+ return {'id': str(id)}, 200
+ except (FieldDoesNotExist, ValidationError):
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise MovieAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class MovieApi(Resource):
+ @staticmethod
+ @jwt_required
+ def put(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
+ except InvalidQueryError:
+ raise SchemaValidationError
+ except DoesNotExist:
+ raise UpdatingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ @jwt_required
+ def delete(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ movie.delete()
+ return '', 200
+ except DoesNotExist:
+ raise DeletingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ def get(self, id):
+
+ try:
+ movies = Movie.objects.get(id=id).to_json()
+ return Response(movies, mimetype="application/json", status=200)
+ except DoesNotExist:
+ raise MovieNotExistsError
+ except Exception:
+ raise InternalServerError
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/errors.py b/resources/errors.py
new file mode 100644
index 0000000..334ca5f
--- /dev/null
+++ b/resources/errors.py
@@ -0,0 +1,82 @@
+class InternalServerError(Exception):
+ pass
+
+
+class SchemaValidationError(Exception):
+ pass
+
+
+class MovieAlreadyExistsError(Exception):
+ pass
+
+
+class UpdatingMovieError(Exception):
+ pass
+
+
+class DeletingMovieError(Exception):
+ pass
+
+
+class MovieNotExistsError(Exception):
+ pass
+
+
+class EmailAlreadyExistsError(Exception):
+ pass
+
+
+class UnauthorizedError(Exception):
+ pass
+
+
+class EmailDoesnotExistsError(Exception):
+ pass
+
+
+class BadTokenError(Exception):
+ pass
+
+
+errors = {
+ "InternalServerError": {
+ "message": "Algo va mal en el servidor",
+ "status": 500
+ },
+ "SchemaValidationError": {
+ "message": "Faltan campos por enviar",
+ "status": 400
+ },
+ "MovieAlreadyExistsError": {
+ "message": "El registro ya existe en base de datos",
+ "status": 400
+ },
+ "UpdatingMovieError": {
+ "message": "No tienes los suficientes permisos para actualizar el registro",
+ "status": 403
+ },
+ "DeletingMovieError": {
+ "message": "No tienes los suficientes permisos para eliminar el registro",
+ "status": 403
+ },
+ "MovieNotExistsError": {
+ "message": "El registro no existe en base de datos",
+ "status": 400
+ },
+ "EmailAlreadyExistsError": {
+ "message": "El usuario ya existe en base de datos",
+ "status": 400
+ },
+ "UnauthorizedError": {
+ "message": "Usuario y/o contraseña inválida",
+ "status": 401
+ },
+ "EmailDoesnotExistsError": {
+ "message": "No se pudó encontrar un usuarios con el correo ingresado",
+ "status": 400
+ },
+ "BadTokenError": {
+ "message": "Token Inválido",
+ "status": 403
+ }
+}
diff --git a/resources/movie.py b/resources/movie.py
new file mode 100644
index 0000000..b7c3e51
--- /dev/null
+++ b/resources/movie.py
@@ -0,0 +1,81 @@
+from flask import Response, request
+from flask_restful import Resource
+from database.models import Movie, User
+from flask_jwt_extended import jwt_required, get_jwt_identity
+
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist, ValidationError, InvalidQueryError
+
+from resources.errors import SchemaValidationError, MovieAlreadyExistsError, InternalServerError, UpdatingMovieError, \
+ DeletingMovieError, MovieNotExistsError
+
+
+class MoviesApi(Resource):
+ @staticmethod
+ def get():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
+ @staticmethod
+ @jwt_required
+ def post():
+
+ try:
+ user_id = get_jwt_identity()
+ body = request.get_json()
+ user = User.objects.get(id=user_id)
+ movie = Movie(**body, added_by=user)
+ movie.save()
+ user.update(push__movies=movie)
+ user.save()
+ id = movie.id
+ return {'id': str(id)}, 200
+ except (FieldDoesNotExist, ValidationError):
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise MovieAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class MovieApi(Resource):
+ @staticmethod
+ @jwt_required
+ def put(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
+ except InvalidQueryError:
+ raise SchemaValidationError
+ except DoesNotExist:
+ raise UpdatingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ @jwt_required
+ def delete(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ movie.delete()
+ return '', 200
+ except DoesNotExist:
+ raise DeletingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ def get(self, id):
+
+ try:
+ movies = Movie.objects.get(id=id).to_json()
+ return Response(movies, mimetype="application/json", status=200)
+ except DoesNotExist:
+ raise MovieNotExistsError
+ except Exception:
+ raise InternalServerError
diff --git a/resources/reset_password.py b/resources/reset_password.py
new file mode 100644
index 0000000..4948324
--- /dev/null
+++ b/resources/reset_password.py
@@ -0,0 +1,74 @@
+from flask import request, render_template
+from flask_jwt_extended import create_access_token, decode_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from resources.errors import SchemaValidationError, InternalServerError, EmailDoesnotExistsError, BadTokenError
+from jwt.exceptions import ExpiredSignatureError, DecodeError, InvalidTokenError
+from services.mail_service import send_email
+
+
+class ForgotPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ email = body.get('email')
+ if not email:
+ raise SchemaValidationError
+
+ user = User.objects.get(email=email)
+ if not user:
+ raise EmailDoesnotExistsError
+
+ expires = datetime.timedelta(hours=24)
+ reset_token = create_access_token(str(user.id), expires_delta=expires)
+
+ return send_email('[Movie-bag] Cambia tu Contraseña',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body=render_template('email/reset_password.txt',
+ url=url + reset_token),
+ html_body=render_template('email/reset_password.html',
+ url=url + reset_token))
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except EmailDoesnotExistsError:
+ raise EmailDoesnotExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class ResetPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ reset_token = body.get('reset_token')
+ password = body.get('password')
+
+ if not reset_token or not password:
+ raise SchemaValidationError
+
+ user_id = decode_token(reset_token)['identity']
+
+ user = User.objects.get(id=user_id)
+
+ user.modify(password=password)
+ user.hash_password()
+ user.save()
+
+ return send_email('[Movie-bag] Cambio de Contraseña Exitoso',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body='El cambio de tu contraseña fue exitoso',
+ html_body='
Cambio de contraseña exitoso
')
+
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except ExpiredSignatureError:
+ raise ExpiredSignatureError
+ except (DecodeError, InvalidTokenError):
+ raise BadTokenError
+ except Exception as e:
+ raise InternalServerError
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/errors.py b/resources/errors.py
new file mode 100644
index 0000000..334ca5f
--- /dev/null
+++ b/resources/errors.py
@@ -0,0 +1,82 @@
+class InternalServerError(Exception):
+ pass
+
+
+class SchemaValidationError(Exception):
+ pass
+
+
+class MovieAlreadyExistsError(Exception):
+ pass
+
+
+class UpdatingMovieError(Exception):
+ pass
+
+
+class DeletingMovieError(Exception):
+ pass
+
+
+class MovieNotExistsError(Exception):
+ pass
+
+
+class EmailAlreadyExistsError(Exception):
+ pass
+
+
+class UnauthorizedError(Exception):
+ pass
+
+
+class EmailDoesnotExistsError(Exception):
+ pass
+
+
+class BadTokenError(Exception):
+ pass
+
+
+errors = {
+ "InternalServerError": {
+ "message": "Algo va mal en el servidor",
+ "status": 500
+ },
+ "SchemaValidationError": {
+ "message": "Faltan campos por enviar",
+ "status": 400
+ },
+ "MovieAlreadyExistsError": {
+ "message": "El registro ya existe en base de datos",
+ "status": 400
+ },
+ "UpdatingMovieError": {
+ "message": "No tienes los suficientes permisos para actualizar el registro",
+ "status": 403
+ },
+ "DeletingMovieError": {
+ "message": "No tienes los suficientes permisos para eliminar el registro",
+ "status": 403
+ },
+ "MovieNotExistsError": {
+ "message": "El registro no existe en base de datos",
+ "status": 400
+ },
+ "EmailAlreadyExistsError": {
+ "message": "El usuario ya existe en base de datos",
+ "status": 400
+ },
+ "UnauthorizedError": {
+ "message": "Usuario y/o contraseña inválida",
+ "status": 401
+ },
+ "EmailDoesnotExistsError": {
+ "message": "No se pudó encontrar un usuarios con el correo ingresado",
+ "status": 400
+ },
+ "BadTokenError": {
+ "message": "Token Inválido",
+ "status": 403
+ }
+}
diff --git a/resources/movie.py b/resources/movie.py
new file mode 100644
index 0000000..b7c3e51
--- /dev/null
+++ b/resources/movie.py
@@ -0,0 +1,81 @@
+from flask import Response, request
+from flask_restful import Resource
+from database.models import Movie, User
+from flask_jwt_extended import jwt_required, get_jwt_identity
+
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist, ValidationError, InvalidQueryError
+
+from resources.errors import SchemaValidationError, MovieAlreadyExistsError, InternalServerError, UpdatingMovieError, \
+ DeletingMovieError, MovieNotExistsError
+
+
+class MoviesApi(Resource):
+ @staticmethod
+ def get():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
+ @staticmethod
+ @jwt_required
+ def post():
+
+ try:
+ user_id = get_jwt_identity()
+ body = request.get_json()
+ user = User.objects.get(id=user_id)
+ movie = Movie(**body, added_by=user)
+ movie.save()
+ user.update(push__movies=movie)
+ user.save()
+ id = movie.id
+ return {'id': str(id)}, 200
+ except (FieldDoesNotExist, ValidationError):
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise MovieAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class MovieApi(Resource):
+ @staticmethod
+ @jwt_required
+ def put(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
+ except InvalidQueryError:
+ raise SchemaValidationError
+ except DoesNotExist:
+ raise UpdatingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ @jwt_required
+ def delete(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ movie.delete()
+ return '', 200
+ except DoesNotExist:
+ raise DeletingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ def get(self, id):
+
+ try:
+ movies = Movie.objects.get(id=id).to_json()
+ return Response(movies, mimetype="application/json", status=200)
+ except DoesNotExist:
+ raise MovieNotExistsError
+ except Exception:
+ raise InternalServerError
diff --git a/resources/reset_password.py b/resources/reset_password.py
new file mode 100644
index 0000000..4948324
--- /dev/null
+++ b/resources/reset_password.py
@@ -0,0 +1,74 @@
+from flask import request, render_template
+from flask_jwt_extended import create_access_token, decode_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from resources.errors import SchemaValidationError, InternalServerError, EmailDoesnotExistsError, BadTokenError
+from jwt.exceptions import ExpiredSignatureError, DecodeError, InvalidTokenError
+from services.mail_service import send_email
+
+
+class ForgotPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ email = body.get('email')
+ if not email:
+ raise SchemaValidationError
+
+ user = User.objects.get(email=email)
+ if not user:
+ raise EmailDoesnotExistsError
+
+ expires = datetime.timedelta(hours=24)
+ reset_token = create_access_token(str(user.id), expires_delta=expires)
+
+ return send_email('[Movie-bag] Cambia tu Contraseña',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body=render_template('email/reset_password.txt',
+ url=url + reset_token),
+ html_body=render_template('email/reset_password.html',
+ url=url + reset_token))
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except EmailDoesnotExistsError:
+ raise EmailDoesnotExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class ResetPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ reset_token = body.get('reset_token')
+ password = body.get('password')
+
+ if not reset_token or not password:
+ raise SchemaValidationError
+
+ user_id = decode_token(reset_token)['identity']
+
+ user = User.objects.get(id=user_id)
+
+ user.modify(password=password)
+ user.hash_password()
+ user.save()
+
+ return send_email('[Movie-bag] Cambio de Contraseña Exitoso',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body='El cambio de tu contraseña fue exitoso',
+ html_body='Cambio de contraseña exitoso
')
+
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except ExpiredSignatureError:
+ raise ExpiredSignatureError
+ except (DecodeError, InvalidTokenError):
+ raise BadTokenError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/routes.py b/resources/routes.py
new file mode 100644
index 0000000..c68188b
--- /dev/null
+++ b/resources/routes.py
@@ -0,0 +1,12 @@
+from .movie import MoviesApi, MovieApi
+from .auth import SignupApi, LoginApi
+from .reset_password import ForgotPassword, ResetPassword
+
+
+def initialize_routes(api):
+ api.add_resource(MoviesApi, '/api/movies')
+ api.add_resource(MovieApi, '/api/movies/')
+ api.add_resource(SignupApi, '/api/auth/signup')
+ api.add_resource(LoginApi, '/api/auth/login')
+ api.add_resource(ForgotPassword, '/api/auth/forgot')
+ api.add_resource(ResetPassword, '/api/auth/reset')
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/errors.py b/resources/errors.py
new file mode 100644
index 0000000..334ca5f
--- /dev/null
+++ b/resources/errors.py
@@ -0,0 +1,82 @@
+class InternalServerError(Exception):
+ pass
+
+
+class SchemaValidationError(Exception):
+ pass
+
+
+class MovieAlreadyExistsError(Exception):
+ pass
+
+
+class UpdatingMovieError(Exception):
+ pass
+
+
+class DeletingMovieError(Exception):
+ pass
+
+
+class MovieNotExistsError(Exception):
+ pass
+
+
+class EmailAlreadyExistsError(Exception):
+ pass
+
+
+class UnauthorizedError(Exception):
+ pass
+
+
+class EmailDoesnotExistsError(Exception):
+ pass
+
+
+class BadTokenError(Exception):
+ pass
+
+
+errors = {
+ "InternalServerError": {
+ "message": "Algo va mal en el servidor",
+ "status": 500
+ },
+ "SchemaValidationError": {
+ "message": "Faltan campos por enviar",
+ "status": 400
+ },
+ "MovieAlreadyExistsError": {
+ "message": "El registro ya existe en base de datos",
+ "status": 400
+ },
+ "UpdatingMovieError": {
+ "message": "No tienes los suficientes permisos para actualizar el registro",
+ "status": 403
+ },
+ "DeletingMovieError": {
+ "message": "No tienes los suficientes permisos para eliminar el registro",
+ "status": 403
+ },
+ "MovieNotExistsError": {
+ "message": "El registro no existe en base de datos",
+ "status": 400
+ },
+ "EmailAlreadyExistsError": {
+ "message": "El usuario ya existe en base de datos",
+ "status": 400
+ },
+ "UnauthorizedError": {
+ "message": "Usuario y/o contraseña inválida",
+ "status": 401
+ },
+ "EmailDoesnotExistsError": {
+ "message": "No se pudó encontrar un usuarios con el correo ingresado",
+ "status": 400
+ },
+ "BadTokenError": {
+ "message": "Token Inválido",
+ "status": 403
+ }
+}
diff --git a/resources/movie.py b/resources/movie.py
new file mode 100644
index 0000000..b7c3e51
--- /dev/null
+++ b/resources/movie.py
@@ -0,0 +1,81 @@
+from flask import Response, request
+from flask_restful import Resource
+from database.models import Movie, User
+from flask_jwt_extended import jwt_required, get_jwt_identity
+
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist, ValidationError, InvalidQueryError
+
+from resources.errors import SchemaValidationError, MovieAlreadyExistsError, InternalServerError, UpdatingMovieError, \
+ DeletingMovieError, MovieNotExistsError
+
+
+class MoviesApi(Resource):
+ @staticmethod
+ def get():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
+ @staticmethod
+ @jwt_required
+ def post():
+
+ try:
+ user_id = get_jwt_identity()
+ body = request.get_json()
+ user = User.objects.get(id=user_id)
+ movie = Movie(**body, added_by=user)
+ movie.save()
+ user.update(push__movies=movie)
+ user.save()
+ id = movie.id
+ return {'id': str(id)}, 200
+ except (FieldDoesNotExist, ValidationError):
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise MovieAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class MovieApi(Resource):
+ @staticmethod
+ @jwt_required
+ def put(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
+ except InvalidQueryError:
+ raise SchemaValidationError
+ except DoesNotExist:
+ raise UpdatingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ @jwt_required
+ def delete(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ movie.delete()
+ return '', 200
+ except DoesNotExist:
+ raise DeletingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ def get(self, id):
+
+ try:
+ movies = Movie.objects.get(id=id).to_json()
+ return Response(movies, mimetype="application/json", status=200)
+ except DoesNotExist:
+ raise MovieNotExistsError
+ except Exception:
+ raise InternalServerError
diff --git a/resources/reset_password.py b/resources/reset_password.py
new file mode 100644
index 0000000..4948324
--- /dev/null
+++ b/resources/reset_password.py
@@ -0,0 +1,74 @@
+from flask import request, render_template
+from flask_jwt_extended import create_access_token, decode_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from resources.errors import SchemaValidationError, InternalServerError, EmailDoesnotExistsError, BadTokenError
+from jwt.exceptions import ExpiredSignatureError, DecodeError, InvalidTokenError
+from services.mail_service import send_email
+
+
+class ForgotPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ email = body.get('email')
+ if not email:
+ raise SchemaValidationError
+
+ user = User.objects.get(email=email)
+ if not user:
+ raise EmailDoesnotExistsError
+
+ expires = datetime.timedelta(hours=24)
+ reset_token = create_access_token(str(user.id), expires_delta=expires)
+
+ return send_email('[Movie-bag] Cambia tu Contraseña',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body=render_template('email/reset_password.txt',
+ url=url + reset_token),
+ html_body=render_template('email/reset_password.html',
+ url=url + reset_token))
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except EmailDoesnotExistsError:
+ raise EmailDoesnotExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class ResetPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ reset_token = body.get('reset_token')
+ password = body.get('password')
+
+ if not reset_token or not password:
+ raise SchemaValidationError
+
+ user_id = decode_token(reset_token)['identity']
+
+ user = User.objects.get(id=user_id)
+
+ user.modify(password=password)
+ user.hash_password()
+ user.save()
+
+ return send_email('[Movie-bag] Cambio de Contraseña Exitoso',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body='El cambio de tu contraseña fue exitoso',
+ html_body='Cambio de contraseña exitoso
')
+
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except ExpiredSignatureError:
+ raise ExpiredSignatureError
+ except (DecodeError, InvalidTokenError):
+ raise BadTokenError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/routes.py b/resources/routes.py
new file mode 100644
index 0000000..c68188b
--- /dev/null
+++ b/resources/routes.py
@@ -0,0 +1,12 @@
+from .movie import MoviesApi, MovieApi
+from .auth import SignupApi, LoginApi
+from .reset_password import ForgotPassword, ResetPassword
+
+
+def initialize_routes(api):
+ api.add_resource(MoviesApi, '/api/movies')
+ api.add_resource(MovieApi, '/api/movies/')
+ api.add_resource(SignupApi, '/api/auth/signup')
+ api.add_resource(LoginApi, '/api/auth/login')
+ api.add_resource(ForgotPassword, '/api/auth/forgot')
+ api.add_resource(ResetPassword, '/api/auth/reset')
diff --git a/run.py b/run.py
new file mode 100644
index 0000000..dddb9f2
--- /dev/null
+++ b/run.py
@@ -0,0 +1,6 @@
+from livereload import Server
+from app import app
+
+if __name__=='__main__':
+ server = Server(app.wsgi_app)
+ server.serve()
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/errors.py b/resources/errors.py
new file mode 100644
index 0000000..334ca5f
--- /dev/null
+++ b/resources/errors.py
@@ -0,0 +1,82 @@
+class InternalServerError(Exception):
+ pass
+
+
+class SchemaValidationError(Exception):
+ pass
+
+
+class MovieAlreadyExistsError(Exception):
+ pass
+
+
+class UpdatingMovieError(Exception):
+ pass
+
+
+class DeletingMovieError(Exception):
+ pass
+
+
+class MovieNotExistsError(Exception):
+ pass
+
+
+class EmailAlreadyExistsError(Exception):
+ pass
+
+
+class UnauthorizedError(Exception):
+ pass
+
+
+class EmailDoesnotExistsError(Exception):
+ pass
+
+
+class BadTokenError(Exception):
+ pass
+
+
+errors = {
+ "InternalServerError": {
+ "message": "Algo va mal en el servidor",
+ "status": 500
+ },
+ "SchemaValidationError": {
+ "message": "Faltan campos por enviar",
+ "status": 400
+ },
+ "MovieAlreadyExistsError": {
+ "message": "El registro ya existe en base de datos",
+ "status": 400
+ },
+ "UpdatingMovieError": {
+ "message": "No tienes los suficientes permisos para actualizar el registro",
+ "status": 403
+ },
+ "DeletingMovieError": {
+ "message": "No tienes los suficientes permisos para eliminar el registro",
+ "status": 403
+ },
+ "MovieNotExistsError": {
+ "message": "El registro no existe en base de datos",
+ "status": 400
+ },
+ "EmailAlreadyExistsError": {
+ "message": "El usuario ya existe en base de datos",
+ "status": 400
+ },
+ "UnauthorizedError": {
+ "message": "Usuario y/o contraseña inválida",
+ "status": 401
+ },
+ "EmailDoesnotExistsError": {
+ "message": "No se pudó encontrar un usuarios con el correo ingresado",
+ "status": 400
+ },
+ "BadTokenError": {
+ "message": "Token Inválido",
+ "status": 403
+ }
+}
diff --git a/resources/movie.py b/resources/movie.py
new file mode 100644
index 0000000..b7c3e51
--- /dev/null
+++ b/resources/movie.py
@@ -0,0 +1,81 @@
+from flask import Response, request
+from flask_restful import Resource
+from database.models import Movie, User
+from flask_jwt_extended import jwt_required, get_jwt_identity
+
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist, ValidationError, InvalidQueryError
+
+from resources.errors import SchemaValidationError, MovieAlreadyExistsError, InternalServerError, UpdatingMovieError, \
+ DeletingMovieError, MovieNotExistsError
+
+
+class MoviesApi(Resource):
+ @staticmethod
+ def get():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
+ @staticmethod
+ @jwt_required
+ def post():
+
+ try:
+ user_id = get_jwt_identity()
+ body = request.get_json()
+ user = User.objects.get(id=user_id)
+ movie = Movie(**body, added_by=user)
+ movie.save()
+ user.update(push__movies=movie)
+ user.save()
+ id = movie.id
+ return {'id': str(id)}, 200
+ except (FieldDoesNotExist, ValidationError):
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise MovieAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class MovieApi(Resource):
+ @staticmethod
+ @jwt_required
+ def put(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
+ except InvalidQueryError:
+ raise SchemaValidationError
+ except DoesNotExist:
+ raise UpdatingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ @jwt_required
+ def delete(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ movie.delete()
+ return '', 200
+ except DoesNotExist:
+ raise DeletingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ def get(self, id):
+
+ try:
+ movies = Movie.objects.get(id=id).to_json()
+ return Response(movies, mimetype="application/json", status=200)
+ except DoesNotExist:
+ raise MovieNotExistsError
+ except Exception:
+ raise InternalServerError
diff --git a/resources/reset_password.py b/resources/reset_password.py
new file mode 100644
index 0000000..4948324
--- /dev/null
+++ b/resources/reset_password.py
@@ -0,0 +1,74 @@
+from flask import request, render_template
+from flask_jwt_extended import create_access_token, decode_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from resources.errors import SchemaValidationError, InternalServerError, EmailDoesnotExistsError, BadTokenError
+from jwt.exceptions import ExpiredSignatureError, DecodeError, InvalidTokenError
+from services.mail_service import send_email
+
+
+class ForgotPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ email = body.get('email')
+ if not email:
+ raise SchemaValidationError
+
+ user = User.objects.get(email=email)
+ if not user:
+ raise EmailDoesnotExistsError
+
+ expires = datetime.timedelta(hours=24)
+ reset_token = create_access_token(str(user.id), expires_delta=expires)
+
+ return send_email('[Movie-bag] Cambia tu Contraseña',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body=render_template('email/reset_password.txt',
+ url=url + reset_token),
+ html_body=render_template('email/reset_password.html',
+ url=url + reset_token))
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except EmailDoesnotExistsError:
+ raise EmailDoesnotExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class ResetPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ reset_token = body.get('reset_token')
+ password = body.get('password')
+
+ if not reset_token or not password:
+ raise SchemaValidationError
+
+ user_id = decode_token(reset_token)['identity']
+
+ user = User.objects.get(id=user_id)
+
+ user.modify(password=password)
+ user.hash_password()
+ user.save()
+
+ return send_email('[Movie-bag] Cambio de Contraseña Exitoso',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body='El cambio de tu contraseña fue exitoso',
+ html_body='Cambio de contraseña exitoso
')
+
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except ExpiredSignatureError:
+ raise ExpiredSignatureError
+ except (DecodeError, InvalidTokenError):
+ raise BadTokenError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/routes.py b/resources/routes.py
new file mode 100644
index 0000000..c68188b
--- /dev/null
+++ b/resources/routes.py
@@ -0,0 +1,12 @@
+from .movie import MoviesApi, MovieApi
+from .auth import SignupApi, LoginApi
+from .reset_password import ForgotPassword, ResetPassword
+
+
+def initialize_routes(api):
+ api.add_resource(MoviesApi, '/api/movies')
+ api.add_resource(MovieApi, '/api/movies/')
+ api.add_resource(SignupApi, '/api/auth/signup')
+ api.add_resource(LoginApi, '/api/auth/login')
+ api.add_resource(ForgotPassword, '/api/auth/forgot')
+ api.add_resource(ResetPassword, '/api/auth/reset')
diff --git a/run.py b/run.py
new file mode 100644
index 0000000..dddb9f2
--- /dev/null
+++ b/run.py
@@ -0,0 +1,6 @@
+from livereload import Server
+from app import app
+
+if __name__=='__main__':
+ server = Server(app.wsgi_app)
+ server.serve()
\ No newline at end of file
diff --git a/services/mail_service.py b/services/mail_service.py
new file mode 100644
index 0000000..af53dad
--- /dev/null
+++ b/services/mail_service.py
@@ -0,0 +1,21 @@
+from threading import Thread
+from flask_mail import Message
+
+from app import app
+from app import mail
+from resources.errors import InternalServerError
+
+
+def send_async_email(app, msg):
+ with app.app_context():
+ try:
+ mail.send(msg)
+ except ConnectionRefusedError:
+ raise InternalServerError("[MAIL SERVER] not working")
+
+
+def send_email(subject, sender, recipients, text_body, html_body):
+ msg = Message(subject, sender=sender, recipients=recipients)
+ msg.body = text_body
+ msg.html = html_body
+ Thread(target=send_async_email, args=(app, msg)).start()
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/errors.py b/resources/errors.py
new file mode 100644
index 0000000..334ca5f
--- /dev/null
+++ b/resources/errors.py
@@ -0,0 +1,82 @@
+class InternalServerError(Exception):
+ pass
+
+
+class SchemaValidationError(Exception):
+ pass
+
+
+class MovieAlreadyExistsError(Exception):
+ pass
+
+
+class UpdatingMovieError(Exception):
+ pass
+
+
+class DeletingMovieError(Exception):
+ pass
+
+
+class MovieNotExistsError(Exception):
+ pass
+
+
+class EmailAlreadyExistsError(Exception):
+ pass
+
+
+class UnauthorizedError(Exception):
+ pass
+
+
+class EmailDoesnotExistsError(Exception):
+ pass
+
+
+class BadTokenError(Exception):
+ pass
+
+
+errors = {
+ "InternalServerError": {
+ "message": "Algo va mal en el servidor",
+ "status": 500
+ },
+ "SchemaValidationError": {
+ "message": "Faltan campos por enviar",
+ "status": 400
+ },
+ "MovieAlreadyExistsError": {
+ "message": "El registro ya existe en base de datos",
+ "status": 400
+ },
+ "UpdatingMovieError": {
+ "message": "No tienes los suficientes permisos para actualizar el registro",
+ "status": 403
+ },
+ "DeletingMovieError": {
+ "message": "No tienes los suficientes permisos para eliminar el registro",
+ "status": 403
+ },
+ "MovieNotExistsError": {
+ "message": "El registro no existe en base de datos",
+ "status": 400
+ },
+ "EmailAlreadyExistsError": {
+ "message": "El usuario ya existe en base de datos",
+ "status": 400
+ },
+ "UnauthorizedError": {
+ "message": "Usuario y/o contraseña inválida",
+ "status": 401
+ },
+ "EmailDoesnotExistsError": {
+ "message": "No se pudó encontrar un usuarios con el correo ingresado",
+ "status": 400
+ },
+ "BadTokenError": {
+ "message": "Token Inválido",
+ "status": 403
+ }
+}
diff --git a/resources/movie.py b/resources/movie.py
new file mode 100644
index 0000000..b7c3e51
--- /dev/null
+++ b/resources/movie.py
@@ -0,0 +1,81 @@
+from flask import Response, request
+from flask_restful import Resource
+from database.models import Movie, User
+from flask_jwt_extended import jwt_required, get_jwt_identity
+
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist, ValidationError, InvalidQueryError
+
+from resources.errors import SchemaValidationError, MovieAlreadyExistsError, InternalServerError, UpdatingMovieError, \
+ DeletingMovieError, MovieNotExistsError
+
+
+class MoviesApi(Resource):
+ @staticmethod
+ def get():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
+ @staticmethod
+ @jwt_required
+ def post():
+
+ try:
+ user_id = get_jwt_identity()
+ body = request.get_json()
+ user = User.objects.get(id=user_id)
+ movie = Movie(**body, added_by=user)
+ movie.save()
+ user.update(push__movies=movie)
+ user.save()
+ id = movie.id
+ return {'id': str(id)}, 200
+ except (FieldDoesNotExist, ValidationError):
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise MovieAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class MovieApi(Resource):
+ @staticmethod
+ @jwt_required
+ def put(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
+ except InvalidQueryError:
+ raise SchemaValidationError
+ except DoesNotExist:
+ raise UpdatingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ @jwt_required
+ def delete(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ movie.delete()
+ return '', 200
+ except DoesNotExist:
+ raise DeletingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ def get(self, id):
+
+ try:
+ movies = Movie.objects.get(id=id).to_json()
+ return Response(movies, mimetype="application/json", status=200)
+ except DoesNotExist:
+ raise MovieNotExistsError
+ except Exception:
+ raise InternalServerError
diff --git a/resources/reset_password.py b/resources/reset_password.py
new file mode 100644
index 0000000..4948324
--- /dev/null
+++ b/resources/reset_password.py
@@ -0,0 +1,74 @@
+from flask import request, render_template
+from flask_jwt_extended import create_access_token, decode_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from resources.errors import SchemaValidationError, InternalServerError, EmailDoesnotExistsError, BadTokenError
+from jwt.exceptions import ExpiredSignatureError, DecodeError, InvalidTokenError
+from services.mail_service import send_email
+
+
+class ForgotPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ email = body.get('email')
+ if not email:
+ raise SchemaValidationError
+
+ user = User.objects.get(email=email)
+ if not user:
+ raise EmailDoesnotExistsError
+
+ expires = datetime.timedelta(hours=24)
+ reset_token = create_access_token(str(user.id), expires_delta=expires)
+
+ return send_email('[Movie-bag] Cambia tu Contraseña',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body=render_template('email/reset_password.txt',
+ url=url + reset_token),
+ html_body=render_template('email/reset_password.html',
+ url=url + reset_token))
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except EmailDoesnotExistsError:
+ raise EmailDoesnotExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class ResetPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ reset_token = body.get('reset_token')
+ password = body.get('password')
+
+ if not reset_token or not password:
+ raise SchemaValidationError
+
+ user_id = decode_token(reset_token)['identity']
+
+ user = User.objects.get(id=user_id)
+
+ user.modify(password=password)
+ user.hash_password()
+ user.save()
+
+ return send_email('[Movie-bag] Cambio de Contraseña Exitoso',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body='El cambio de tu contraseña fue exitoso',
+ html_body='Cambio de contraseña exitoso
')
+
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except ExpiredSignatureError:
+ raise ExpiredSignatureError
+ except (DecodeError, InvalidTokenError):
+ raise BadTokenError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/routes.py b/resources/routes.py
new file mode 100644
index 0000000..c68188b
--- /dev/null
+++ b/resources/routes.py
@@ -0,0 +1,12 @@
+from .movie import MoviesApi, MovieApi
+from .auth import SignupApi, LoginApi
+from .reset_password import ForgotPassword, ResetPassword
+
+
+def initialize_routes(api):
+ api.add_resource(MoviesApi, '/api/movies')
+ api.add_resource(MovieApi, '/api/movies/')
+ api.add_resource(SignupApi, '/api/auth/signup')
+ api.add_resource(LoginApi, '/api/auth/login')
+ api.add_resource(ForgotPassword, '/api/auth/forgot')
+ api.add_resource(ResetPassword, '/api/auth/reset')
diff --git a/run.py b/run.py
new file mode 100644
index 0000000..dddb9f2
--- /dev/null
+++ b/run.py
@@ -0,0 +1,6 @@
+from livereload import Server
+from app import app
+
+if __name__=='__main__':
+ server = Server(app.wsgi_app)
+ server.serve()
\ No newline at end of file
diff --git a/services/mail_service.py b/services/mail_service.py
new file mode 100644
index 0000000..af53dad
--- /dev/null
+++ b/services/mail_service.py
@@ -0,0 +1,21 @@
+from threading import Thread
+from flask_mail import Message
+
+from app import app
+from app import mail
+from resources.errors import InternalServerError
+
+
+def send_async_email(app, msg):
+ with app.app_context():
+ try:
+ mail.send(msg)
+ except ConnectionRefusedError:
+ raise InternalServerError("[MAIL SERVER] not working")
+
+
+def send_email(subject, sender, recipients, text_body, html_body):
+ msg = Message(subject, sender=sender, recipients=recipients)
+ msg.body = text_body
+ msg.html = html_body
+ Thread(target=send_async_email, args=(app, msg)).start()
diff --git a/templates/email/reset_password.html b/templates/email/reset_password.html
new file mode 100644
index 0000000..c02b9c0
--- /dev/null
+++ b/templates/email/reset_password.html
@@ -0,0 +1,12 @@
+Estimado, Usuario
+
+ Para cambiar tu contraseña
+
+ Clic aquí
+ .
+
+ Alternativamente, puedes pegar el siguiente enlace en la barra de direcciones de tu navegador:
+ {{url}}
+ Si no has solicitado un restablecimiento de contraseña, simplemente ignora este mensaje.
+ Atentamente
+ Equipo de asistencia de ...
diff --git a/.env b/.env
new file mode 100644
index 0000000..3e96829
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+JWT_SECRET_KEY = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTYyNTcxMjQ1MywiaWF0IjoxNjI1NzEyNDUzfQ.ubSTJLfXMgaEyFRt7JtMCzzXovBFbgV3Yu3VI5UgtQE'
+MAIL_SERVER = "localhost"
+MAIL_PORT = "1025"
+MAIL_USERNAME = "support@movie-bag.com"
+MAIL_PASSWORD = ""
\ No newline at end of file
diff --git a/.idea/apiRestFlask.iml b/.idea/apiRestFlask.iml
new file mode 100644
index 0000000..31e2ab8
--- /dev/null
+++ b/.idea/apiRestFlask.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea16c0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2c2b81
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..0223102
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1625517343973
+
+
+ 1625517343973
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..242440b
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,17 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+flask = "*"
+flask-mongoengine = "*"
+flask-restful = "*"
+flask-bcrypt = "*"
+flask-jwt-extended = "*"
+flask-mail = "*"
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..9175163
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,393 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "8536e16e6c5e514bbecaf1570c2e28536f338f2cb993886e217cfa879c03963c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aniso8601": {
+ "hashes": [
+ "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
+ "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
+ ],
+ "version": "==9.0.1"
+ },
+ "bcrypt": {
+ "hashes": [
+ "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
+ "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
+ "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
+ "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
+ "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
+ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
+ "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.0"
+ },
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
+ "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
+ "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
+ "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
+ "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
+ "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
+ "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
+ "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
+ "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
+ "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
+ "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
+ "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
+ "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
+ "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
+ "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
+ "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
+ "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
+ "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
+ "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
+ "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
+ "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
+ "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5",
+ "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
+ "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
+ "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
+ "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
+ "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
+ "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
+ "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
+ "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369",
+ "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827",
+ "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053",
+ "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa",
+ "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4",
+ "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322",
+ "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132",
+ "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62",
+ "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa",
+ "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0",
+ "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396",
+ "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
+ "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
+ "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
+ "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
+ "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
+ "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
+ "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
+ "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
+ "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
+ ],
+ "version": "==1.14.5"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
+ "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==8.0.1"
+ },
+ "dnspython": {
+ "hashes": [
+ "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
+ "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "email-validator": {
+ "hashes": [
+ "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b",
+ "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"
+ ],
+ "version": "==1.1.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
+ "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "flask-bcrypt": {
+ "hashes": [
+ "sha256:d71c8585b2ee1c62024392ebdbc447438564e2c8c02b4e57b56a4cafd8d13c5f"
+ ],
+ "index": "pypi",
+ "version": "==0.7.1"
+ },
+ "flask-jwt-extended": {
+ "hashes": [
+ "sha256:22b8ffa7587d50aaf65f3009f1d55ef7287da8260eaf4655a5837e33479216c3",
+ "sha256:26969d931bd959dd6b82b2ac07733b499d52c8967229e70bf4ad5859de6cb3b2"
+ ],
+ "index": "pypi",
+ "version": "==4.2.3"
+ },
+ "flask-mail": {
+ "hashes": [
+ "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"
+ ],
+ "index": "pypi",
+ "version": "==0.9.1"
+ },
+ "flask-mongoengine": {
+ "hashes": [
+ "sha256:2db13140ce7f61a935e75268190450d5ecc9b60a7310fd289f9511835aa105d4",
+ "sha256:ce68726d2be8d88006e88f17e4be3b7ad07c79ca8dedb60653d3dab5d9485840"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "flask-restful": {
+ "hashes": [
+ "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2",
+ "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"
+ ],
+ "index": "pypi",
+ "version": "==0.3.9"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf",
+ "sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.15.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
+ "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==3.2"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac",
+ "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==4.6.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
+ "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
+ "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.0.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
+ "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
+ "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
+ "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
+ "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
+ "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
+ "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
+ "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
+ "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
+ "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
+ "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
+ "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
+ "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
+ "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
+ "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
+ "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
+ "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
+ "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
+ "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
+ "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
+ "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
+ "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
+ "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
+ "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
+ "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
+ "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
+ "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
+ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
+ "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
+ "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
+ "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
+ "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
+ "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
+ "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "mongoengine": {
+ "hashes": [
+ "sha256:3d1c8b9f5d43144bd726a3f01e58d2831c6fb112960a4a60b3a26fa85e026ab3",
+ "sha256:de275e70cd58891dc46eef43369c522ce450dccb6d6f1979cbc9b93e6bdaf6cb"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==0.23.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1",
+ "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.1.0"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:03be7ad107d252bb7325d4af6309fdd2c025d08854d35f0e7abc8bf048f4245e",
+ "sha256:071552b065e809d24c5653fcc14968cfd6fde4e279408640d5ac58e3353a3c5f",
+ "sha256:08b8723248730599c9803ae4c97b8f3f76c55219104303c88cb962a31e3bb5ee",
+ "sha256:08bda7b2c522ff9f1e554570da16298271ebb0c56ab9699446aacba249008988",
+ "sha256:0aaf4d44f1f819360f9432df538d54bbf850f18152f34e20337c01b828479171",
+ "sha256:0cabfc297f4cf921f15bc789a8fbfd7115eb9f813d3f47a74b609894bc66ab0d",
+ "sha256:13acf6164ead81c9fc2afa0e1ea6d6134352973ce2bb35496834fee057063c04",
+ "sha256:15b083d1b789b230e5ac284442d9ecb113c93f3785a6824f748befaab803b812",
+ "sha256:161fcd3281c42f644aa8dec7753cca2af03ce654e17d76da4f0dab34a12480ca",
+ "sha256:1a994a42f49dab5b6287e499be7d3d2751776486229980d8857ad53b8333d469",
+ "sha256:20d75ea11527331a2980ab04762a9d960bcfea9475c54bbeab777af880de61cd",
+ "sha256:225c61e08fe517aede7912937939e09adf086c8e6f7e40d4c85ad678c2c2aea3",
+ "sha256:3135dd574ef1286189f3f04a36c8b7a256376914f8cbbce66b94f13125ded858",
+ "sha256:3491c7de09e44eded16824cb58cf9b5cc1dc6f066a0bb7aa69929d02aa53b828",
+ "sha256:3551912f5c34d8dd7c32c6bb00ae04192af47f7b9f653608f107d19c1a21a194",
+ "sha256:38a7b5140a48fc91681cdb5cb95b7cd64640b43d19259fdd707fa9d5a715f2b2",
+ "sha256:3a3498a8326111221560e930f198b495ea6926937e249f475052ffc6893a6680",
+ "sha256:3bfc7689a1bacb9bcd2f2d5185d99507aa29f667a58dd8adaa43b5a348139e46",
+ "sha256:421d13523d11c57f57f257152bc4a6bb463aadf7a3918e9c96fefdd6be8dbfb8",
+ "sha256:424799c71ff435094e5fb823c40eebb4500f0e048133311e9c026467e8ccebac",
+ "sha256:474e21d0e07cd09679e357d1dac76e570dab86665e79a9d3354b10a279ac6fb3",
+ "sha256:4c7e8c8e1e1918dcf6a652ac4b9d87164587c26fd2ce5dd81e73a5ab3b3d492f",
+ "sha256:506a6dab4c7ffdcacdf0b8e70bd20eb2e77fa994519547c9d88d676400fcad58",
+ "sha256:510cd3bfabb63a07405b7b79fae63127e34c118b7531a2cbbafc7a24fd878594",
+ "sha256:517ba47ca04a55b1f50ee8df9fd97f6c37df5537d118fb2718952b8623860466",
+ "sha256:539d4cb1b16b57026999c53e5aab857fe706e70ae5310cc8c232479923f932e6",
+ "sha256:5c36428cc4f7fae56354db7f46677fd21222fc3cb1e8829549b851172033e043",
+ "sha256:5db59223ed1e634d842a053325f85f908359c6dac9c8ddce8ef145061fae7df8",
+ "sha256:5e606846c049ed40940524057bfdf1105af6066688c0e6a1a3ce2038589bae70",
+ "sha256:6060794aac9f7b0644b299f46a9c6cbc0bc470bd01572f4134df140afd41ded6",
+ "sha256:62c29bc36a6d9be68fe7b5aaf1e120b4aa66a958d1e146601fcd583eb12cae7b",
+ "sha256:73326b211e7410c8bd6a74500b1e3f392f39cf10862e243d00937e924f112c01",
+ "sha256:78f07961f4f214ea8e80be63cffd5cc158eb06cd922ffbf6c7155b11728f28f9",
+ "sha256:7c97554ea521f898753d9773891d0347ebfaddcc1dee2ad94850b163171bf1f1",
+ "sha256:8898f6699f740ca93a0879ed07d8e6db02d68af889d0ebb3d13ab017e6b1af1e",
+ "sha256:8a41fdc751dc4707a4fafb111c442411816a7c225ebb5cadb57599534b5d5372",
+ "sha256:8e0004b0393d72d76de94b4792a006cb960c1c65c7659930fbf9a81ce4341982",
+ "sha256:977b1d4f868986b4ba5d03c317fde4d3b66e687d74473130cd598e3103db34fa",
+ "sha256:9a4f6e0b01df820ba9ed0b4e618ca83a1c089e48d4f268d0e00dcd49893d4549",
+ "sha256:9b9298964389c180a063a9e8bac8a80ed42de11d04166b20249bfa0a489e0e0f",
+ "sha256:a08c8b322b671857c81f4c30cd3c8df2895fd3c0e9358714f39e0ef8fb327702",
+ "sha256:ad31f184dcd3271de26ab1f9c51574afb99e1b0e484ab1da3641256b723e4994",
+ "sha256:aff3656af2add93f290731a6b8930b23b35c0c09569150130a58192b3ec6fc61",
+ "sha256:b2f41261b648cf5dee425f37ff14f4ad151c2f24b827052b402637158fd056ef",
+ "sha256:b413117210fa6d92664c3d860571e8e8727c3e8f2ff197276c5d0cb365abd3ad",
+ "sha256:b7efc7e7049ef366777cfd35437c18a4166bb50a5606a1c840ee3b9624b54fc9",
+ "sha256:b8f94acd52e530a38f25e4d5bf7ddfdd4bea9193e718f58419def0d4406b58d3",
+ "sha256:d0a70151d7de8a3194cdc906bcc1a42e14594787c64b0c1c9c975e5a2af3e251",
+ "sha256:d360e5d5dd3d55bf5d1776964625018d85b937d1032bae1926dd52253decd0db",
+ "sha256:d4e62417e89b717a7bcd8576ac3108cd063225942cc91c5b37ff5465fdccd386",
+ "sha256:d65bac5f6724d9ea6f0b5a0f0e4952fbbf209adcf6b5583b54c54bd2fcd74dc0",
+ "sha256:e02beaab433fd1104b2804f909e694cfbdb6578020740a9051597adc1cd4e19f",
+ "sha256:e4b631688dfbdd61b5610e20b64b99d25771c6d52d9da73349342d2a0f11c46a",
+ "sha256:e4e9db78b71db2b1684ee4ecc3e32c4600f18cdf76e6b9ae03e338e52ee4b168",
+ "sha256:eb4d176394c37a76e8b0afe54b12d58614a67a60a7f8c0dd3a5afbb013c01092",
+ "sha256:f08665d3cc5abc2f770f472a9b5f720a9b3ab0b8b3bb97c7c1487515e5653d39",
+ "sha256:f3d851af3852f16ad4adc7ee054fd9c90a7a5063de94d815b7f6a88477b9f4c6",
+ "sha256:f4ba58157e8ae33ee86fadf9062c506e535afd904f07f9be32731f4410a23b7f",
+ "sha256:f664ed7613b8b18f0ce5696b146776266a038c19c5cd6efffa08ecc189b01b73",
+ "sha256:f947b359cc4769af8b49be7e37af01f05fcf15b401da2528021148e4a54426d1",
+ "sha256:fe4189846448df013cd9df11bba38ddf78043f8c290a9f06430732a7a8601cce",
+ "sha256:fea5cb1c63efe1399f0812532c7cf65458d38fd011be350bc5021dfcac39fba8",
+ "sha256:fedf0dee7a412ca6d1d6d92c158fe9cbaa8ea0cae90d268f9ccc0744de7a97d0",
+ "sha256:fffff7bfb6799a763d3742c59c6ee7ffadda21abed557637bc44ed1080876484"
+ ],
+ "version": "==3.11.4"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
+ ],
+ "version": "==2021.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+ "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+ "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.10.0.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
+ "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==2.0.1"
+ },
+ "wtforms": {
+ "extras": [
+ "email"
+ ],
+ "hashes": [
+ "sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
+ "sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
+ ],
+ "version": "==2.3.3"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3",
+ "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.5.0"
+ }
+ },
+ "develop": {}
+}
diff --git a/__pycache__/app.cpython-37.pyc b/__pycache__/app.cpython-37.pyc
new file mode 100644
index 0000000..a7151f5
--- /dev/null
+++ b/__pycache__/app.cpython-37.pyc
Binary files differ
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..08dbc6b
--- /dev/null
+++ b/app.py
@@ -0,0 +1,24 @@
+from flask import Flask
+from database.db import initialize_db
+from flask_restful import Api
+from resources.routes import initialize_routes
+from flask_bcrypt import Bcrypt
+from flask_jwt_extended import JWTManager
+from resources.errors import errors
+from flask_mail import Mail
+from resources.routes import initialize_routes
+
+app = Flask(__name__)
+app.config.from_envvar('ENV_FILE_LOCATION')
+mail = Mail(app)
+
+api = Api(app, errors=errors)
+bcrypt = Bcrypt(app)
+jwt = JWTManager(app)
+
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/surveyWTD'
+}
+
+initialize_db(app)
+initialize_routes(api)
diff --git a/database/__pycache__/db.cpython-37.pyc b/database/__pycache__/db.cpython-37.pyc
new file mode 100644
index 0000000..3064a78
--- /dev/null
+++ b/database/__pycache__/db.cpython-37.pyc
Binary files differ
diff --git a/database/__pycache__/models.cpython-37.pyc b/database/__pycache__/models.cpython-37.pyc
new file mode 100644
index 0000000..ed4ddc0
--- /dev/null
+++ b/database/__pycache__/models.cpython-37.pyc
Binary files differ
diff --git a/database/db.py b/database/db.py
new file mode 100644
index 0000000..a3b6855
--- /dev/null
+++ b/database/db.py
@@ -0,0 +1,7 @@
+from flask_mongoengine import MongoEngine
+
+db = MongoEngine()
+
+
+def initialize_db(app):
+ db.init_app(app)
\ No newline at end of file
diff --git a/database/models.py b/database/models.py
new file mode 100644
index 0000000..2f1e2a0
--- /dev/null
+++ b/database/models.py
@@ -0,0 +1,24 @@
+from .db import db
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+
+class Movie(db.Document):
+ name = db.StringField(required=True, unique=True)
+ casts = db.ListField(db.StringField(), required=True)
+ genres = db.ListField(db.StringField(), required=True)
+ added_by = db.ReferenceField('User')
+
+
+class User(db.Document):
+ email = db.EmailField(required=True, unique=True)
+ password = db.StringField(required=True, min_length=6)
+ movies = db.ListField(db.ReferenceField('Movie', reverse_delete_rule=db.PULL))
+
+ def hash_password(self):
+ self.password = generate_password_hash(self.password).decode('utf8')
+
+ def check_password(self, password):
+ return check_password_hash(self.password, password)
+
+
+User.register_delete_rule(Movie, 'added_by', db.CASCADE)
diff --git a/model.ts b/model.ts
new file mode 100644
index 0000000..f709a5c
--- /dev/null
+++ b/model.ts
@@ -0,0 +1,100 @@
+/*
+ API data model
+*/
+
+/* USER */
+
+interface User {
+ id: number;
+ nit: number;
+ username: string;
+ first_name: string;
+ last_name: string;
+ email: string;
+ password: string;
+ photo: string; // OPIONAL: si consideran que puede ser útil
+ role: string; // o puede ser una tabla de roles
+ permissions: string[];
+ created_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ updated_at: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+ last_login: Date; // OPCIONAL: en algún punto puede ser útil para gestón
+}
+
+interface Interviewed {
+ id: number;
+ nit: number;
+ first_name: string;
+ last_name: string;
+ email: string;
+ birth_date: Date;
+ city: City;
+}
+
+
+interface Creator {
+ id: number;
+ user: User;
+ created_at: Date;
+}
+
+/* CITY */
+interface City {
+ id: number;
+ name: string;
+ description: string;
+}
+
+/* SURVEY */
+
+interface Survey {
+ id: number; // Pienso que puede ser mejor idea usar de id algo como "N&SDJNJ&20Ur%&&wdDWEFDS", para no acceder tan fácil a la url
+ title: string;
+ description: string;
+ image: string;
+ creators: Creator[];
+ questions: Question[];
+ answers: Answer[];
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface QuestionType {
+ id:number;
+ name:string;
+}
+
+interface Question {
+ id: number;
+ question: string;
+ type: number;
+ is_obligatory: boolean; // Dudo que sea necesario, teniendo en cuenta que todas las respuestas son editables
+ options: string[];
+ other_option: boolean; // Define si el que responder puede sugerir una respuesta
+}
+
+interface AnswerPerson {
+ id_question: number;
+ answers_person: any[];
+}
+
+
+interface Answer {
+ creators: Creator[];
+ interviewed: Interviewed; // IMPORTANTE: Si esto es muy importante de definir.
+ // 1. Si se hace como una variable aparte, tocaría
+ // colocar una pregunta fija para todas las encuestas, que tome todos los datos del encuestado,
+ // y permitiria buscar y filtrar por datos de encuestado
+ // 2. Si esa pregunta no es fija para todas las, tocaría dejar que el que cree
+ // la encuesta agrege la pregunta de datos de encuestado a su gusto,
+ // sin embargo, si se hace así, no se podría ni buscar ni filtrar por encuestado
+ answer_person: AnswerPerson[];
+ state: State;
+ created_at: Date;
+ updated_at: Date;
+}
+
+interface State {
+ id: number;
+ name: string; // Completado; En proceso; No responde; pendiente;
+ description: string;
+}
diff --git a/resources/__pycache__/auth.cpython-37.pyc b/resources/__pycache__/auth.cpython-37.pyc
new file mode 100644
index 0000000..1601832
--- /dev/null
+++ b/resources/__pycache__/auth.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/movie.cpython-37.pyc b/resources/__pycache__/movie.cpython-37.pyc
new file mode 100644
index 0000000..063272c
--- /dev/null
+++ b/resources/__pycache__/movie.cpython-37.pyc
Binary files differ
diff --git a/resources/__pycache__/routes.cpython-37.pyc b/resources/__pycache__/routes.cpython-37.pyc
new file mode 100644
index 0000000..ef0a5dc
--- /dev/null
+++ b/resources/__pycache__/routes.cpython-37.pyc
Binary files differ
diff --git a/resources/auth.py b/resources/auth.py
new file mode 100644
index 0000000..9581b58
--- /dev/null
+++ b/resources/auth.py
@@ -0,0 +1,48 @@
+from flask import Response, request
+from flask_jwt_extended import create_access_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist
+from resources.errors import SchemaValidationError, EmailAlreadyExistsError, UnauthorizedError, InternalServerError
+
+
+class SignupApi(Resource):
+ @staticmethod
+ def post():
+
+ try:
+ body = request.get_json()
+ user = User(**body)
+ user.hash_password()
+ user.save()
+ id = user.id
+ return {'id': str(id)}, 200
+ except FieldDoesNotExist:
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise EmailAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class LoginApi(Resource):
+
+ def post(self):
+
+ try:
+ body = request.get_json()
+ user = User.objects.get(email=body.get('email'))
+ authorized = user.check_password(body.get('password'))
+
+ if not authorized:
+ raise UnauthorizedError
+
+ expires = datetime.timedelta(days=7)
+ access_token = create_access_token(identity=str(user.id), expires_delta=expires)
+
+ return {'token': access_token}, 200
+ except (UnauthorizedError, DoesNotExist):
+ raise UnauthorizedError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/errors.py b/resources/errors.py
new file mode 100644
index 0000000..334ca5f
--- /dev/null
+++ b/resources/errors.py
@@ -0,0 +1,82 @@
+class InternalServerError(Exception):
+ pass
+
+
+class SchemaValidationError(Exception):
+ pass
+
+
+class MovieAlreadyExistsError(Exception):
+ pass
+
+
+class UpdatingMovieError(Exception):
+ pass
+
+
+class DeletingMovieError(Exception):
+ pass
+
+
+class MovieNotExistsError(Exception):
+ pass
+
+
+class EmailAlreadyExistsError(Exception):
+ pass
+
+
+class UnauthorizedError(Exception):
+ pass
+
+
+class EmailDoesnotExistsError(Exception):
+ pass
+
+
+class BadTokenError(Exception):
+ pass
+
+
+errors = {
+ "InternalServerError": {
+ "message": "Algo va mal en el servidor",
+ "status": 500
+ },
+ "SchemaValidationError": {
+ "message": "Faltan campos por enviar",
+ "status": 400
+ },
+ "MovieAlreadyExistsError": {
+ "message": "El registro ya existe en base de datos",
+ "status": 400
+ },
+ "UpdatingMovieError": {
+ "message": "No tienes los suficientes permisos para actualizar el registro",
+ "status": 403
+ },
+ "DeletingMovieError": {
+ "message": "No tienes los suficientes permisos para eliminar el registro",
+ "status": 403
+ },
+ "MovieNotExistsError": {
+ "message": "El registro no existe en base de datos",
+ "status": 400
+ },
+ "EmailAlreadyExistsError": {
+ "message": "El usuario ya existe en base de datos",
+ "status": 400
+ },
+ "UnauthorizedError": {
+ "message": "Usuario y/o contraseña inválida",
+ "status": 401
+ },
+ "EmailDoesnotExistsError": {
+ "message": "No se pudó encontrar un usuarios con el correo ingresado",
+ "status": 400
+ },
+ "BadTokenError": {
+ "message": "Token Inválido",
+ "status": 403
+ }
+}
diff --git a/resources/movie.py b/resources/movie.py
new file mode 100644
index 0000000..b7c3e51
--- /dev/null
+++ b/resources/movie.py
@@ -0,0 +1,81 @@
+from flask import Response, request
+from flask_restful import Resource
+from database.models import Movie, User
+from flask_jwt_extended import jwt_required, get_jwt_identity
+
+from mongoengine.errors import FieldDoesNotExist, NotUniqueError, DoesNotExist, ValidationError, InvalidQueryError
+
+from resources.errors import SchemaValidationError, MovieAlreadyExistsError, InternalServerError, UpdatingMovieError, \
+ DeletingMovieError, MovieNotExistsError
+
+
+class MoviesApi(Resource):
+ @staticmethod
+ def get():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
+ @staticmethod
+ @jwt_required
+ def post():
+
+ try:
+ user_id = get_jwt_identity()
+ body = request.get_json()
+ user = User.objects.get(id=user_id)
+ movie = Movie(**body, added_by=user)
+ movie.save()
+ user.update(push__movies=movie)
+ user.save()
+ id = movie.id
+ return {'id': str(id)}, 200
+ except (FieldDoesNotExist, ValidationError):
+ raise SchemaValidationError
+ except NotUniqueError:
+ raise MovieAlreadyExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class MovieApi(Resource):
+ @staticmethod
+ @jwt_required
+ def put(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
+ except InvalidQueryError:
+ raise SchemaValidationError
+ except DoesNotExist:
+ raise UpdatingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ @jwt_required
+ def delete(self, id):
+
+ try:
+ user_id = get_jwt_identity()
+ movie = Movie.objects.get(id=id, added_by=user_id)
+ movie.delete()
+ return '', 200
+ except DoesNotExist:
+ raise DeletingMovieError
+ except Exception:
+ raise InternalServerError
+
+ @staticmethod
+ def get(self, id):
+
+ try:
+ movies = Movie.objects.get(id=id).to_json()
+ return Response(movies, mimetype="application/json", status=200)
+ except DoesNotExist:
+ raise MovieNotExistsError
+ except Exception:
+ raise InternalServerError
diff --git a/resources/reset_password.py b/resources/reset_password.py
new file mode 100644
index 0000000..4948324
--- /dev/null
+++ b/resources/reset_password.py
@@ -0,0 +1,74 @@
+from flask import request, render_template
+from flask_jwt_extended import create_access_token, decode_token
+from database.models import User
+from flask_restful import Resource
+import datetime
+from resources.errors import SchemaValidationError, InternalServerError, EmailDoesnotExistsError, BadTokenError
+from jwt.exceptions import ExpiredSignatureError, DecodeError, InvalidTokenError
+from services.mail_service import send_email
+
+
+class ForgotPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ email = body.get('email')
+ if not email:
+ raise SchemaValidationError
+
+ user = User.objects.get(email=email)
+ if not user:
+ raise EmailDoesnotExistsError
+
+ expires = datetime.timedelta(hours=24)
+ reset_token = create_access_token(str(user.id), expires_delta=expires)
+
+ return send_email('[Movie-bag] Cambia tu Contraseña',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body=render_template('email/reset_password.txt',
+ url=url + reset_token),
+ html_body=render_template('email/reset_password.html',
+ url=url + reset_token))
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except EmailDoesnotExistsError:
+ raise EmailDoesnotExistsError
+ except Exception as e:
+ raise InternalServerError
+
+
+class ResetPassword(Resource):
+ def post(self):
+ url = request.host_url + 'reset/'
+ try:
+ body = request.get_json()
+ reset_token = body.get('reset_token')
+ password = body.get('password')
+
+ if not reset_token or not password:
+ raise SchemaValidationError
+
+ user_id = decode_token(reset_token)['identity']
+
+ user = User.objects.get(id=user_id)
+
+ user.modify(password=password)
+ user.hash_password()
+ user.save()
+
+ return send_email('[Movie-bag] Cambio de Contraseña Exitoso',
+ sender='support@test.com',
+ recipients=[user.email],
+ text_body='El cambio de tu contraseña fue exitoso',
+ html_body='Cambio de contraseña exitoso
')
+
+ except SchemaValidationError:
+ raise SchemaValidationError
+ except ExpiredSignatureError:
+ raise ExpiredSignatureError
+ except (DecodeError, InvalidTokenError):
+ raise BadTokenError
+ except Exception as e:
+ raise InternalServerError
diff --git a/resources/routes.py b/resources/routes.py
new file mode 100644
index 0000000..c68188b
--- /dev/null
+++ b/resources/routes.py
@@ -0,0 +1,12 @@
+from .movie import MoviesApi, MovieApi
+from .auth import SignupApi, LoginApi
+from .reset_password import ForgotPassword, ResetPassword
+
+
+def initialize_routes(api):
+ api.add_resource(MoviesApi, '/api/movies')
+ api.add_resource(MovieApi, '/api/movies/')
+ api.add_resource(SignupApi, '/api/auth/signup')
+ api.add_resource(LoginApi, '/api/auth/login')
+ api.add_resource(ForgotPassword, '/api/auth/forgot')
+ api.add_resource(ResetPassword, '/api/auth/reset')
diff --git a/run.py b/run.py
new file mode 100644
index 0000000..dddb9f2
--- /dev/null
+++ b/run.py
@@ -0,0 +1,6 @@
+from livereload import Server
+from app import app
+
+if __name__=='__main__':
+ server = Server(app.wsgi_app)
+ server.serve()
\ No newline at end of file
diff --git a/services/mail_service.py b/services/mail_service.py
new file mode 100644
index 0000000..af53dad
--- /dev/null
+++ b/services/mail_service.py
@@ -0,0 +1,21 @@
+from threading import Thread
+from flask_mail import Message
+
+from app import app
+from app import mail
+from resources.errors import InternalServerError
+
+
+def send_async_email(app, msg):
+ with app.app_context():
+ try:
+ mail.send(msg)
+ except ConnectionRefusedError:
+ raise InternalServerError("[MAIL SERVER] not working")
+
+
+def send_email(subject, sender, recipients, text_body, html_body):
+ msg = Message(subject, sender=sender, recipients=recipients)
+ msg.body = text_body
+ msg.html = html_body
+ Thread(target=send_async_email, args=(app, msg)).start()
diff --git a/templates/email/reset_password.html b/templates/email/reset_password.html
new file mode 100644
index 0000000..c02b9c0
--- /dev/null
+++ b/templates/email/reset_password.html
@@ -0,0 +1,12 @@
+Estimado, Usuario
+
+ Para cambiar tu contraseña
+
+ Clic aquí
+ .
+
+ Alternativamente, puedes pegar el siguiente enlace en la barra de direcciones de tu navegador:
+ {{url}}
+ Si no has solicitado un restablecimiento de contraseña, simplemente ignora este mensaje.
+ Atentamente
+ Equipo de asistencia de ...
diff --git a/templates/email/reset_password.txt b/templates/email/reset_password.txt
new file mode 100644
index 0000000..d893252
--- /dev/null
+++ b/templates/email/reset_password.txt
@@ -0,0 +1,11 @@
+Estimado usuario
+
+Para restablecer tu contraseña haz clic en el siguiente enlace:
+
+{{url}}
+
+Si no has solicitado un restablecimiento de contraseña, simplemente ignora este mensaje.
+
+Atentamente
+
+Equipo de soporte de ...
\ No newline at end of file