diff --git a/Pipfile b/Pipfile index d212dcb..6bb7013 100644 --- a/Pipfile +++ b/Pipfile @@ -17,7 +17,7 @@ pytest-integration = "*" iniconfig = "*" [packages] -phi = {editable = true,path = "."} +phi = {editable = true, path = "."} aiohttp = "==3.8.1" click = "8.0" pyYAML = "*" @@ -26,3 +26,7 @@ passlib = "==1.7.1" bcrypt = "==3.2.0" multidict = "*" iniconfig = "*" +aiohttp-session = {version = "==2.11.0", extras = ["secure"]} + +[pipenv] +allow_prereleases = true diff --git a/Pipfile.lock b/Pipfile.lock index 0a926d4..38bacd7 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "eb8c5e35f0ae8527fab69be92ade0ac4999e53bff62ce2848933020ce3e1b2ac" + "sha256": "f2f9eee7ecaf6f2f4bd347f6021acfe9a08f99e1bb7145cf2a2be854efc941b1" }, "pipfile-spec": 6, "requires": {}, @@ -92,6 +92,17 @@ "index": "pypi", "version": "==3.8.1" }, + "aiohttp-session": { + "extras": [ + "secure" + ], + "hashes": [ + "sha256:0fdf39600f6a05c4943ef6c7b099071ca9854413111a26761626244be5015dc4", + "sha256:d5451b72ba748d72ef01f55c3af45b63be2d40b2bdadf47407007e1270343384" + ], + "index": "pypi", + "version": "==2.11.0" + }, "aiosignal": { "hashes": [ "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a", @@ -205,11 +216,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd", - "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455" + "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45", + "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c" ], "markers": "python_full_version >= '3.5.0'", - "version": "==2.0.10" + "version": "==2.0.11" }, "click": { "hashes": [ @@ -219,6 +230,31 @@ "index": "pypi", "version": "==7.0" }, + "cryptography": { + "hashes": [ + "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3", + "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31", + "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac", + "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf", + "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316", + "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca", + "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638", + "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94", + "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12", + "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173", + "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b", + "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a", + "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f", + "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2", + "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9", + "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46", + "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903", + "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3", + "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1", + "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee" + ], + "version": "==36.0.1" + }, "frozenlist": { "hashes": [ "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e", @@ -589,6 +625,17 @@ "index": "pypi", "version": "==3.8.1" }, + "aiohttp-session": { + "extras": [ + "secure" + ], + "hashes": [ + "sha256:0fdf39600f6a05c4943ef6c7b099071ca9854413111a26761626244be5015dc4", + "sha256:d5451b72ba748d72ef01f55c3af45b63be2d40b2bdadf47407007e1270343384" + ], + "index": "pypi", + "version": "==2.11.0" + }, "aiosignal": { "hashes": [ "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a", @@ -738,11 +785,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd", - "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455" + "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45", + "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c" ], "markers": "python_full_version >= '3.5.0'", - "version": "==2.0.10" + "version": "==2.0.11" }, "click": { "hashes": [ @@ -757,53 +804,75 @@ "toml" ], "hashes": [ - "sha256:012157499ec4f135fc36cd2177e3d1a1840af9b236cbe80e9a5ccfc83d912a69", - "sha256:0a34d313105cdd0d3644c56df2d743fe467270d6ab93b5d4a347eb9fec8924d6", - "sha256:11e61c5548ecf74ea1f8b059730b049871f0e32b74f88bd0d670c20c819ad749", - "sha256:152cc2624381df4e4e604e21bd8e95eb8059535f7b768c1fb8b8ae0b26f47ab0", - "sha256:1b4285fde5286b946835a1a53bba3ad41ef74285ba9e8013e14b5ea93deaeafc", - "sha256:27a94db5dc098c25048b0aca155f5fac674f2cf1b1736c5272ba28ead2fc267e", - "sha256:27ac7cb84538e278e07569ceaaa6f807a029dc194b1c819a9820b9bb5dbf63ab", - "sha256:2a491e159294d756e7fc8462f98175e2d2225e4dbe062cca7d3e0d5a75ba6260", - "sha256:2bc85664b06ba42d14bb74d6ddf19d8bfc520cb660561d2d9ce5786ae72f71b5", - "sha256:32168001f33025fd756884d56d01adebb34e6c8c0b3395ca8584cdcee9c7c9d2", - "sha256:3c4ce3b647bd1792d4394f5690d9df6dc035b00bcdbc5595099c01282a59ae01", - "sha256:433b99f7b0613bdcdc0b00cc3d39ed6d756797e3b078d2c43f8a38288520aec6", - "sha256:4578728c36de2801c1deb1c6b760d31883e62e33f33c7ba8f982e609dc95167d", - "sha256:509c68c3e2015022aeda03b003dd68fa19987cdcf64e9d4edc98db41cfc45d30", - "sha256:51372e24b1f7143ee2df6b45cff6a721f3abe93b1e506196f3ffa4155c2497f7", - "sha256:5d008e0f67ac800b0ca04d7914b8501312c8c6c00ad8c7ba17754609fae1231a", - "sha256:649df3641eb351cdfd0d5533c92fc9df507b6b2bf48a7ef8c71ab63cbc7b5c3c", - "sha256:6e78b1e25e5c5695dea012be473e442f7094d066925604be20b30713dbd47f89", - "sha256:72d9d186508325a456475dd05b1756f9a204c7086b07fffb227ef8cee03b1dc2", - "sha256:7d82c610a2e10372e128023c5baf9ce3d270f3029fe7274ff5bc2897c68f1318", - "sha256:7ee317486593193e066fc5e98ac0ce712178c21529a85c07b7cb978171f25d53", - "sha256:7eed8459a2b81848cafb3280b39d7d49950d5f98e403677941c752e7e7ee47cb", - "sha256:823f9325283dc9565ba0aa2d240471a93ca8999861779b2b6c7aded45b58ee0f", - "sha256:85c5fc9029043cf8b07f73fbb0a7ab6d3b717510c3b5642b77058ea55d7cacde", - "sha256:86c91c511853dfda81c2cf2360502cb72783f4b7cebabef27869f00cbe1db07d", - "sha256:8e0c3525b1a182c8ffc9bca7e56b521e0c2b8b3e82f033c8e16d6d721f1b54d6", - "sha256:987a84ff98a309994ca77ed3cc4b92424f824278e48e4bf7d1bb79a63cfe2099", - "sha256:9ed3244b415725f08ca3bdf02ed681089fd95e9465099a21c8e2d9c5d6ca2606", - "sha256:a189036c50dcd56100746139a459f0d27540fef95b09aba03e786540b8feaa5f", - "sha256:a4748349734110fd32d46ff8897b561e6300d8989a494ad5a0a2e4f0ca974fc7", - "sha256:a5d79c9af3f410a2b5acad91258b4ae179ee9c83897eb9de69151b179b0227f5", - "sha256:a7596aa2f2b8fa5604129cfc9a27ad9beec0a96f18078cb424d029fdd707468d", - "sha256:ab4fc4b866b279740e0d917402f0e9a08683e002f43fa408e9655818ed392196", - "sha256:bde4aeabc0d1b2e52c4036c54440b1ad05beeca8113f47aceb4998bb7471e2c2", - "sha256:c72bb4679283c6737f452eeb9b2a0e570acaef2197ad255fb20162adc80bea76", - "sha256:c8582e9280f8d0f38114fe95a92ae8d0790b56b099d728cc4f8a2e14b1c4a18c", - "sha256:ca29c352389ea27a24c79acd117abdd8a865c6eb01576b6f0990cd9a4e9c9f48", - "sha256:ce443a3e6df90d692c38762f108fc4c88314bf477689f04de76b3f252e7a351c", - "sha256:d1675db48490e5fa0b300f6329ecb8a9a37c29b9ab64fa9c964d34111788ca2d", - "sha256:da1a428bdbe71f9a8c270c7baab29e9552ac9d0e0cba5e7e9a4c9ee6465d258d", - "sha256:e4ff163602c5c77e7bb4ea81ba5d3b793b4419f8acd296aae149370902cf4e92", - "sha256:e67ccd53da5958ea1ec833a160b96357f90859c220a00150de011b787c27b98d", - "sha256:e8071e7d9ba9f457fc674afc3de054450be2c9b195c470147fbbc082468d8ff7", - "sha256:fff16a30fdf57b214778eff86391301c4509e327a65b877862f7c929f10a4253" + "sha256:1245ab82e8554fa88c4b2ab1e098ae051faac5af829efdcf2ce6b34dccd5567c", + "sha256:1bc6d709939ff262fd1432f03f080c5042dc6508b6e0d3d20e61dd045456a1a0", + "sha256:25e73d4c81efa8ea3785274a2f7f3bfbbeccb6fcba2a0bdd3be9223371c37554", + "sha256:276b13cc085474e482566c477c25ed66a097b44c6e77132f3304ac0b039f83eb", + "sha256:2aed4761809640f02e44e16b8b32c1a5dee5e80ea30a0ff0912158bde9c501f2", + "sha256:2dd70a167843b4b4b2630c0c56f1b586fe965b4f8ac5da05b6690344fd065c6b", + "sha256:352c68e233409c31048a3725c446a9e48bbff36e39db92774d4f2380d630d8f8", + "sha256:3f2b05757c92ad96b33dbf8e8ec8d4ccb9af6ae3c9e9bd141c7cc44d20c6bcba", + "sha256:448d7bde7ceb6c69e08474c2ddbc5b4cd13c9e4aa4a717467f716b5fc938a734", + "sha256:463e52616ea687fd323888e86bf25e864a3cc6335a043fad6bbb037dbf49bbe2", + "sha256:482fb42eea6164894ff82abbcf33d526362de5d1a7ed25af7ecbdddd28fc124f", + "sha256:56c4a409381ddd7bbff134e9756077860d4e8a583d310a6f38a2315b9ce301d0", + "sha256:56d296cbc8254a7dffdd7bcc2eb70be5a233aae7c01856d2d936f5ac4e8ac1f1", + "sha256:5e15d424b8153756b7c903bde6d4610be0c3daca3986173c18dd5c1a1625e4cd", + "sha256:618eeba986cea7f621d8607ee378ecc8c2504b98b3fdc4952b30fe3578304687", + "sha256:61d47a897c1e91f33f177c21de897267b38fbb45f2cd8e22a710bcef1df09ac1", + "sha256:621f6ea7260ea2ffdaec64fe5cb521669984f567b66f62f81445221d4754df4c", + "sha256:6a5cdc3adb4f8bb8d8f5e64c2e9e282bc12980ef055ec6da59db562ee9bdfefa", + "sha256:6c3f6158b02ac403868eea390930ae64e9a9a2a5bbfafefbb920d29258d9f2f8", + "sha256:704f89b87c4f4737da2860695a18c852b78ec7279b24eedacab10b29067d3a38", + "sha256:72128176fea72012063200b7b395ed8a57849282b207321124d7ff14e26988e8", + "sha256:78fbb2be068a13a5d99dce9e1e7d168db880870f7bc73f876152130575bd6167", + "sha256:7bff3a98f63b47464480de1b5bdd80c8fade0ba2832c9381253c9b74c4153c27", + "sha256:84f2436d6742c01136dd940ee158bfc7cf5ced3da7e4c949662b8703b5cd8145", + "sha256:9976fb0a5709988778ac9bc44f3d50fccd989987876dfd7716dee28beed0a9fa", + "sha256:9ad0a117b8dc2061ce9461ea4c1b4799e55edceb236522c5b8f958ce9ed8fa9a", + "sha256:9e3dd806f34de38d4c01416344e98eab2437ac450b3ae39c62a0ede2f8b5e4ed", + "sha256:9eb494070aa060ceba6e4bbf44c1bc5fa97bfb883a0d9b0c9049415f9e944793", + "sha256:9fde6b90889522c220dd56a670102ceef24955d994ff7af2cb786b4ba8fe11e4", + "sha256:9fff3ff052922cb99f9e52f63f985d4f7a54f6b94287463bc66b7cdf3eb41217", + "sha256:a06c358f4aed05fa1099c39decc8022261bb07dfadc127c08cfbd1391b09689e", + "sha256:a4f923b9ab265136e57cc14794a15b9dcea07a9c578609cd5dbbfff28a0d15e6", + "sha256:c5b81fb37db76ebea79aa963b76d96ff854e7662921ce742293463635a87a78d", + "sha256:d5ed164af5c9078596cfc40b078c3b337911190d3faeac830c3f1274f26b8320", + "sha256:d651fde74a4d3122e5562705824507e2f5b2d3d57557f1916c4b27635f8fbe3f", + "sha256:de73fca6fb403dd72d4da517cfc49fcf791f74eee697d3219f6be29adf5af6ce", + "sha256:e647a0be741edbb529a72644e999acb09f2ad60465f80757da183528941ff975", + "sha256:e92c7a5f7d62edff50f60a045dc9542bf939758c95b2fcd686175dd10ce0ed10", + "sha256:eeffd96882d8c06d31b65dddcf51db7c612547babc1c4c5db6a011abe9798525", + "sha256:f5a4551dfd09c3bd12fca8144d47fe7745275adf3229b7223c2f9e29a975ebda", + "sha256:fac0bcc5b7e8169bffa87f0dcc24435446d329cbc2b5486d155c2e0f3b493ae1" ], "markers": "python_version >= '3.7'", - "version": "==6.3" + "version": "==6.3.1" + }, + "cryptography": { + "hashes": [ + "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3", + "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31", + "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac", + "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf", + "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316", + "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca", + "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638", + "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94", + "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12", + "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173", + "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b", + "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a", + "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f", + "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2", + "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9", + "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46", + "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903", + "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3", + "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1", + "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee" + ], + "version": "==36.0.1" }, "decorator": { "hashes": [ @@ -929,7 +998,7 @@ "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee", "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c" ], - "markers": "python_version >= '3.5'", + "markers": "python_full_version >= '3.5.0'", "version": "==0.1.3" }, "mock": { @@ -1072,11 +1141,11 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:1bb05628c7d87b645974a1bad3f17612be0c29fa39af9f7688030163f680bad6", - "sha256:e56f2ff799bacecd3e88165b1e2f5ebf9bcd59e80e06d395fa0cc4b8bd7bb506" + "sha256:4bcf119be2200c17ed0d518872ef922f1de336eb6d1ddbd1e089ceb6447d97c6", + "sha256:a51d41a6a45fd9def54365bca8f0402c8f182f2b6f7e29c74d55faeb9fb38ac4" ], "markers": "python_full_version >= '3.6.2'", - "version": "==3.0.24" + "version": "==3.0.26" }, "ptyprocess": { "hashes": [ @@ -1112,7 +1181,7 @@ "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65", "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a" ], - "markers": "python_version >= '3.5'", + "markers": "python_full_version >= '3.5.0'", "version": "==2.11.2" }, "pyparsing": { @@ -1125,11 +1194,11 @@ }, "pytest": { "hashes": [ - "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89", - "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134" + "sha256:8fc363e0b7407a9397e660ef81e1634e4504faaeb6ad1d2416da4c38d29a0f45", + "sha256:e1af71303d633af3376130b388e028342815cff74d2f3be4aeb22f3fd94325e6" ], "index": "pypi", - "version": "==6.2.5" + "version": "==7.0.0rc1" }, "pytest-aiohttp": { "hashes": [ @@ -1283,11 +1352,11 @@ }, "setuptools": { "hashes": [ - "sha256:2404879cda71495fc4d5cbc445ed52fdaddf352b36e40be8dcc63147cb4edabe", - "sha256:68eb94073fc486091447fcb0501efd6560a0e5a1839ba249e5ff3c4c93f05f90" + "sha256:b83cf328a4f6a987c95610e76b29a30778db05174eef71f771776c48f8f25d1b", + "sha256:f6871e8aba174d1e22f576c7a471d8460e226b8424b0f2e929a13330b8b83118" ], "markers": "python_version >= '3.7'", - "version": "==60.5.0" + "version": "==60.7.0" }, "six": { "hashes": [ @@ -1317,6 +1386,7 @@ "sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224", "sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1" ], + "markers": "python_version >= '3.7'", "version": "==2.0.0" }, "traitlets": { diff --git a/config.yml b/config.yml index 1162b95..173907c 100644 --- a/config.yml +++ b/config.yml @@ -3,6 +3,8 @@ core: listen: host: 127.0.0.1 port: 8080 + # generated with: openssl rand -hex 16 + cookiestore_secret: "e41133b5cfdd8660815b8d5cc2c74843" ldap: @@ -14,11 +16,12 @@ ldap: validate: False # Can either be True or False. Default: False ca_certs: openldap/cert.pem - username: uid=phi,ou=Services,dc=unit,dc=macaomilano,dc=org - password: phi + # username: uid=phi,ou=Services,dc=unit,dc=macaomilano,dc=org + # password: phi + # username: cn=root,dc=unit,dc=macaomilano,dc=org + # password: root base_dn: dc=unit,dc=macaomilano,dc=org - attribute_id: uid logging: diff --git a/integration_tests/test_model.py b/integration_tests/test_model.py index 04ca9e3..767ed8d 100644 --- a/integration_tests/test_model.py +++ b/integration_tests/test_model.py @@ -11,7 +11,7 @@ from phi.async_ldap.model import ( Robots, Service, Group, - Congregations, + Roles, ) from phi.async_ldap.mixins import build_heritage from phi.async_ldap.client import AsyncClient @@ -36,7 +36,7 @@ cl = AsyncClient( async def clean_db(): h = Hackers(cl) r = Robots(cl) - c = Congregations(cl) + c = Roles(cl) h.delete_cascade = True r.delete_cascade = True c.delete_cascade = True @@ -227,7 +227,7 @@ async def test_Group_init(): u = await init_achilles() g = await init_group("achaeans", [u]) - c = Congregations(cl) + c = Roles(cl) res = await c.search("achaeans") @@ -246,9 +246,9 @@ async def test_Group_describe(): res = await g.describe() assert res == { - "ou": "Congregations", + "ou": "Roles", "cn": "achaeans", - "dn": f"cn=achaeans,ou=Congregations,{BASE_DN}", + "dn": f"cn=achaeans,ou=Roles,{BASE_DN}", "member": [u1.dn, u2.dn], } diff --git a/openldap/init.ldif b/openldap/init.ldif index f7bfe91..a0d901a 100644 --- a/openldap/init.ldif +++ b/openldap/init.ldif @@ -16,10 +16,10 @@ objectClass: top objectClass: organizationalUnit ou: Robots -dn: ou=Congregations,dc=unit,dc=macaomilano,dc=org +dn: ou=Roles,dc=unit,dc=macaomilano,dc=org objectClass: top objectClass: organizationalUnit -ou: Congregations +ou: Roles dn: uid=phi,ou=Robots,dc=unit,dc=macaomilano,dc=org objectClass: account @@ -47,9 +47,9 @@ objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: person objectClass: top -memberOf: cn=Admins,ou=Congregations,dc=unit,dc=macaomilano,dc=org -memberOf: cn=GitUsers,ou=Congregations,dc=unit,dc=macaomilano,dc=org -memberOf: cn=IRCUsers,ou=Congregations,dc=unit,dc=macaomilano,dc=org +memberOf: cn=Admins,ou=Roles,dc=unit,dc=macaomilano,dc=org +memberOf: cn=GitUsers,ou=Roles,dc=unit,dc=macaomilano,dc=org +memberOf: cn=IRCUsers,ou=Roles,dc=unit,dc=macaomilano,dc=org cn: Raffaello sn: Mascetti mail: rmascetti@autistici.org @@ -61,8 +61,8 @@ objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: person objectClass: top -memberOf: cn=GitUsers,ou=Congregations,dc=unit,dc=macaomilano,dc=org -memberOf: cn=IRCUsers,ou=Congregations,dc=unit,dc=macaomilano,dc=org +memberOf: cn=GitUsers,ou=Roles,dc=unit,dc=macaomilano,dc=org +memberOf: cn=IRCUsers,ou=Roles,dc=unit,dc=macaomilano,dc=org cn: Guido sn: Necchi mail: gnecchi@autistici.org @@ -74,20 +74,20 @@ objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: person objectClass: top -memberOf: cn=GitUsers,ou=Congregations,dc=unit,dc=macaomilano,dc=org +memberOf: cn=GitUsers,ou=Roles,dc=unit,dc=macaomilano,dc=org cn: Giorgio sn: Perozzi mail: gperozzi@autistici.org uid: perozzi userPassword: {SHA}0+CRQKqsTj1I82PHxvZ4ebbddXQ= -dn: cn=Admins,ou=Congregations,dc=unit,dc=macaomilano,dc=org +dn: cn=Admins,ou=Roles,dc=unit,dc=macaomilano,dc=org member: uid=conte_mascetti,ou=Hackers,dc=unit,dc=macaomilano,dc=org cn: Admins objectClass: groupOfNames objectClass: top -dn: cn=GitUsers,ou=Congregations,dc=unit,dc=macaomilano,dc=org +dn: cn=GitUsers,ou=Roles,dc=unit,dc=macaomilano,dc=org member: uid=conte_mascetti,ou=Hackers,dc=unit,dc=macaomilano,dc=org member: uid=necchi,ou=Hackers,dc=unit,dc=macaomilano,dc=org member: uid=perozzi,ou=Hackers,dc=unit,dc=macaomilano,dc=org @@ -95,7 +95,7 @@ cn: GitUsers objectClass: groupOfNames objectClass: top -dn: cn=IRCUsers,ou=Congregations,dc=unit,dc=macaomilano,dc=org +dn: cn=IRCUsers,ou=Roles,dc=unit,dc=macaomilano,dc=org member: uid=conte_mascetti,ou=Hackers,dc=unit,dc=macaomilano,dc=org member: uid=necchi,ou=Hackers,dc=unit,dc=macaomilano,dc=org cn: IRCUsers diff --git a/setup.py b/setup.py index 9048f19..de1939f 100644 --- a/setup.py +++ b/setup.py @@ -10,10 +10,11 @@ setup( author_email="unit@paranoici.org", package_dir={"": "src"}, packages=find_packages("src"), - entry_points={"console_scripts": ["phid=phi.app:cli"]}, + entry_points={"console_scripts": ["phid=phi.web.app:cli"]}, setup_requires=["pytest-runner"], install_requires=[ "aiohttp==3.8.1", + "aiohttp_session[secure]==2.11.0", "click==7.0", "pyYAML", "bonsai==1.3.0", diff --git a/src/phi/api/app.py b/src/phi/api/app.py index 4f0af82..23a5fd5 100644 --- a/src/phi/api/app.py +++ b/src/phi/api/app.py @@ -2,24 +2,19 @@ from aiohttp import web from phi.logging import get_logger -from phi.async_ldap.client import AsyncClient -from phi.async_ldap.model import Hackers, Robots, Congregations from phi.api.routes import api_routes +from phi.web.auth_middleware import authenticated log = get_logger(__name__) -def api_app(config): +def api_app(store): log.info("Initializing API sub-app.") - app = web.Application() + app = web.Application(middlewares=[authenticated]) - ldap_client = AsyncClient(**config.get("ldap", {})) - app["ldap_client"] = ldap_client - app["users"] = Hackers(ldap_client) - app["services"] = Robots(ldap_client) - app["groups"] = Congregations(ldap_client) + app["store"] = store app["log"] = log app.router.add_routes(api_routes) diff --git a/src/phi/api/rest.py b/src/phi/api/rest.py index 2cee299..4a6652a 100644 --- a/src/phi/api/rest.py +++ b/src/phi/api/rest.py @@ -9,8 +9,8 @@ from aiohttp.web import ( ) from phi.logging import get_logger -from phi.api.utils import serialize -from phi.async_ldap.model import Hackers, User +# from phi.api.utils import serialize +from phi.async_ldap.model import User from phi.exceptions import ( PhiEntryDoesNotExist, PhiUnexpectedRuntimeValue, diff --git a/src/phi/api/routes.py b/src/phi/api/routes.py index 9d092b0..39654c0 100644 --- a/src/phi/api/routes.py +++ b/src/phi/api/routes.py @@ -1,9 +1,9 @@ -from aiohttp.web import route +from aiohttp.web import view from phi.api.rest import UserView api_routes = [ - route("*", "/user", UserView), - route("*", "/user/", UserView), - route("*", "/user/{uid}", UserView), + view("/user", UserView), + view("/user/", UserView), + view("/user/{uid}", UserView), ] diff --git a/src/phi/async_ldap/client.py b/src/phi/async_ldap/client.py index 219d42d..ac63b03 100644 --- a/src/phi/async_ldap/client.py +++ b/src/phi/async_ldap/client.py @@ -86,7 +86,7 @@ class AsyncClient(LDAPClient): host=None, port=None, encryption=None, - cyphers=None, + ciphers=None, validate=False, ca_cert=None, username=None, @@ -130,3 +130,6 @@ class AsyncClient(LDAPClient): self.set_auto_page_acquire(True) self.set_credentials(self.method, user=self.username, password=self.password) + + def __repr__(self): + return f"AsyncClient[{self.full_uri}]<{self.username}>" diff --git a/src/phi/async_ldap/model.py b/src/phi/async_ldap/model.py index acf26e6..13c194f 100644 --- a/src/phi/async_ldap/model.py +++ b/src/phi/async_ldap/model.py @@ -84,7 +84,7 @@ class Group(mixins.Member, mixins.Entry, mixins.Singleton): object_class = ["groupOfNames", "top"] _instances = dict() # type: ignore id_tag = "cn" - ou = "Congregations" + ou = "Roles" ldap_attributes = ["cn", "ou", "member"] memeber_classes = {"Hackers": User, "Robots": Service} empty = False @@ -110,9 +110,9 @@ class Group(mixins.Member, mixins.Entry, mixins.Singleton): yield self.memeber_classes.get(dn["ou"])(self.client, dn["uid"]) -class Congregations(mixins.OrganizationalUnit, mixins.Entry, mixins.Singleton): +class Roles(mixins.OrganizationalUnit, mixins.Entry, mixins.Singleton): _instances = dict() # type: ignore - ou = "Congregations" + ou = "Roles" child_class = Group diff --git a/src/phi/config.py b/src/phi/config.py index 269d38e..01dead5 100644 --- a/src/phi/config.py +++ b/src/phi/config.py @@ -5,7 +5,7 @@ import yaml NAME = "phi" DEFAULT_CONFIG = { - "core": {"listen": {"host": "localhost", "port": 8080}}, + "core": {"listen": {"host": "localhost", "port": 8080}, "cookiestore_secret": None}, "ldap": { "host": "localhost", "port": 389, @@ -13,10 +13,7 @@ DEFAULT_CONFIG = { "ciphers": "HIGH", "validate": True, "ca_certs": pkg_resources.resource_filename(NAME, "openldap/cert.pem"), - "username": None, - "password": None, "base_dn": None, - "attribute_id": "uid", "attribute_mail": "mail", }, "logging": { @@ -35,9 +32,18 @@ DEFAULT_CONFIG = { }, }, "loggers": { - "phi": {"level": "INFO", "handlers": ["console", "file"],}, - "aiohttp": {"level": "INFO", "handlers": ["console", "file"],}, - "bonsai": {"level": "WARNING", "handlers": ["console", "file"],}, + "phi": { + "level": "INFO", + "handlers": ["console", "file"], + }, + "aiohttp": { + "level": "INFO", + "handlers": ["console", "file"], + }, + "bonsai": { + "level": "WARNING", + "handlers": ["console", "file"], + }, }, }, } @@ -123,3 +129,16 @@ def recursive_merge(main_config, aux_config): _recursive_merge(main_config, aux_config, DEFAULT_CONFIG, "ROOT", _config) return _config["ROOT"] + + +def extract_secret(config): + try: + secret = config["core"]["cookiestore_secret"].encode("utf-8") + if len(secret) != 32: + raise ValueError( + "The provided core.cookiestore_secret must be 32 bytes long" + ) + + return secret + except KeyError: + raise RuntimeError("You must provide a core.cookiestore_secret") diff --git a/src/phi/app.py b/src/phi/web/app.py similarity index 88% rename from src/phi/app.py rename to src/phi/web/app.py index 2e95c08..aec3b7b 100644 --- a/src/phi/app.py +++ b/src/phi/web/app.py @@ -1,23 +1,34 @@ # -*- encoding: utf-8 -*- -import pkg_resources - from aiohttp import web +from aiohttp_session import setup +from aiohttp_session.cookie_storage import EncryptedCookieStorage import click from pprint import pformat as pp import yaml -from phi.config import get_config, merge_config +from phi.config import get_config, merge_config, extract_secret from phi.logging import setup_logging, get_logger from phi.api.app import api_app +from phi.web.client_store import ClientStore +from phi.web.login import login log = get_logger(__name__) +LOGIN_ROUTE = "/login" + + def setup_app(config): app = web.Application() - app["config"] = config + setup(app, EncryptedCookieStorage(extract_secret(config))) - api = api_app(config) + app["config"] = config + app["store"] = ClientStore(LOGIN_ROUTE) + app["log"] = log + + app.add_routes([web.post(LOGIN_ROUTE, login)]) + + api = api_app(app["store"]) app.add_subapp("/api", api) return app @@ -109,7 +120,11 @@ def run_app(app): help="Path to a yaml configuration for the logger.", ) @click.option( - "--debug", "debug", is_flag=True, default=False, help="Set the log level to debug.", + "--debug", + "debug", + is_flag=True, + default=False, + help="Set the log level to debug.", ) def cli( host, @@ -141,6 +156,7 @@ def cli( debug, ) config_file, file_config = get_config(config_path) + log.debug(f"FILE: {pp(file_config)}") config = merge_config(cli_config, file_config) if debug: set_to_debug(config) diff --git a/src/phi/web/auth_middleware.py b/src/phi/web/auth_middleware.py new file mode 100644 index 0000000..b4f4d6d --- /dev/null +++ b/src/phi/web/auth_middleware.py @@ -0,0 +1,23 @@ +# -*- encoding: utf-8 -*- +from aiohttp.web import middleware, HTTPFound + +from phi.web import app +from phi.async_ldap.model import Hackers, Robots, Roles + + +@middleware +async def authenticated(request, handler): + try: + store = request.app["store"] + except KeyError: + raise HTTPFound(app.LOGIN_ROUTE) + + client = await store.get_client(request) + + request.app["ldap_client"] = client + request.app["users"] = Hackers(client) + request.app["services"] = Robots(client) + request.app["groups"] = Roles(client) + resp = await handler(request) + + return resp diff --git a/src/phi/web/client_store.py b/src/phi/web/client_store.py new file mode 100644 index 0000000..a3c072b --- /dev/null +++ b/src/phi/web/client_store.py @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- +import secrets + +from aiohttp.web import HTTPFound +from aiohttp_session import get_session + + +class ClientStore(dict): + """ + This class is responsible to hold the clients used by the active connections. + """ + + def __init__(self, login_route): + self.login_route = login_route + self.store = dict() + + async def get_client(self, request): + session = await get_session(request) + client_id = session.get("client_id") + if client_id is None: + raise HTTPFound(self.login_route) + + client = self.store.get(client_id) + if client is None: + raise HTTPFound(self.login_route) + + return client + + async def set_client(self, request, client): + session = await get_session(request) + + client_id = secrets.token_hex(16) + + self.store[client_id] = client + session["client_id"] = client_id diff --git a/src/phi/web/login.py b/src/phi/web/login.py new file mode 100644 index 0000000..961e22a --- /dev/null +++ b/src/phi/web/login.py @@ -0,0 +1,38 @@ +# -*- encoding: utf-8 -*- +from aiohttp.web import HTTPBadRequest, HTTPOk + +from phi.async_ldap.client import AsyncClient + + +async def login(request): + log = request.app["log"] + log.debug("login") + + store = request.app["store"] + config = request.app["config"] + + body = await request.json() + + tag = body.get("tag", "uid") + + ou = body.get("ou") + if ou is not None: + config["ldap"]["ou"] = ou + + try: + user = body["user"] + password = body["password"] + except KeyError as e: + text = f"Missing key: {e}" + log.warn(text) + raise HTTPBadRequest(text=text) + + client = AsyncClient( + attribute_id=tag, username=user, password=password, **config.get("ldap") + ) + + log.debug(f"Client: {client}") + + await store.set_client(request, client) + + raise HTTPOk diff --git a/test/aux_async_model.py b/test/aux_async_model.py index c6e185a..36fabb8 100644 --- a/test/aux_async_model.py +++ b/test/aux_async_model.py @@ -9,7 +9,7 @@ from phi.async_ldap.model import ( Robots, Service, Group, - Congregations, + Roles, ) from phi.async_ldap.mixins import build_heritage from phi.async_ldap.client import AsyncClient @@ -36,7 +36,7 @@ cl = AsyncClient( async def get_all_children(): h = Hackers(cl) r = Robots(cl) - g = Congregations(cl) + g = Roles(cl) hackers = await dlv(h, User) robots = await dlv(r, Service) @@ -69,7 +69,7 @@ def sync_await(awaitable): h = Hackers(cl) r = Robots(cl) -c = Congregations(cl) +c = Roles(cl) # asyncio.run(print_async("hackers:", describe(h))) @@ -81,7 +81,7 @@ c = Congregations(cl) # asyncio.run(print_async("Hackers members:", get_members(h))) # asyncio.run(print_async("Robots members:", get_members(r))) -# asyncio.run(print_async("Congregations members:", get_members(c))) +# asyncio.run(print_async("Roles members:", get_members(c))) # async def add_new(obj, name, **kw): @@ -139,17 +139,17 @@ async def remove_member(group, member): # asyncio.run(print_async("Robots members:", get_members(r))) asyncio.run(safe_search(c, "GitUsers")) -asyncio.run(print_async("Congregations members:", get_members(c))) +asyncio.run(print_async("Roles members:", get_members(c))) asyncio.run( add_new(Group, "naughty", member=[User(cl, "conte_mascetti"), User(cl, "necchi")]) ) -asyncio.run(print_async("Congregations members:", get_members(c))) +asyncio.run(print_async("Roles members:", get_members(c))) asyncio.run(safe_delete(Group(cl, "naughty"))) -asyncio.run(print_async("Congregations members:", get_members(c))) +asyncio.run(print_async("Roles members:", get_members(c))) asyncio.run( add_new(Group, "naughty", member=[User(cl, "conte_mascetti"), User(cl, "necchi")]) ) -asyncio.run(print_async("Congregations members:", get_members(c))) +asyncio.run(print_async("Roles members:", get_members(c))) print("==> HERE <==") naughty = sync_await(Group(cl, "naughty").sync()) print("NAUGHTY =>>", [m for m in naughty.get_members()])