modification du layout du projet

This commit is contained in:
2022-05-22 19:24:43 +02:00
parent d19676b591
commit 89eb63af86
16 changed files with 808 additions and 237 deletions

View File

@@ -11,6 +11,8 @@ flask-api = "*"
pyjwt = "*"
flask-jwt-extended = "*"
flask-cors = "*"
flask-restx = "*"
sqlalchemy = "*"
[dev-packages]

184
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "669b22bb2a66c8f60df267735d00d669d090508392aa6a13af139f18ecffba67"
"sha256": "d32cc66979cc6c5146b7607b4d44ecf5aca0c98e863c8f3c4ce33ef9e5246458"
},
"pipfile-spec": 6,
"requires": {
@@ -16,12 +16,29 @@
]
},
"default": {
"aniso8601": {
"hashes": [
"sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f",
"sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"
],
"markers": "python_version >= '3.5'",
"version": "==9.0.1"
},
"attrs": {
"hashes": [
"sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4",
"sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==21.4.0"
},
"certifi": {
"hashes": [
"sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
"sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"
"sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7",
"sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a"
],
"version": "==2021.10.8"
"markers": "python_version >= '3.6'",
"version": "==2022.5.18.1"
},
"charset-normalizer": {
"hashes": [
@@ -71,6 +88,75 @@
"index": "pypi",
"version": "==4.4.0"
},
"flask-restx": {
"hashes": [
"sha256:63c69a61999a34f1774eaccc6fc8c7f504b1aad7d56a8ec672264e52d9ac05f4",
"sha256:96157547acaa8892adcefd8c60abf9040212ac2a8634937a82946e07b46147fd"
],
"index": "pypi",
"version": "==0.5.1"
},
"greenlet": {
"hashes": [
"sha256:0051c6f1f27cb756ffc0ffbac7d2cd48cb0362ac1736871399a739b2885134d3",
"sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711",
"sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd",
"sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073",
"sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708",
"sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67",
"sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23",
"sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1",
"sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08",
"sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd",
"sha256:2bde6792f313f4e918caabc46532aa64aa27a0db05d75b20edfc5c6f46479de2",
"sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa",
"sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8",
"sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40",
"sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab",
"sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6",
"sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc",
"sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b",
"sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e",
"sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963",
"sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3",
"sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d",
"sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d",
"sha256:8c5d5b35f789a030ebb95bff352f1d27a93d81069f2adb3182d99882e095cefe",
"sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28",
"sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3",
"sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e",
"sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c",
"sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d",
"sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0",
"sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497",
"sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee",
"sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713",
"sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58",
"sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a",
"sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06",
"sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88",
"sha256:b336501a05e13b616ef81ce329c0e09ac5ed8c732d9ba7e3e983fcc1a9e86965",
"sha256:b8c008de9d0daba7b6666aa5bbfdc23dcd78cafc33997c9b7741ff6353bafb7f",
"sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4",
"sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5",
"sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c",
"sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a",
"sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1",
"sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43",
"sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627",
"sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b",
"sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168",
"sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d",
"sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5",
"sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478",
"sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf",
"sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce",
"sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c",
"sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b"
],
"markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))",
"version": "==1.1.2"
},
"idna": {
"hashes": [
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
@@ -103,6 +189,14 @@
"markers": "python_version >= '3.7'",
"version": "==3.1.2"
},
"jsonschema": {
"hashes": [
"sha256:71b5e39324422543546572954ce71c67728922c104902cb7ce252e522235b33f",
"sha256:7c6d882619340c3347a1bf7315e147e6d3dae439033ae6383d6acb908c101dfc"
],
"markers": "python_version >= '3.7'",
"version": "==4.5.1"
},
"mariadb": {
"hashes": [
"sha256:166973d6cd7da5d4fe84fc9d63f8d219a660ed2c82ebf6acadc9b3dd811f51bc",
@@ -166,11 +260,45 @@
},
"pyjwt": {
"hashes": [
"sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41",
"sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f"
"sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf",
"sha256:d42908208c699b3b973cbeb01a969ba6a96c821eefb1c5bfe4c390c01d67abba"
],
"index": "pypi",
"version": "==2.3.0"
"version": "==2.4.0"
},
"pyrsistent": {
"hashes": [
"sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c",
"sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc",
"sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e",
"sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26",
"sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec",
"sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286",
"sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045",
"sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec",
"sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8",
"sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c",
"sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca",
"sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22",
"sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a",
"sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96",
"sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc",
"sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1",
"sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07",
"sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6",
"sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b",
"sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5",
"sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6"
],
"markers": "python_version >= '3.7'",
"version": "==0.18.1"
},
"pytz": {
"hashes": [
"sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7",
"sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"
],
"version": "==2022.1"
},
"requests": {
"hashes": [
@@ -188,6 +316,48 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"sqlalchemy": {
"hashes": [
"sha256:09c606d8238feae2f360b8742ffbe67741937eb0a05b57f536948d198a3def96",
"sha256:166a3887ec355f7d2f12738f7fa25dc8ac541867147a255f790f2f41f614cb44",
"sha256:16abf35af37a3d5af92725fc9ec507dd9e9183d261c2069b6606d60981ed1c6e",
"sha256:2e885548da361aa3f8a9433db4cfb335b2107e533bf314359ae3952821d84b3e",
"sha256:2ec89bf98cc6a0f5d1e28e3ad28e9be6f3b4bdbd521a4053c7ae8d5e1289a8a1",
"sha256:2ecac4db8c1aa4a269f5829df7e706639a24b780d2ac46b3e485cbbd27ec0028",
"sha256:316c7e5304dda3e3ad711569ac5d02698bbc71299b168ac56a7076b86259f7ea",
"sha256:5041474dcab7973baa91ec1f3112049a9dd4652898d6a95a6a895ff5c58beb6b",
"sha256:53d2d9ee93970c969bc4e3c78b1277d7129554642f6ffea039c282c7dc4577bc",
"sha256:5864a83bd345871ad9699ce466388f836db7572003d67d9392a71998092210e3",
"sha256:5c90ef955d429966d84326d772eb34333178737ebb669845f1d529eb00c75e72",
"sha256:5d50cb71c1dbed70646d521a0975fb0f92b7c3f84c61fa59e07be23a1aaeecfc",
"sha256:64678ac321d64a45901ef2e24725ec5e783f1f4a588305e196431447e7ace243",
"sha256:64d796e9af522162f7f2bf7a3c5531a0a550764c426782797bbeed809d0646c5",
"sha256:6cb4c4f57a20710cea277edf720d249d514e587f796b75785ad2c25e1c0fed26",
"sha256:6e1fe00ee85c768807f2a139b83469c1e52a9ffd58a6eb51aa7aeb524325ab18",
"sha256:6e859fa96605027bd50d8e966db1c4e1b03e7b3267abbc4b89ae658c99393c58",
"sha256:7a052bd9f53004f8993c624c452dfad8ec600f572dd0ed0445fbe64b22f5570e",
"sha256:81e53bd383c2c33de9d578bfcc243f559bd3801a0e57f2bcc9a943c790662e0c",
"sha256:83cf3077712be9f65c9aaa0b5bc47bc1a44789fd45053e2e3ecd59ff17c63fe9",
"sha256:8b20c4178ead9bc398be479428568ff31b6c296eb22e75776273781a6551973f",
"sha256:8d07fe2de0325d06e7e73281e9a9b5e259fbd7cbfbe398a0433cbb0082ad8fa7",
"sha256:a0ae3aa2e86a4613f2d4c49eb7da23da536e6ce80b2bfd60bbb2f55fc02b0b32",
"sha256:af2587ae11400157753115612d6c6ad255143efba791406ad8a0cbcccf2edcb3",
"sha256:b3db741beaa983d4cbf9087558620e7787106319f7e63a066990a70657dd6b35",
"sha256:be094460930087e50fd08297db9d7aadaed8408ad896baf758e9190c335632da",
"sha256:cb441ca461bf97d00877b607f132772644b623518b39ced54da433215adce691",
"sha256:ce20f5da141f8af26c123ebaa1b7771835ca6c161225ce728962a79054f528c3",
"sha256:d57ac32f8dc731fddeb6f5d1358b4ca5456e72594e664769f0a9163f13df2a31",
"sha256:dce3468bf1fc12374a1a732c9efd146ce034f91bb0482b602a9311cb6166a920",
"sha256:e12532c4d3f614678623da5d852f038ace1f01869b89f003ed6fe8c793f0c6a3",
"sha256:e74ce103b81c375c3853b436297952ef8d7863d801dcffb6728d01544e5191b5",
"sha256:f0394a3acfb8925db178f7728adb38c027ed7e303665b225906bfa8099dc1ce8",
"sha256:f522214f6749bc073262529c056f7dfd660f3b5ec4180c5354d985eb7219801e",
"sha256:fbf8c09fe9728168f8cc1b40c239eab10baf9c422c18be7f53213d70434dea43",
"sha256:fca8322e04b2dde722fcb0558682740eebd3bd239bea7a0d0febbc190e99dc15"
],
"index": "pypi",
"version": "==1.4.36"
},
"urllib3": {
"hashes": [
"sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14",

77
log/U10Manager.log Normal file
View File

@@ -0,0 +1,77 @@
2022-05-19 16:41:16,281 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 16:41:16,285 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 16:42:50,490 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 16:42:50,502 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 16:46:54,185 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 16:46:54,195 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 16:46:54,345 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 16:47:33,809 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 16:47:33,812 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 16:47:33,957 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:42:07,368 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:42:07,395 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:42:07,489 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:42:39,145 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:42:39,152 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:42:39,251 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:44:48,956 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:44:48,959 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:44:48,981 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:44:57,140 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:47:37,823 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:47:37,834 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:48:03,411 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:48:03,415 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:48:03,443 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:48:03,448 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:49:04,618 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:49:04,619 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:49:04,659 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:49:04,660 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:50:56,568 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:50:56,574 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:50:56,592 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:50:56,595 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:50:59,020 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:50:59,026 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:23,530 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:23,532 - U10Manager [views.login:109] - ERROR - authorization failed !
2022-05-19 19:51:23,532 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:33,784 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:33,787 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:33,918 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:33,922 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:36,908 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:36,909 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:36,929 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:36,932 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:47,744 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:47,747 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:47,913 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:47,916 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:50,345 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:50,347 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:50,369 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:50,372 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:51:52,796 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:51:52,798 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:52:13,041 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:52:13,100 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:52:22,270 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 19:52:22,274 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 19:52:22,375 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 20:11:24,554 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 20:11:24,606 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-19 20:11:31,885 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-19 20:11:31,886 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-20 09:01:52,314 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-20 09:01:52,322 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-20 09:01:52,485 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-20 09:01:52,496 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-20 09:04:13,524 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-20 09:04:13,541 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-20 09:04:13,743 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-20 09:04:13,745 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données
2022-05-20 09:21:42,458 - U10Manager [db.connect:95] - INFO - Connexion à la base de données
2022-05-20 09:21:42,465 - U10Manager [views.post:89] - ERROR - Login and Password required !
2022-05-20 09:21:42,465 - U10Manager [db.disconnect:112] - INFO - Déconnexion de la base de données

0
requirements.txt Normal file
View File

9
run.py Normal file
View File

@@ -0,0 +1,9 @@
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : U10Manager Flask RESTful API
from src import app
print("Launch Flask RESTful API Backend ...")
application = app.create_app()
application.run(host="0.0.0.0")

12
setup.py Normal file
View File

@@ -0,0 +1,12 @@
from setuptools import find_packages, setup
setup(
name='U10Manager',
version='1.0.0',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
install_requires=[
'flask',
],
)

View File

@@ -0,0 +1,4 @@
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : U10Manager Flask RESTful API

104
src/app.py Normal file
View File

@@ -0,0 +1,104 @@
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : U10Manager Flask RESTful API
#########################################################
# Importation de modules externes #
import sys, re, os
from pprint import pprint
import logging as log
from logging.config import dictConfig
from flask import Flask
from flask.logging import default_handler
from flask_cors import CORS, cross_origin
from flask_jwt_extended import JWTManager
import jwt
from src.config import DefaultConfig
from src.db import db
from src.users import users
from src.auth import auth
#########################################################
# Corps principal du programme #
def create_app(config=None, app_name=None):
''' create and configure the app '''
print("Create and configure the Flask app ...")
if app_name is None:
app_name = DefaultConfig.PROJECT
# create the app
# tells the app that configuration files are relative to the instance folder.
app = Flask(app_name, instance_path=os.getcwd(), instance_relative_config=True)
configure_app(app, config)
configure_log(app)
configure_database(app)
configure_blueprints(app)
return app
def configure_app(app, config=None):
''' configure the app with conf file and/or object '''
# load default config
app.config.from_object(DefaultConfig)
if config:
# load specific config
app.config.from_object(config)
# setup the Flask-JWT-Extended extension
jwt = JWTManager(app)
# setup the Flask-CORS extension for handling Cross Origin Resource Sharing
CORS(app, resources={r"/api/*": {
"origins": ["http://localhost:4200","http://localhost:5000"],
"supports_credentials": True
}})
def configure_log(app):
''' configure log handler '''
if not os.path.exists(app.config['LOG_FOLDER']):
try:
os.makedirs(app.config['LOG_FOLDER'])
except OSError:
pass
# On vire tous les handlers
for h in app.logger.handlers:
app.logger.removeHandler(h)
# Set info level on logger, which might be overwritten by handers.
# Suppress DEBUG messages.
app.logger.setLevel(log.DEBUG)
formatter = log.Formatter('%(asctime)s - %(name)s [%(module)s.%(funcName)s:%(lineno)d] - %(levelname)s - %(message)s')
info_log = os.path.join(app.config['LOG_FOLDER'], DefaultConfig.PROJECT + '.log')
info_file_handler = log.handlers.RotatingFileHandler(info_log, maxBytes=100000, backupCount=10)
info_file_handler.setLevel(log.INFO)
info_file_handler.setFormatter(formatter)
app.logger.addHandler(info_file_handler)
fl = log.StreamHandler()
fl.setLevel(log.DEBUG)
fl.setFormatter(formatter)
app.logger.addHandler(fl)
def configure_database(app):
''' configure database parameters '''
# Set database parameters ...
db.host = app.config['SQL_HOST_URI']
db.port = app.config['SQL_PORT']
db.user = app.config['SQL_USERNAME']
db.password = app.config['SQL_PASSWORD']
db.database = app.config['SQL_DATABASE']
def configure_blueprints(app):
''' configure blueprints '''
for bp in [users, auth]:
app.register_blueprint(bp)

6
src/auth/__init__.py Normal file
View File

@@ -0,0 +1,6 @@
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : Users views and models
from .views import auth

123
src/auth/views.py Normal file
View File

@@ -0,0 +1,123 @@
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : Auth routes
#########################################################
# Importation de modules externes #
import sys, re, os
import logging as log
from flask import Flask, Blueprint, request, abort, jsonify, current_app
from flask_api import status
from flask_jwt_extended import create_access_token
from flask_jwt_extended import get_jwt
from flask_jwt_extended import set_access_cookies
from flask_jwt_extended import unset_jwt_cookies
from flask_jwt_extended import get_jwt_identity
from flask_jwt_extended import jwt_required
from flask_restx import Api, Resource, reqparse
import json
from werkzeug.security import check_password_hash
from werkzeug.exceptions import HTTPException
from src.db import db, dbmanage
#########################################################
# Class et Methods #
auth = Blueprint('auth', __name__, url_prefix='/api/utilisateurs')
api = Api(auth,
version="1.0",
title="U10Manager Flask RESTful API",
description="Welcome to the Swagger UI documentation site!",
doc="/ui")
@auth.errorhandler(HTTPException)
def handle_exception(e):
''' return JSON instead of HTML for HTTP errors '''
response = e.get_response()
# replace the body with JSON
response.data = json.dumps({
'code': e.code,
'name': e.name,
'description': e.description,
})
response.content_type = "application/json"
return response
@auth.after_request
def refresh_expiring_tokens(response):
''' Using an 'after_request' callback, we refresh any token that is within
30 minutes of expiring.'''
try:
exp_timestamp = get_jwt()['exp']
now = datetime.datetime.now(datetime.timezone.utc)
target_timestamp = datetime.datetime.timestamp(now + datetime.timedelta(minutes=30))
### DEBUG ###
current_app.logger.debug("exp: {} - target: {}".format(exp_timestamp, target_timestamp))
### END DEBUG ###
if target_timestamp > exp_timestamp:
current_app.logger.warning("On doit recréer un token ....")
access_token = create_access_token(identity=get_jwt_identity())
set_access_cookies(response, access_token)
return response
except (RuntimeError, KeyError):
return response
@auth.route('/login', methods=['POST'])
def login():
### DEBUG ###
current_app.logger.debug("Request : {}".format(request))
current_app.logger.debug("Auth {}".format(request.authorization))
### END DEBUG ###
auth = request.authorization
user = None
if not auth or not auth.username or not auth.password:
current_app.logger.error("Login and Password required !")
db.disconnect()
abort(401, description='Login and Password required')
# On vérifie que l'utilisateur existe en base de données
sql_statement = "SELECT * FROM utilisateur WHERE Identifiant = \"{}\"".format(auth.username)
# execution de la requete sql
etat, ret = db.execute(sql_statement, None, False)
if not etat:
db.disconnect()
abort(500)
else:
if not ret:
db.disconnect()
abort(404)
else:
user = ret[0]
### DEBUG ###
current_app.logger.debug("user bdd: {}".format(user))
### END DEBUG ###
if user and user['Actif'] and check_password_hash(user['Password'], auth.password):
try:
# create a new access token
token = create_access_token(identity=user)
content = jsonify({'message': 'login successful !'})
# set token as cookie
set_access_cookies(content, token)
except Exception as e:
current_app.logger.erreur('Erreur : {}'.format(e))
db.disconnect()
abort(500)
return content
current_app.logger.error("authorization failed !")
db.disconnect()
abort(401)
@auth.route('/logout', methods=['POST'])
def logout():
""" Handles HTTP requests to URL: /api/utilisateurs/logout """
content = jsonify({'message': 'logout successful !'})
unset_jwt_cookies(content)
return content

47
src/config.py Normal file
View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
#
# @author: vincent.benoit@benserv.fr
# @brief: Flask Config classes
import os
import datetime
class BaseConfig(object):
PROJECT = "U10Manager"
# Get app root path, also can use flask.root_path.
PROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
DEBUG = False
TESTING = False
ADMINS = ['vincent.benoit@benserv.fr']
LOG_FOLDER = os.path.join(os.getcwd(), 'log')
class DefaultConfig(BaseConfig):
DEBUG = True
TESTING = True
FLASK_ENV = 'development'
SECRET_KEY = "thisissecret"
# Setup the Flask-JWT-Extended extension
JWT_SECRET_KEY = "cdscjdsklcfqezffhrevneqggfuhmnvqnmh"
JWT_COOKIE_SECURE = False
JWT_TOKEN_LOCATION = ["cookies"]
JWT_ACCESS_TOKEN_EXPIRES = datetime.timedelta(hours=1)
# Controls if Cross Site Request Forgery (CSRF) protection is enabled when using cookies
# This should always be True in production
JWT_COOKIE_CSRF_PROTECT = True
JWT_CSRF_IN_COOKIES = True
UPLOAD_FOLDER = os.path.join(os.getcwd(),'static/img')
ALLOWED_EXTENSIONS = {'png', 'jpg', 'gif', 'jpeg'}
MAX_CONTENT_LENGTH = 1 * 1024 * 1024 # 1 megabytes
SQL_HOST_URI = '127.0.0.1'
SQL_PORT = 3306
SQL_USERNAME = 'vincent'
SQL_PASSWORD = 'malkavian'
SQL_DATABASE = 'test1'

168
src/db.py Normal file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : wrapper de la base de données mariadb
#########################################################
# Importation de modules externes #
import sys, re, os
import logging as log
import mariadb
from flask_api import status
from flask import current_app
from functools import wraps
from src.config import DefaultConfig
#########################################################
# Class et Methods #
class BDDsql:
_conf = {
'host': '',
'port': 0,
'user': '',
'password': '',
'database': ''
}
def __init__(self, host="0.0.0.0", port=3306, user="user1", password="pass1", database="db1"):
''' Constructor '''
self._conf['host']=host
self._conf['port']=port
self._conf['user']=user
self._conf['password']=password
self._conf['database']=database
self.connected = False
self.logger = log.getLogger(DefaultConfig.PROJECT)
@property
def host(self):
''' getter host parameter '''
return self._conf['host']
@host.setter
def host(self, host=""):
''' setter host parameter '''
self._conf['host'] = host
@property
def port(self):
''' getter port parameter '''
return self._conf['port']
@port.setter
def port(self, port=0):
''' setter port parameter '''
self._conf['port'] = port
@property
def user(self):
''' getter user parameter '''
return self._conf['user']
@user.setter
def user(self, user=""):
''' setter user parameter'''
self._conf['user'] = user
@property
def password(self):
''' getter password parameter '''
return self._conf['password']
@password.setter
def password(self, password=""):
''' setter password parameter '''
self._conf['password'] = password
@property
def database(self):
''' getter database parameter '''
return self._conf['database']
@database.setter
def database(self, database=""):
''' setter database parameter '''
self._conf['database'] = database
def connect(self):
''' connect to database '''
self.logger.info("Connexion à la base de données")
self.conn = None
self.cursor = None
try:
# connection for MariaDB
self.conn = mariadb.connect(**self._conf)
# create a connection cursor
self.cursor = self.conn.cursor()
self.connected = True
except mariadb.Error as e:
self.logger.error("Error connecting to MariaDB Platform: {}".format(e))
content = {'error': str(e)}
return False, content
return True, {}
def disconnect(self):
''' disconnect from database '''
self.logger.info("Déconnexion de la base de données")
self.conn.close()
self.connected = False
return
def execute(self, sql_statement="", data=None, commit=False):
''' execute SQL statement and retreive datas if necessary '''
json_data=[]
try:
# execute a SQL statement
### DEBUG ###
self.logger.debug("statement: {}".format(sql_statement))
### END DEBUG ###
if not data:
self.cursor.execute(sql_statement)
else:
self.cursor.execute(sql_statement, data)
if commit:
self.conn.commit()
except mariadb.Error as e:
self.logger.error("Error: {}".format(e))
content = {'error': str(e)}
return False, content
if not commit:
# serialize results into JSON
row_headers=[x[0] for x in self.cursor.description]
rv = self.cursor.fetchall()
### DEBUG ###
self.logger.debug("description: {} - datas: {}".format(self.cursor.description, rv))
### END DEBUG ###
for result in rv:
json_data.append(dict(zip(row_headers,result)))
return True, json_data
#########################################################
# Decorators #
def dbmanage(func):
''' decorateur de la fonction db.connect & db.disconnect '''
@wraps(func)
def wrapper(*args, **kwargs):
# connexion à la base de données
state, ret = db.connect()
if not state:
content = {'Erreur' : ret['error']}
return content, status.HTTP_503_SERVICE_UNAVAILABLE
else:
# Appel de la fonction
ret = func(*args, **kwargs)
# deconnexion de la base de données
db.disconnect()
return ret
return wrapper
# Instantiate database
db = BDDsql()

4
src/decorators.py Normal file
View File

@@ -0,0 +1,4 @@
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : U10Manager Flask RESTful API

0
src/schema.sql Normal file
View File

6
src/users/__init__.py Normal file
View File

@@ -0,0 +1,6 @@
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : Users views and models
from .views import users

View File

@@ -1,20 +1,17 @@
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
# @author : vincent.benoit@benserv.fr
# @brief : Test du token JWT avec Flask
# @brief : Users routes
#########################################################
# Importation de modules externes #
import sys, re, os
import logging as log
from logging.config import dictConfig
from pprint import pprint
import json
import datetime
from flask import Flask, request, abort, jsonify, render_template, make_response, send_file
from flask_cors import CORS, cross_origin
from flask.logging import default_handler
from flask import Flask, Blueprint, request, abort, jsonify, send_file, current_app
from flask_api import status
from flask_jwt_extended import create_access_token
from flask_jwt_extended import get_jwt
@@ -22,142 +19,19 @@ from flask_jwt_extended import set_access_cookies
from flask_jwt_extended import unset_jwt_cookies
from flask_jwt_extended import get_jwt_identity
from flask_jwt_extended import jwt_required
from flask_jwt_extended import JWTManager
import json
import mariadb
import uuid
import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.security import generate_password_hash
from werkzeug.exceptions import HTTPException, RequestEntityTooLarge
from werkzeug.utils import secure_filename
import jwt
from functools import wraps
from src.db import db, dbmanage
#########################################################
# Class et Methods #
class BDD:
conf = {
'host': '127.0.0.1',
'port': 3306,
'user': 'vincent',
'password': 'malkavian',
'database': 'test1'
}
users = Blueprint('users', __name__, url_prefix='/api/utilisateurs')
def __init__(self, host="0.0.0.0", port=3306, user="user1", password="pass1", database="db1"):
''' Constructor '''
self.conf['host']=host
self.conf['port']=port
self.conf['user']=user
self.conf['password']=password
self.conf['database']=database
self.connected = False
self.logger = log.getLogger("U10Manager")
def connect(self):
''' connect to database '''
self.logger.info("Connexion à la base de données")
self.conn = None
self.cursor = None
try:
# connection for MariaDB
self.conn = mariadb.connect(**self.conf)
# create a connection cursor
self.cursor = self.conn.cursor()
self.connected = True
except mariadb.Error as e:
self.logger.error("Error connecting to MariaDB Platform: {}".format(e))
content = {'error': str(e)}
return False, content
return True, {}
def disconnect(self):
''' disconnect from database '''
self.logger.info("Déconnexion de la base de données")
self.conn.close()
self.connected = False
return
def execute(self, sql_statement="", data=None, commit=False):
''' execute SQL statement and retreive datas if necessary '''
json_data=[]
try:
# execute a SQL statement
### DEBUG ###
self.logger.debug("statement: {}".format(sql_statement))
### END DEBUG ###
if not data:
self.cursor.execute(sql_statement)
else:
self.cursor.execute(sql_statement, data)
if commit:
self.conn.commit()
except mariadb.Error as e:
self.logger.error("Error: {}".format(e))
content = {'error': str(e)}
return False, content
if not commit:
# serialize results into JSON
row_headers=[x[0] for x in self.cursor.description]
rv = self.cursor.fetchall()
self.logger.debug("description: {} - datas: {}".format(self.cursor.description, rv))
for result in rv:
json_data.append(dict(zip(row_headers,result)))
self.logger.debug("json_data: {}".format(pprint(json_data)))
return True, json_data
#########################################################
# Corps principal du programme #
logger = log.getLogger("U10Manager")
app = Flask(__name__)
CORS(app, resources={r"/api/*": {
"origins": "http://localhost:4200",
"supports_credentials": True
}})
db = BDD(host='127.0.0.1', port=3306, user='vincent', password='malkavian', database='test1')
app.config["SECRET_KEY"] = "thisissecret"
# Setup the Flask-JWT-Extended extension
app.config["JWT_SECRET_KEY"] = "cdscjdsklcfqezffhrevneqggfuhmnvqnmh"
app.config["JWT_COOKIE_SECURE"] = False
app.config["JWT_TOKEN_LOCATION"] = ["cookies"]
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = datetime.timedelta(hours=1)
# Controls if Cross Site Request Forgery (CSRF) protection is enabled when using cookies
# This should always be True in production
app.config["JWT_COOKIE_CSRF_PROTECT"] = True
UPLOAD_FOLDER = 'static/img'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'gif', 'jpeg'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 1 * 1000 * 1000 # 1 megabytes
jwt = JWTManager(app)
def dbmanage(func):
''' decorateur de la fonction db.connect & db.disconnect '''
@wraps(func)
def wrapper(*args, **kwargs):
# connexion à la base de données
state, ret = db.connect()
if not state:
content = {'Erreur' : ret['error']}
return content, status.HTTP_503_SERVICE_UNAVAILABLE
else:
# Appel de la fonction
ret = func(*args, **kwargs)
# deconnexion de la base de données
db.disconnect()
return ret
return wrapper
@app.errorhandler(HTTPException)
@users.errorhandler(HTTPException)
def handle_exception(e):
''' return JSON instead of HTML for HTTP errors '''
response = e.get_response()
@@ -170,7 +44,7 @@ def handle_exception(e):
response.content_type = "application/json"
return response
@app.after_request
@users.after_request
def refresh_expiring_tokens(response):
''' Using an 'after_request' callback, we refresh any token that is within
30 minutes of expiring.'''
@@ -179,17 +53,18 @@ def refresh_expiring_tokens(response):
now = datetime.datetime.now(datetime.timezone.utc)
target_timestamp = datetime.datetime.timestamp(now + datetime.timedelta(minutes=30))
### DEBUG ###
logger.debug("exp: {} - target: {}".format(exp_timestamp, target_timestamp))
current_app.logger.debug("exp: {} - target: {}".format(exp_timestamp, target_timestamp))
### END DEBUG ###
if target_timestamp > exp_timestamp:
logger.warning("On doit recréer un token ....")
current_app.logger.warning("On doit recréer un token ....")
access_token = create_access_token(identity=get_jwt_identity())
set_access_cookies(response, access_token)
return response
except (RuntimeError, KeyError):
return response
@app.route('/api/utilisateurs', methods=['GET'])
@users.route('', methods=['GET'])
@jwt_required()
@dbmanage
def get_all_users():
@@ -197,7 +72,7 @@ def get_all_users():
# Access the identity of the current user with get_jwt_identity
current_user = get_jwt_identity()
### DEBUG ###
logger.debug("current_user: {}".format(current_user))
current_app.logger.debug("current_user: {}".format(current_user))
### DEBUG END ###
# Test si l'utilisateur courant est actif ou pas
if not current_user["Actif"]:
@@ -216,7 +91,7 @@ def get_all_users():
content = ret
return jsonify(content)
@app.route('/api/utilisateurs/<int:userId>', methods=['GET'])
@users.route('/<int:userId>', methods=['GET'])
@jwt_required()
@dbmanage
def get_one_user(userId):
@@ -224,7 +99,7 @@ def get_one_user(userId):
# Access the identity of the current user with get_jwt_identity
current_user = get_jwt_identity()
### DEBUG ###
logger.debug("Actif ? {} - Role ? {} - userId : {}/{}".format(current_user["Actif"], current_user["Role"], current_user["userId"], userId))
current_app.logger.debug("Actif ? {} - Role ? {} - userId : {}/{}".format(current_user["Actif"], current_user["Role"], current_user["userId"], userId))
### DEBUG END ###
# Test si l'utilisateur courant est actif ou pas
# Si l'utilisateur courant n'est pas administrateur, il ne peut voir que son profil
@@ -244,7 +119,7 @@ def get_one_user(userId):
content = ret[0]
return jsonify(content)
@app.route('/api/utilisateurs', methods=['POST'])
@users.route('', methods=['POST'])
@jwt_required()
@dbmanage
def add_user():
@@ -270,7 +145,7 @@ def add_user():
db.disconnect()
abort(401, description="Identifiant déjà utilisé!")
### DEBUG ###
logger.debug("Datas: {}".format(data_json))
current_app.logger.debug("Datas: {}".format(data_json))
### END DEBUG ###
# Hash du mot de passe
hashed_password = generate_password_hash(data_json['Password'], method='sha256')
@@ -282,12 +157,12 @@ def add_user():
if not etat:
content = {'Erreur': ret['error']}
### DEBUG ###
logger.debug("content: {}".format(content))
current_app.logger.debug("content: {}".format(content))
### END DEBUG ###
return content, status.HTTP_500_INTERNAL_SERVER_ERROR
return jsonify({'message' : 'Nouvel utilisateur créé!'})
@app.route('/api/utilisateurs/<int:userId>', methods=['PUT'])
@users.route('/<int:userId>', methods=['PUT'])
@jwt_required()
@dbmanage
def modif_user(userId):
@@ -302,7 +177,7 @@ def modif_user(userId):
# test des attributs (JSON) de la requete
if not request.data.decode("utf-8"):
logger.error("Data not found")
current_app.logger.error("Data not found")
db.disconnect()
abort(400, description='Data not found')
@@ -310,9 +185,6 @@ def modif_user(userId):
dataDict = request.get_json()
# Hash du mot de passe
dataDict['Password'] = generate_password_hash(dataDict['Password'], method='sha256')
### DEBUG ###
logger.debug("Datas: {}".format(pprint(dataDict)))
### END DEBUG ###
sql_statement = "UPDATE utilisateur SET Nom=%s, Prenom=%s, Photo=%s, Identifiant=%s, Password=%s, Role=%s, Actif=%d WHERE userId = {}".format(userId)
data = (dataDict['Nom'], dataDict['Prenom'], dataDict['Photo'], dataDict['Identifiant'], dataDict['Password'], dataDict['Role'], dataDict['Actif'])
@@ -323,7 +195,7 @@ def modif_user(userId):
abort(500)
return jsonify({'message' : 'utilisateur {} modifié!'.format(userId)})
@app.route('/api/utilisateurs/<int:userId>', methods=['DELETE'])
@users.route('/<int:userId>', methods=['DELETE'])
@jwt_required()
@dbmanage
def del_user(userId):
@@ -337,7 +209,7 @@ def del_user(userId):
# test des attributs (JSON) de la requete
if request.data.decode("utf-8"):
logger.error("Data found : {}".format(request.data.decode("utf-8")))
current_app.logger.error("Data found : {}".format(request.data.decode("utf-8")))
db.disconnect()
abort(400)
# On vérifie que l'utilisateur existe en base de données
@@ -355,7 +227,7 @@ def del_user(userId):
# On supprime l'utilisateur si celui-ci a été trouvé
sql_statement = "DELETE FROM utilisateur WHERE userId = {}".format(userId)
### DEBUG ###
logger.debug("statement: {}".format(sql_statement))
current_app.logger.debug("statement: {}".format(sql_statement))
### END DEBUG ###
# Execution de la requete SQL
etat, ret = db.execute(sql_statement, None, True)
@@ -365,7 +237,7 @@ def del_user(userId):
content = {'message' : 'utilisateur supprimé!'}
return jsonify(content)
@app.route('/api/utilisateurs/<int:userId>/reset_password', methods=['GET'])
@users.route('/<int:userId>/reset_password', methods=['GET'])
@jwt_required()
@dbmanage
def reset_passwd_user(userId):
@@ -389,7 +261,38 @@ def reset_passwd_user(userId):
content = {'message' : 'reset du mot de passe!'}
return jsonify(content)
@app.route('/api/utilisateurs/<int:userId>/photo', methods=['GET'])
@users.route('/<int:userId>/activate', methods=['PUT'])
@jwt_required()
@dbmanage
def deactivate_user(userId):
''' Désactivation d'un utilisateur représenté par son Id '''
# Access the identity of the current user with get_jwt_identity
current_user = get_jwt_identity()
# Test si l'utilisateur courant est Admin ou pas
if not current_user["Actif"] or current_user["Role"] != 'Administrateur':
db.disconnect()
abort(403, description='Utilisateur non autorisé')
# test des attributs (JSON) de la requete
if not request.data.decode("utf-8"):
current_app.logger.error("Data not found")
db.disconnect()
abort(400, description='Data not found')
# recuperation des attributs (JSON) de la requete
dataDict = request.get_json()
# Création de la requete SQL
sql_statement = "UPDATE utilisateur SET Actif={} WHERE userId = {}".format(dataDict['Actif'], userId)
# Execution de la requete SQL
etat, ret = db.execute(sql_statement, None, True)
if not etat:
db.disconnect()
abort(500)
content = {'message' : 'desactivation de l\'utilisateur réussi!'}
return jsonify(content)
@users.route('/<int:userId>/photo', methods=['GET'])
@jwt_required()
@dbmanage
def get_photo(userId):
@@ -417,10 +320,10 @@ def get_photo(userId):
abort(404)
user = ret[0]
if user['Photo']:
return send_file(os.path.join('../', user['Photo']), mimetype='image/'+os.path.splitext(user['Photo'])[1].split('.')[1])
return send_file(os.path.join(user['Photo']), mimetype='image/'+os.path.splitext(user['Photo'])[1].split('.')[1])
return abort(404, description='Picture not found!')
@app.route('/api/utilisateurs/current', methods=['GET'])
@users.route('/current', methods=['GET'])
@jwt_required()
def current_user():
''' retourne l'utilisateur courant connecté '''
@@ -428,63 +331,10 @@ def current_user():
current_user = get_jwt_identity()
return jsonify(current_user)
@app.route('/api/utilisateurs/login', methods=['POST'])
@dbmanage
def login():
### DEBUG ###
logger.debug("Request : {}".format(request))
logger.debug("Auth {}".format(request.authorization))
### END DEBUG ###
auth = request.authorization
user = None
if not auth or not auth.username or not auth.password:
logger.error("Login and Password required !")
db.disconnect()
abort(401, description='Login and Password required')
# On vérifie que l'utilisateur existe en base de données
sql_statement = "SELECT * FROM utilisateur WHERE Identifiant = \"{}\"".format(auth.username)
# execution de la requete sql
etat, ret = db.execute(sql_statement, None, False)
if not etat:
db.disconnect()
abort(500)
else:
if not ret:
db.disconnect()
abort(404)
else:
user = ret[0]
### DEBUG ###
logger.debug("user bdd: {}".format(user))
### END DEBUG ###
if user and check_password_hash(user['Password'], auth.password):
try:
# create a new access token
token = create_access_token(identity=user)
content = jsonify({'message': 'login successful !'})
# set token as cookie
set_access_cookies(content, token)
except Exception as e:
logger.erreur('Erreur : {}'.format(e))
db.disconnect()
return abort(500)
return content
logger.error("authorization failed !")
db.disconnect()
return abort(401)
@app.route('/api/utilisateurs/logout', methods=['POST'])
def logout():
content = jsonify({'message': 'logout successful !'})
unset_jwt_cookies(content)
return content
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/api/utilisateurs/<int:userId>/uploadImage', methods=['POST'])
@users.route('/<int:userId>/uploadImage', methods=['POST'])
@jwt_required()
@dbmanage
def uploadImage(userId):
@@ -494,7 +344,7 @@ def uploadImage(userId):
# Si l'utilisateur courant n'est pas administrateur, il ne peut voir que son profil
if not current_user["Actif"] or current_user["Role"] != "Administrateur" and current_user['userId'] != userId:
db.disconnect()
logger.error("Utilisateur non autorisé")
current_app.logger.error("Utilisateur non autorisé")
abort(403, description='Utilisateur non autorisé')
# On vérifie que l'utilisateur existe en base de données
@@ -510,23 +360,27 @@ def uploadImage(userId):
abort(404)
user = ret[0]
current_app.logger.debug("Req Headers: {}".format(request.headers))
current_app.logger.debug("Req Files: {}".format(request.files))
current_app.logger.debug("Req data: {}".format(request.data))
# check if the post request has the file part
if 'photo' not in request.files:
logger.error('No file part in the request')
current_app.logger.error('No file part in the request')
abort(400)
try:
photo = request.files['photo']
except RequestEntityTooLarge as e:
logger.error("Fichier trop gros ...")
current_app.logger.error("Fichier trop gros ...")
abort(413)
# If the user does not select a file, the browser submits an empty file without a filename
if photo.filename == '':
logger.error('No selected file')
current_app.logger.error('No selected file')
abort(401)
if photo and allowed_file(photo.filename):
filename = secure_filename(photo.filename)
### DEBUG ###
logger.debug("filename: {}".format(os.path.splitext(filename)))
current_app.logger.debug("filename: {}".format(os.path.splitext(filename)))
### END DEBUG ###
filepath = os.path.join(app.config['UPLOAD_FOLDER'], user['Identifiant'] + os.path.splitext(filename)[1])
photo.save(filepath)
@@ -540,18 +394,3 @@ def uploadImage(userId):
abort(500)
content = jsonify({'message': 'photo saved successfuly!'})
return content
def main():
logger.setLevel(log.DEBUG)
fl = log.StreamHandler()
fl.setLevel(log.DEBUG)
formatter = log.Formatter('%(asctime)s - %(name)s [%(module)s.%(funcName)s:%(lineno)d] - %(levelname)s - %(message)s')
fl.setFormatter(formatter)
logger.addHandler(fl)
app.logger.handlers.clear()
app.logger.addHandler(fl)
app.run(host="0.0.0.0", debug=True)
if __name__ == '__main__':
main()