diff --git a/Pipfile b/Pipfile index fd917b1..d10a323 100644 --- a/Pipfile +++ b/Pipfile @@ -26,10 +26,13 @@ msal = "*" okta = "*" asyncio = "*" onelogin = "*" +google-api-python-client = "*" +google-auth-oauthlib = "*" certifi = "*" setuptools = "*" cryptography = "*" werkzeug = "*" +importlib-metadata = "*" [pipenv] allow_prereleases = false diff --git a/Pipfile.lock b/Pipfile.lock index 6232c0a..3b9f874 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,22 +1,28 @@ { "_meta": { "hash": { - "sha256": "d0b711fd630097c1e79141ad687786fa047dca222a8b1f1e4dc0347ef80742d0" + "sha256": "8a037c60558ff243346d1306715a6de10d66e3d28785f6ff42f2c1aa878378a2" }, "pipfile-spec": 6, - "requires": {"python_version": "3.9"}, + "requires": { + "python_version": "3.9" + }, "sources": [ - {"name": "pypi", "url": "https://pypi.org/simple", "verify_ssl": true} - ], + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] }, "default": { "aenum": { "hashes": [ "sha256:27b1710b9d084de6e2e695dab78fe9f269de924b51ae2850170ee7e1ca6288a5", "sha256:8cbd76cd18c4f870ff39b24284d3ea028fbe8731a58df3aa581e434c575b9559", - "sha256:e0dfaeea4c2bd362144b87377e2c61d91958c5ed0b4daf89cb6f45ae23af6288", + "sha256:e0dfaeea4c2bd362144b87377e2c61d91958c5ed0b4daf89cb6f45ae23af6288" ], - "version": "==3.1.15", + "version": "==3.1.15" }, "aiohttp": { "hashes": [ @@ -106,68 +112,76 @@ "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced", "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28", "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8", - "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824", + "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824" ], "markers": "python_version >= '3.6'", - "version": "==3.8.5", + "version": "==3.8.5" }, "aiosignal": { "hashes": [ "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", - "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17", + "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" ], "markers": "python_version >= '3.7'", - "version": "==1.3.1", + "version": "==1.3.1" }, "apscheduler": { "hashes": [ "sha256:1611d207b095ff52d97884e90736c192bdd94dbd44ce27eb92c3f1da24a400d3", - "sha256:3f17fd3915f14f4bfa597f552130a14a9d1cc74a002fa1d95dd671cb48dba70e", + "sha256:3f17fd3915f14f4bfa597f552130a14a9d1cc74a002fa1d95dd671cb48dba70e" ], "index": "pypi", - "version": "==3.10.3", + "version": "==3.10.3" }, "async-timeout": { "hashes": [ "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", - "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028", + "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" ], "markers": "python_version >= '3.7'", - "version": "==4.0.3", + "version": "==4.0.3" }, "asyncio": { "hashes": [ "sha256:83360ff8bc97980e4ff25c964c7bd3923d333d177aa4f7fb736b019f26c7cb41", "sha256:b62c9157d36187eca799c378e572c969f0da87cd5fc42ca372d92cdb06e7e1de", "sha256:c46a87b48213d7464f22d9a497b9eef8c1928b68320a2fa94240f969f6fec08c", - "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d", + "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d" ], "index": "pypi", - "version": "==3.4.3", + "version": "==3.4.3" }, "attrs": { "hashes": [ "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", - "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015", + "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" ], "markers": "python_version >= '3.7'", - "version": "==23.1.0", + "version": "==23.1.0" }, "blinker": { "hashes": [ "sha256:4afd3de66ef3a9f8067559fb7a1cbe555c17dcbe15971b05d1b625c3e7abe213", - "sha256:c3d739772abb7bc2860abf5f2ec284223d9ad5c76da018234f6f50d6f31ab1f0", + "sha256:c3d739772abb7bc2860abf5f2ec284223d9ad5c76da018234f6f50d6f31ab1f0" ], "markers": "python_version >= '3.7'", - "version": "==1.6.2", + "version": "==1.6.2" + }, + "cachetools": { + "hashes": [ + "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590", + "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b" + ], + "markers": "python_version >= '3.7'", + "version": "==5.3.1" }, "certifi": { "hashes": [ "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082", - "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9", + "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9" ], "index": "pypi", - "version": "==2023.7.22", + "version": "==2023.7.22" }, "cffi": { "hashes": [ @@ -234,9 +248,9 @@ "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", - "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0", + "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" ], - "version": "==1.15.1", + "version": "==1.15.1" }, "charset-normalizer": { "hashes": [ @@ -314,18 +328,18 @@ "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1", "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c", "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac", - "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa", + "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.2.0", + "version": "==3.2.0" }, "click": { "hashes": [ - "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd", - "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5", + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" ], "markers": "python_version >= '3.7'", - "version": "==8.1.6", + "version": "==8.1.7" }, "cryptography": { "hashes": [ @@ -351,32 +365,32 @@ "sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1", "sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c", "sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e", - "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de", + "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de" ], "index": "pypi", - "version": "==41.0.3", + "version": "==41.0.3" }, "ecdsa": { "hashes": [ "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49", - "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd", + "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", - "version": "==0.18.0", + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.18.0" }, "flask": { "hashes": [ "sha256:77fd4e1249d8c9923de34907236b747ced06e5467ecac1a7bb7115ae0e9670b0", - "sha256:8c2f9abd47a9e8df7f0c3f091ce9497d011dc3b31effcf4c85a6e2b50f4114ef", + "sha256:8c2f9abd47a9e8df7f0c3f091ce9497d011dc3b31effcf4c85a6e2b50f4114ef" ], "index": "pypi", - "version": "==2.3.2", + "version": "==2.3.2" }, "flatdict": { "hashes": [ "sha256:cd32f08fd31ed21eb09ebc76f06b6bd12046a24f77beb1fd0281917e47f26742" ], - "version": "==4.0.1", + "version": "==4.0.1" }, "frozendict": { "hashes": [ @@ -416,10 +430,10 @@ "sha256:f0f573dc4861dd7ec9e055c8cceaf45355e894e749f621f199aab7b311ac4bdb", "sha256:f2a4e818ac457f6354401dcb631527af25e5a20fcfc81e6b5054b45fc245caca", "sha256:f83fed36497af9562ead5e9fb8443224ba2781786bd3b92b1087cb7d0ff20135", - "sha256:ffc684773de7c88724788fa9787d0016fd75830412d58acbd9ed1a04762c675b", + "sha256:ffc684773de7c88724788fa9787d0016fd75830412d58acbd9ed1a04762c675b" ], "markers": "python_version >= '3.6'", - "version": "==2.3.8", + "version": "==2.3.8" }, "frozenlist": { "hashes": [ @@ -483,50 +497,105 @@ "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f", "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3", "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1", - "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e", + "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e" ], "markers": "python_version >= '3.8'", - "version": "==1.4.0", + "version": "==1.4.0" }, "github3.py": { "hashes": [ "sha256:30d571076753efc389edc7f9aaef338a4fcb24b54d8968d5f39b1342f45ddd36", - "sha256:a89af7de25650612d1da2f0609622bcdeb07ee8a45a1c06b2d16a05e4234e753", + "sha256:a89af7de25650612d1da2f0609622bcdeb07ee8a45a1c06b2d16a05e4234e753" ], "index": "pypi", - "version": "==4.0.1", + "version": "==4.0.1" + }, + "google-api-core": { + "hashes": [ + "sha256:25d29e05a0058ed5f19c61c0a78b1b53adea4d9364b464d014fbda941f6d1c9a", + "sha256:d92a5a92dc36dd4f4b9ee4e55528a90e432b059f93aee6ad857f9de8cc7ae94a" + ], + "markers": "python_version >= '3.7'", + "version": "==2.11.1" + }, + "google-api-python-client": { + "hashes": [ + "sha256:48277291894876a1ca7ed4127e055e81f81e6343ced1b544a7200ae2c119dcd7", + "sha256:5215f4cd577753fc4192ccfbe0bb8b55d4bb5fd68fa6268ac5cf271b6305de31" + ], + "index": "pypi", + "version": "==2.97.0" + }, + "google-auth": { + "hashes": [ + "sha256:164cba9af4e6e4e40c3a4f90a1a6c12ee56f14c0b4868d1ca91b32826ab334ce", + "sha256:d61d1b40897407b574da67da1a833bdc10d5a11642566e506565d1b1a46ba873" + ], + "markers": "python_version >= '3.6'", + "version": "==2.22.0" + }, + "google-auth-httplib2": { + "hashes": [ + "sha256:31e49c36c6b5643b57e82617cb3e021e3e1d2df9da63af67252c02fa9c1f4a10", + "sha256:a07c39fd632becacd3f07718dfd6021bf396978f03ad3ce4321d060015cc30ac" + ], + "version": "==0.1.0" + }, + "google-auth-oauthlib": { + "hashes": [ + "sha256:95880ca704928c300f48194d1770cf5b1462835b6e49db61445a520f793fd5fb", + "sha256:e375064964820b47221a7e1b7ee1fd77051b6323c3f9e3e19785f78ab67ecfc5" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "googleapis-common-protos": { + "hashes": [ + "sha256:69f9bbcc6acde92cab2db95ce30a70bd2b81d20b12eff3f1aabaffcbe8a93918", + "sha256:e73ebb404098db405ba95d1e1ae0aa91c3e15a71da031a2eeb6b2e23e7bc3708" + ], + "markers": "python_version >= '3.7'", + "version": "==1.60.0" + }, + "httplib2": { + "hashes": [ + "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc", + "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.22.0" }, "idna": { "hashes": [ "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2", + "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" ], "markers": "python_version >= '3.5'", - "version": "==3.4", + "version": "==3.4" }, "importlib-metadata": { "hashes": [ "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb", - "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743", + "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743" ], - "markers": "python_version < '3.10'", - "version": "==6.8.0", + "index": "pypi", + "version": "==6.8.0" }, "itsdangerous": { "hashes": [ "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", - "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a", + "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a" ], "markers": "python_version >= '3.7'", - "version": "==2.1.2", + "version": "==2.1.2" }, "jinja2": { "hashes": [ "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", - "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61", + "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" ], "markers": "python_version >= '3.7'", - "version": "==3.1.2", + "version": "==3.1.2" }, "ldap3": { "hashes": [ @@ -534,10 +603,10 @@ "sha256:5630d1383e09ba94839e253e013f1aa1a2cf7a547628ba1265cb7b9a844b5687", "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70", "sha256:5ab7febc00689181375de40c396dcad4f2659cd260fc5e94c508b6d77c17e9d5", - "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f", + "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f" ], "index": "pypi", - "version": "==2.9.1", + "version": "==2.9.1" }, "markupsafe": { "hashes": [ @@ -590,18 +659,18 @@ "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", - "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2", + "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2" ], "markers": "python_version >= '3.7'", - "version": "==2.1.3", + "version": "==2.1.3" }, "msal": { "hashes": [ "sha256:25c9a33acf84301f93d1fdbe9f1a9c60cd38af0d5fffdbfa378138fc7bc1e86b", - "sha256:3342e0837a047007f9d479e814b559c3219767453d57920dc40a31986862048b", + "sha256:3342e0837a047007f9d479e814b559c3219767453d57920dc40a31986862048b" ], "index": "pypi", - "version": "==1.23.0", + "version": "==1.23.0" }, "multidict": { "hashes": [ @@ -678,41 +747,76 @@ "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171", "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf", "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d", - "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba", + "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba" ], "markers": "python_version >= '3.7'", - "version": "==6.0.4", + "version": "==6.0.4" + }, + "oauthlib": { + "hashes": [ + "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", + "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918" + ], + "markers": "python_version >= '3.6'", + "version": "==3.2.2" }, "okta": { "hashes": [ "sha256:47e28d04dc99afcc90e2aa151612e9e1f435ecc2b23d9e3a3843f2cc6e6b11de", - "sha256:91bceaae2c9bccdffceafa2fdd0fa41f6963f6994ad46cd63e573f35cfe7585d", + "sha256:91bceaae2c9bccdffceafa2fdd0fa41f6963f6994ad46cd63e573f35cfe7585d" ], "index": "pypi", - "version": "==2.9.2", + "version": "==2.9.2" }, "onelogin": { "hashes": [ "sha256:20228a6e0bb66f4aafe06e43293b6052e7b42f9066ac65babce1f14abb006245", - "sha256:e32e828f66461c8ae82bd7fd6a2d33c53c0f525884d737b759eae4b2a30a239b", + "sha256:e32e828f66461c8ae82bd7fd6a2d33c53c0f525884d737b759eae4b2a30a239b" ], "index": "pypi", - "version": "==3.1.6", + "version": "==3.1.6" + }, + "protobuf": { + "hashes": [ + "sha256:44825e963008f8ea0d26c51911c30d3e82e122997c3c4568fd0385dd7bacaedf", + "sha256:567fe6b0647494845d0849e3d5b260bfdd75692bf452cdc9cb660d12457c055d", + "sha256:5ab19ee50037d4b663c02218a811a5e1e7bb30940c79aac385b96e7a4f9daa61", + "sha256:5d0ceb9de6e08311832169e601d1fc71bd8e8c779f3ee38a97a78554945ecb85", + "sha256:6c817cf4a26334625a1904b38523d1b343ff8b637d75d2c8790189a4064e51c3", + "sha256:81cb9c4621d2abfe181154354f63af1c41b00a4882fb230b4425cbaed65e8f52", + "sha256:82e6e9ebdd15b8200e8423676eab38b774624d6a1ad696a60d86a2ac93f18201", + "sha256:8bb52a2be32db82ddc623aefcedfe1e0eb51da60e18fcc908fb8885c81d72109", + "sha256:a38400a692fd0c6944c3c58837d112f135eb1ed6cdad5ca6c5763336e74f1a04", + "sha256:a6b1ca92ccabfd9903c0c7dde8876221dc7d8d87ad5c42e095cc11b15d3569c7", + "sha256:ae7a1835721086013de193311df858bc12cd247abe4ef9710b715d930b95b33e", + "sha256:ae97b5de10f25b7a443b40427033e545a32b0e9dda17bcd8330d70033379b3e5", + "sha256:e8834ef0b4c88666ebb7c7ec18045aa0f4325481d724daa624a4cf9f28134653" + ], + "markers": "python_version >= '3.7'", + "version": "==4.24.0" }, "pyasn1": { "hashes": [ "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57", - "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde", + "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==0.5.0", + "version": "==0.5.0" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c", + "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==0.3.0" }, "pycparser": { "hashes": [ "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", - "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" ], - "version": "==2.21", + "version": "==2.21" }, "pycryptodomex": { "hashes": [ @@ -747,57 +851,67 @@ "sha256:d84e105787f5e5d36ec6a581ff37a1048d12e638688074b2a00bcf402f9aa1c2", "sha256:e00a4bacb83a2627e8210cb353a2e31f04befc1155db2976e5e239dd66482278", "sha256:f237278836dda412a325e9340ba2e6a84cb0f56b9244781e5b61f10b3905de88", - "sha256:f9ab5ef0718f6a8716695dea16d83b671b22c45e9c0c78fd807c32c0192e54b5", + "sha256:f9ab5ef0718f6a8716695dea16d83b671b22c45e9c0c78fd807c32c0192e54b5" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==3.18.0", + "version": "==3.18.0" }, "pydash": { "hashes": [ "sha256:10e506935953fde4b0d6fe21a88e17783cd1479256ae96f285b5f89063b4efd6", - "sha256:7d9df7e9f36f2bbb08316b609480e7c6468185473a21bdd8e65dda7915565a26", + "sha256:7d9df7e9f36f2bbb08316b609480e7c6468185473a21bdd8e65dda7915565a26" ], "markers": "python_version >= '3.7'", - "version": "==7.0.6", + "version": "==7.0.6" }, "pyjwt": { - "extras": ["crypto"], + "extras": [ + "crypto" + ], "hashes": [ "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de", - "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320", + "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320" ], "markers": "python_version >= '3.7'", - "version": "==2.8.0", + "version": "==2.8.0" + }, + "pyparsing": { + "hashes": [ + "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb", + "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db" + ], + "markers": "python_version >= '3.1'", + "version": "==3.1.1" }, "python-dateutil": { "hashes": [ "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", - "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02", + "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==2.7.5", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.7.5" }, "python-dotenv": { "hashes": [ "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba", - "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a", + "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a" ], "index": "pypi", - "version": "==1.0.0", + "version": "==1.0.0" }, "python-jose": { "hashes": [ "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a", - "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a", + "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a" ], - "version": "==3.3.0", + "version": "==3.3.0" }, "pytz": { "hashes": [ "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", - "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb", + "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb" ], - "version": "==2023.3", + "version": "==2023.3" }, "pyyaml": { "hashes": [ @@ -840,90 +954,98 @@ "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" ], "index": "pypi", - "version": "==6.0.1", + "version": "==6.0.1" }, "requests": { "hashes": [ "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1", + "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" ], "markers": "python_version >= '3.7'", - "version": "==2.31.0", + "version": "==2.31.0" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", + "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.3.1" }, "rsa": { "hashes": [ "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7", - "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21", + "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21" ], "markers": "python_version >= '3.6' and python_version < '4'", - "version": "==4.9", + "version": "==4.9" }, "setuptools": { "hashes": [ "sha256:d59c97e7b774979a5ccb96388efc9eb65518004537e85d52e81eaee89ab6dd91", - "sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715", + "sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715" ], "index": "pypi", - "version": "==68.1.0", + "version": "==68.1.0" }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==1.16.0", + "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:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", - "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6", + "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" ], "markers": "python_version >= '3.7'", - "version": "==4.3.0", + "version": "==4.3.0" }, "tzlocal": { "hashes": [ "sha256:46eb99ad4bdb71f3f72b7d24f4267753e240944ecfc16f25d2719ba89827a803", - "sha256:f3596e180296aaf2dbd97d124fe76ae3a0e3d32b258447de7b939b3fd4be992f", + "sha256:f3596e180296aaf2dbd97d124fe76ae3a0e3d32b258447de7b939b3fd4be992f" ], "markers": "python_version >= '3.7'", - "version": "==5.0.1", + "version": "==5.0.1" }, "uritemplate": { "hashes": [ "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", - "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e", + "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e" ], "markers": "python_version >= '3.6'", - "version": "==4.1.1", + "version": "==4.1.1" }, "urllib3": { "hashes": [ "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f", - "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14", + "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.16", + "version": "==1.26.16" }, "werkzeug": { "hashes": [ "sha256:2b8c0e447b4b9dbcc85dd97b6eeb4dcbaf6c8b6c3be0bd654e25553e0a2157d8", - "sha256:effc12dba7f3bd72e605ce49807bbe692bd729c3bb122a3b91747a6ae77df528", + "sha256:effc12dba7f3bd72e605ce49807bbe692bd729c3bb122a3b91747a6ae77df528" ], "index": "pypi", - "version": "==2.3.7", + "version": "==2.3.7" }, "xmltodict": { "hashes": [ "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56", - "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852", + "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852" ], "markers": "python_version >= '3.4'", - "version": "==0.13.0", + "version": "==0.13.0" }, "yarl": { "hashes": [ @@ -1000,36 +1122,36 @@ "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b", "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7", "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78", - "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7", + "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7" ], "markers": "python_version >= '3.7'", - "version": "==1.9.2", + "version": "==1.9.2" }, "zipp": { "hashes": [ "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0", - "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147", + "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147" ], "markers": "python_version >= '3.8'", - "version": "==3.16.2", - }, + "version": "==3.16.2" + } }, "develop": { "aspy.refactor-imports": { "hashes": [ "sha256:3c7329cdb2613c46fcd757c8e45120efbc3d4b9db805092911eb605c19c5795c", - "sha256:f306037682479945df61b2e6d01bf97256d68f3e704742768deef549e0d61fbb", + "sha256:f306037682479945df61b2e6d01bf97256d68f3e704742768deef549e0d61fbb" ], "markers": "python_version >= '3.7'", - "version": "==3.0.2", + "version": "==3.0.2" }, "astroid": { "hashes": [ "sha256:389656ca57b6108f939cf5d2f9a2a825a3be50ba9d589670f393236e0a03b91c", - "sha256:903f024859b7c7687d7a7f3a3f73b17301f8e42dfd9cc9df9d4418172d3e2dbd", + "sha256:903f024859b7c7687d7a7f3a3f73b17301f8e42dfd9cc9df9d4418172d3e2dbd" ], "markers": "python_full_version >= '3.7.2'", - "version": "==2.15.6", + "version": "==2.15.6" }, "black": { "hashes": [ @@ -1054,50 +1176,50 @@ "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2", "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a", "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f", - "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995", + "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995" ], "index": "pypi", - "version": "==23.7.0", + "version": "==23.7.0" }, "cachetools": { "hashes": [ "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590", - "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b", + "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b" ], "markers": "python_version >= '3.7'", - "version": "==5.3.1", + "version": "==5.3.1" }, "cfgv": { "hashes": [ "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", - "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", + "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560" ], "markers": "python_version >= '3.8'", - "version": "==3.4.0", + "version": "==3.4.0" }, "chardet": { "hashes": [ "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", - "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", + "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970" ], "markers": "python_version >= '3.7'", - "version": "==5.2.0", + "version": "==5.2.0" }, "click": { "hashes": [ - "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd", - "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5", + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" ], "markers": "python_version >= '3.7'", - "version": "==8.1.6", + "version": "==8.1.7" }, "colorama": { "hashes": [ "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", - "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==0.4.6", + "version": "==0.4.6" }, "coverage": { "hashes": [ @@ -1152,72 +1274,64 @@ "sha256:e2ac9a1de294773b9fa77447ab7e529cf4fe3910f6a0832816e5f3d538cfea9a", "sha256:e61260ec93f99f2c2d93d264b564ba912bec502f679793c56f678ba5251f0393", "sha256:fac440c43e9b479d1241fe9d768645e7ccec3fb65dc3a5f6e90675e75c3f3e3a", - "sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba", + "sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba" ], "markers": "python_version >= '3.8'", - "version": "==7.3.0", + "version": "==7.3.0" }, "dill": { "hashes": [ "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e", - "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03", + "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03" ], - "markers": "python_version < '3.11'", - "version": "==0.3.7", + "markers": "python_version >= '3.11'", + "version": "==0.3.7" }, "distlib": { "hashes": [ "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057", - "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8", - ], - "version": "==0.3.7", - }, - "exceptiongroup": { - "hashes": [ - "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9", - "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3", + "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8" ], - "markers": "python_version < '3.11'", - "version": "==1.1.3", + "version": "==0.3.7" }, "filelock": { "hashes": [ "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81", - "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec", + "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec" ], "markers": "python_version >= '3.7'", - "version": "==3.12.2", + "version": "==3.12.2" }, "green": { "hashes": [ "sha256:8865d0b77b5cb13851dd601a58ad2c82bcb52da7ca106f0538c5787f127368a6" ], "index": "pypi", - "version": "==3.4.3", + "version": "==3.4.3" }, "identify": { "hashes": [ "sha256:7243800bce2f58404ed41b7c002e53d4d22bcf3ae1b7900c2d7aefd95394bf7f", - "sha256:c22a8ead0d4ca11f1edd6c9418c3220669b3b7533ada0a0ffa6cc0ef85cf9b54", + "sha256:c22a8ead0d4ca11f1edd6c9418c3220669b3b7533ada0a0ffa6cc0ef85cf9b54" ], "markers": "python_version >= '3.8'", - "version": "==2.5.26", + "version": "==2.5.26" }, "iniconfig": { "hashes": [ "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", + "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" ], "markers": "python_version >= '3.7'", - "version": "==2.0.0", + "version": "==2.0.0" }, "isort": { "hashes": [ "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504", - "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6", + "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6" ], "index": "pypi", - "version": "==5.12.0", + "version": "==5.12.0" }, "lazy-object-proxy": { "hashes": [ @@ -1256,10 +1370,10 @@ "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455", "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734", "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb", - "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59", + "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59" ], "markers": "python_version >= '3.7'", - "version": "==1.9.0", + "version": "==1.9.0" }, "lxml": { "hashes": [ @@ -1354,106 +1468,106 @@ "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b", "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5", "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7", - "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4", + "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==4.9.3", + "version": "==4.9.3" }, "mccabe": { "hashes": [ "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", + "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" ], "markers": "python_version >= '3.6'", - "version": "==0.7.0", + "version": "==0.7.0" }, "mypy-extensions": { "hashes": [ "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", - "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" ], "markers": "python_version >= '3.5'", - "version": "==1.0.0", + "version": "==1.0.0" }, "nodeenv": { "hashes": [ "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2", - "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec", + "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==1.8.0", + "version": "==1.8.0" }, "packaging": { "hashes": [ "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", - "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f", + "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" ], "markers": "python_version >= '3.7'", - "version": "==23.1", + "version": "==23.1" }, "pathspec": { "hashes": [ "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", - "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3", + "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" ], "markers": "python_version >= '3.7'", - "version": "==0.11.2", + "version": "==0.11.2" }, "platformdirs": { "hashes": [ "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d", - "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d", + "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d" ], "markers": "python_version >= '3.7'", - "version": "==3.10.0", + "version": "==3.10.0" }, "pluggy": { "hashes": [ "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849", - "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3", + "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3" ], "markers": "python_version >= '3.7'", - "version": "==1.2.0", + "version": "==1.2.0" }, "pre-commit": { "hashes": [ "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb", - "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023", + "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023" ], "index": "pypi", - "version": "==3.3.3", + "version": "==3.3.3" }, "pylint": { "hashes": [ "sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413", - "sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252", + "sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252" ], "index": "pypi", - "version": "==2.17.5", + "version": "==2.17.5" }, "pyproject-api": { "hashes": [ "sha256:8d41f3f0c04f0f6a830c27b1c425fa66699715ae06d8a054a1c5eeaaf8bfb145", - "sha256:ca462d457880340ceada078678a296ac500061cef77a040e1143004470ab0046", + "sha256:ca462d457880340ceada078678a296ac500061cef77a040e1143004470ab0046" ], "markers": "python_version >= '3.8'", - "version": "==1.5.4", + "version": "==1.5.4" }, "pytest": { "hashes": [ "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", - "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a", + "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a" ], "index": "pypi", - "version": "==7.4.0", + "version": "==7.4.0" }, "pytest-mock": { "hashes": [ "sha256:21c279fff83d70763b05f8874cc9cfb3fcacd6d354247a976f9529d19f9acf39", - "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f", + "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f" ], "index": "pypi", - "version": "==3.11.1", + "version": "==3.11.1" }, "pyyaml": { "hashes": [ @@ -1496,82 +1610,66 @@ "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" ], "index": "pypi", - "version": "==6.0.1", + "version": "==6.0.1" }, "seed-isort-config": { "hashes": [ "sha256:8601fb715a5a4aac39256bbf73c2da6a81f964da9c9d9897ab9074db3663526f", - "sha256:be4cfef8f9a3fe8ea1817069c6b624538ac0b429636ec746edeb27e98ed628c8", + "sha256:be4cfef8f9a3fe8ea1817069c6b624538ac0b429636ec746edeb27e98ed628c8" ], "index": "pypi", - "version": "==2.2.0", + "version": "==2.2.0" }, "setuptools": { "hashes": [ "sha256:d59c97e7b774979a5ccb96388efc9eb65518004537e85d52e81eaee89ab6dd91", - "sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715", + "sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715" ], "index": "pypi", - "version": "==68.1.0", - }, - "tomli": { - "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f", - ], - "markers": "python_version < '3.11'", - "version": "==2.0.1", + "version": "==68.1.0" }, "tomlkit": { "hashes": [ "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86", - "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899", + "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899" ], "markers": "python_version >= '3.7'", - "version": "==0.12.1", + "version": "==0.12.1" }, "tox": { "hashes": [ "sha256:9b6d38fe422599d084afd89375b4803f4bc1f8f16573c77c8fd8ffcc6938f1ff", - "sha256:c80de60fe26f9a009b0a763888bf2099ccfbef50a0279a6b9f6de40eb4eb7457", + "sha256:c80de60fe26f9a009b0a763888bf2099ccfbef50a0279a6b9f6de40eb4eb7457" ], "index": "pypi", - "version": "==4.9.0", + "version": "==4.9.0" }, "tox-gh-actions": { "hashes": [ "sha256:5954766fe2ed0e284f3cdc87535dfdf68d0f803f1011b17ff8cf52ed3156e6c1", - "sha256:ffd4151fe8b62c6f401a2fc5a01317835d7ab380923f6e0d063c300750308328", + "sha256:ffd4151fe8b62c6f401a2fc5a01317835d7ab380923f6e0d063c300750308328" ], "index": "pypi", - "version": "==3.1.3", - }, - "typing-extensions": { - "hashes": [ - "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", - "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6", - ], - "markers": "python_version >= '3.7'", - "version": "==4.3.0", + "version": "==3.1.3" }, "unidecode": { "hashes": [ "sha256:547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be", - "sha256:fed09cf0be8cf415b391642c2a5addfc72194407caee4f98719e40ec2a72b830", + "sha256:fed09cf0be8cf415b391642c2a5addfc72194407caee4f98719e40ec2a72b830" ], "markers": "python_version >= '3.5'", - "version": "==1.3.6", + "version": "==1.3.6" }, "virtualenv": { "hashes": [ "sha256:95a6e9398b4967fbcb5fef2acec5efaf9aa4972049d9ae41f95e0972a683fd02", - "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc", + "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc" ], "markers": "python_version >= '3.7'", - "version": "==20.24.3", + "version": "==20.24.3" }, "wrapt": { "hashes": [ @@ -1649,10 +1747,10 @@ "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034", "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09", "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559", - "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639", + "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639" ], - "markers": "python_version < '3.11'", - "version": "==1.15.0", - }, - }, + "markers": "python_version >= '3.11'", + "version": "==1.15.0" + } + } } diff --git a/README.md b/README.md index 9b79118..39d179f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ It supports both GitHub.com, GitHub Enterprise Server (GHES) and GitHub, but it - Azure AD - Okta - OneLogin +- Google Workspace ## Features This utility provides the following functionality: diff --git a/githubapp/__init__.py b/githubapp/__init__.py index 6e6966b..a4006dd 100644 --- a/githubapp/__init__.py +++ b/githubapp/__init__.py @@ -11,6 +11,8 @@ from .okta import Okta as DirectoryClient elif os.environ.get("USER_DIRECTORY", "LDAP").upper() == "ONELOGIN": from .onelogin import OneLogin as DirectoryClient +elif os.environ.get("USER_DIRECTORY", "LDAP").upper() == "GOOGLE_WORKSPACE": + from .googleworkspace import GoogleWorkspaceClient as DirectoryClient from .version import __version__ __all__ = ["GitHubApp", "DirectoryClient"] diff --git a/githubapp/googleworkspace.py b/githubapp/googleworkspace.py new file mode 100644 index 0000000..de6452d --- /dev/null +++ b/githubapp/googleworkspace.py @@ -0,0 +1,122 @@ +import os +import traceback +import sys +import json +import logging +from google.oauth2 import service_account +import googleapiclient.discovery +from pprint import pprint + +LOG = logging.getLogger(__name__) + +SCOPES = [ + "https://www.googleapis.com/auth/admin.directory.group.readonly", + "https://www.googleapis.com/auth/admin.directory.group.member.readonly", + "https://www.googleapis.com/auth/admin.directory.user.readonly", +] + + +class GoogleWorkspaceClient: + def __init__(self): + # Read settings from the config file and store them as constants + self.GOOGLE_WORKSPACE_SA_CREDS_FILE = os.environ[ + "GOOGLE_WORKSPACE_SA_CREDS_FILE" + ] + self.GOOGLE_WORKSPACE_ADMIN_EMAIL = os.environ["GOOGLE_WORKSPACE_ADMIN_EMAIL"] + self.GOOGLE_WORKSPACE_USER_MAIL_ATTRIBUTE = os.environ.get( + "GOOGLE_WORKSPACE_USER_MAIL_ATTRIBUTE", "primaryEmail" + ) + self.GOOGLE_WORKSPACE_USERNAME_CUSTOM_SCHEMA_NAME = os.environ.get( + "GOOGLE_WORKSPACE_USERNAME_CUSTOM_SCHEMA_NAME" + ) + self.GOOGLE_WORKSPACE_USERNAME_FIELD = os.environ.get( + "GOOGLE_WORKSPACE_USERNAME_FIELD" + ) + self.USER_SYNC_ATTRIBUTE = os.environ["USER_SYNC_ATTRIBUTE"] + + credentials = service_account.Credentials.from_service_account_file( + self.GOOGLE_WORKSPACE_SA_CREDS_FILE, scopes=SCOPES + ) + delegated_credentials = credentials.with_subject( + self.GOOGLE_WORKSPACE_ADMIN_EMAIL + ) + self.service = googleapiclient.discovery.build( + "admin", "directory_v1", credentials=delegated_credentials + ) + + def get_group_members(self, group_name): + """ + Get members of the requested group in GOOGLE_WORKSPACE/Active Directory + :param group_name: The name of the group + :type group_name: str + :return member_list: List of members found in this GOOGLE_WORKSPACE group + :rtype member_list: list + """ + + member_list = [] + # Retrive dict of groups ids, to be able to match group names + groups = self.get_groups_info() + group_id = groups.get(group_name) + if not group_id: + return [] + + service = self.service.members() + request = service.list(groupKey=group_id) + while request is not None: + members = request.execute() + for m in members.get("members", []): + user_info = self.get_user_info(m["id"]) + if user_info.get("email") or user_info.get("username"): + member_list.append(user_info) + request = service.list_next(request, members) + return member_list + + def get_user_info(self, id): + """ + Look up user info from Google Workspace + :param user: + :type user: + :return: + :rtype: + """ + + if self.USER_SYNC_ATTRIBUTE == "username": + user = ( + self.service.users() + .get( + userKey=id, + projection="custom", + customFieldMask=self.GOOGLE_WORKSPACE_USERNAME_CUSTOM_SCHEMA_NAME, + ) + .execute() + ) + if not user["suspended"] and not user["archived"]: + return { + "username": user.get("customSchemas", {}) + .get(self.GOOGLE_WORKSPACE_USERNAME_CUSTOM_SCHEMA_NAME, {}) + .get(self.GOOGLE_WORKSPACE_USERNAME_FIELD), + "email": None, + } + elif self.USER_SYNC_ATTRIBUTE == "email": + user = self.service.users().get(userKey=id).execute() + if not user["suspended"] and not user["archived"]: + return { + "username": None, + "email": user[self.GOOGLE_WORKSPACE_USER_MAIL_ATTRIBUTE], + } + return {"username": None, "email": None} + + def get_groups_info(self): + """ + Returns dict of groups ids + """ + + groups_dict = dict() + service = self.service.groups() + request = service.list(customer="my_customer") + while request is not None: + groups = request.execute() + for g in groups.get("groups", []): + groups_dict[g["name"].lower()] = g["id"] + request = service.list_next(request, groups) + return groups_dict