diff --git a/.github/stale.yml b/.github/stale.yml index 4e6b706f0e..6a34753f92 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -7,6 +7,7 @@ exemptLabels: - pinned - security - pr_wanted + - enhancement/confirmed # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had diff --git a/.python-version b/.python-version new file mode 100644 index 0000000000..f69abe410a --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9.7 diff --git a/Dockerfile b/Dockerfile index 6e245fd53e..fad521d50c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,8 +58,6 @@ RUN apt-get update && \ curl ca-certificates gnupg git runit libpq-dev \ postgresql-client build-essential libxmlsec1-dev \ pkg-config libmaxminddb0 && \ - pip install lxml==4.6.4 --no-cache-dir && \ - export C_INCLUDE_PATH=/usr/local/lib/python3.10/site-packages/lxml/includes && \ pip install -r /requirements.txt --no-cache-dir && \ apt-get remove --purge -y build-essential git && \ apt-get autoremove --purge -y && \ diff --git a/Makefile b/Makefile index 60f9ef558a..335f10b815 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ UID = $(shell id -u) GID = $(shell id -g) NPM_VERSION = $(shell python -m scripts.npm_version) -all: lint-fix lint test gen +all: lint-fix lint test gen web test-integration: coverage run manage.py test tests/integration diff --git a/Pipfile b/Pipfile index 89c7a768ca..2f787564a6 100644 --- a/Pipfile +++ b/Pipfile @@ -32,15 +32,14 @@ geoip2 = "*" gunicorn = "*" kubernetes = "==v19.15.0" ldap3 = "*" -# 4.7.0 and later remove `lxml-version.h` which is required by xmlsec -lxml = "==4.6.5" +lxml = "*" packaging = "*" psycopg2-binary = "*" pycryptodome = "*" pyjwt = "*" pyyaml = "*" requests-oauthlib = "*" -sentry-sdk = "*" +sentry-sdk = { git = 'https://github.com/beryju/sentry-python.git', ref = '379aee28b15d3b87b381317746c4efd24b3d7bc3' } service_identity = "*" structlog = "*" swagger-spec-validator = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 3058437791..aff0e12ec9 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "6a89870496296af32dbc2f64b0832d4c20010829ada0b3c4dc27fee56b68fad9" + "sha256": "dedb51159ef09fd9b00ab28022706f525c9df057ffd646e2a552784341a10538" }, "pipfile-spec": 6, "requires": {}, @@ -169,19 +169,19 @@ }, "boto3": { "hashes": [ - "sha256:76b3ee0d1dd860c9218bc864cd29f1ee986f6e1e75e8669725dd3c411039379e", - "sha256:c39cb6ed376ba1d4689ac8f6759a2b2d8a0b0424dbec0cd3af1558079bcf06e8" + "sha256:739705b28e6b2329ea3b481ba801d439c296aaf176f7850729147ba99bbf8a9a", + "sha256:8f08e8e94bf107c5e9866684e9aadf8d9f60abed0cfe5c1dba4e7328674a1986" ], "index": "pypi", - "version": "==1.20.23" + "version": "==1.20.24" }, "botocore": { "hashes": [ - "sha256:640b62110aa6d1c25553eceafb5bcd89aedeb84b191598d1f6492ad24374d285", - "sha256:7459766c4594f3b8877e8013f93f0dc6c6486acbeb7d9c9ae488396529cc2e84" + "sha256:43006b4f52d7bb655319d3da0f615cdbee7762853acc1ebcb1d49f962e6b4806", + "sha256:e78d48c50c8c013fb9b362c6202fece2fe868edfd89b51968080180bdff41617" ], "markers": "python_version >= '3.6'", - "version": "==1.23.23" + "version": "==1.23.24" }, "cachetools": { "hashes": [ @@ -196,7 +196,7 @@ "sha256:1ef33f089e0a494e8d1b487508356f055c865b1955b125c00c991a4358543c80", "sha256:8eca49962b1bfc09c24d442aa55688be88efe5c24aeef89d3be135614b95c678" ], - "markers": "python_version >= '3.7' and python_version < '4'", + "markers": "python_version >= '3.7' and python_full_version < '4.0.0'", "version": "==1.9.0" }, "cbor2": { @@ -325,7 +325,7 @@ "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667", "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035" ], - "markers": "python_version < '4' and python_full_version >= '3.6.2'", + "markers": "python_full_version >= '3.6.2' and python_full_version < '4.0.0'", "version": "==0.3.0" }, "click-plugins": { @@ -494,11 +494,11 @@ }, "djangorestframework": { "hashes": [ - "sha256:6d1d59f623a5ad0509fe0d6bfe93cbdfe17b8116ebc8eda86d45f6e16e819aaf", - "sha256:f747949a8ddac876e879190df194b925c177cdeb725a099db1460872f7c0a7f2" + "sha256:48e64f08244fa0df9e2b8fbd405edec263d8e1251112a06d0073b546b7c86b9c", + "sha256:8b987d5683f5b3553dd946d4972048d3117fc526cb0bc01a3f021e81af53f39e" ], "index": "pypi", - "version": "==3.12.4" + "version": "==3.13.0" }, "djangorestframework-guardian": { "hashes": [ @@ -816,69 +816,69 @@ }, "lxml": { "hashes": [ - "sha256:11ae552a78612620afd15625be9f1b82e3cc2e634f90d6b11709b10a100cba59", - "sha256:121fc6f71c692b49af6c963b84ab7084402624ffbe605287da362f8af0668ea3", - "sha256:124f09614f999551ac65e5b9875981ce4b66ac4b8e2ba9284572f741935df3d9", - "sha256:12ae2339d32a2b15010972e1e2467345b7bf962e155671239fba74c229564b7f", - "sha256:12d8d6fe3ddef629ac1349fa89a638b296a34b6529573f5055d1cb4e5245f73b", - "sha256:1a2a7659b8eb93c6daee350a0d844994d49245a0f6c05c747f619386fb90ba04", - "sha256:1ccbfe5d17835db906f2bab6f15b34194db1a5b07929cba3cf45a96dbfbfefc0", - "sha256:2f77556266a8fe5428b8759fbfc4bd70be1d1d9c9b25d2a414f6a0c0b0f09120", - "sha256:3534d7c468c044f6aef3c0aff541db2826986a29ea73f2ca831f5d5284d9b570", - "sha256:3884476a90d415be79adfa4e0e393048630d0d5bcd5757c4c07d8b4b00a1096b", - "sha256:3b95fb7e6f9c2f53db88f4642231fc2b8907d854e614710996a96f1f32018d5c", - "sha256:46515773570a33eae13e451c8fcf440222ef24bd3b26f40774dd0bd8b6db15b2", - "sha256:46f21f2600d001af10e847df9eb3b832e8a439f696c04891bcb8a8cedd859af9", - "sha256:473701599665d874919d05bb33b56180447b3a9da8d52d6d9799f381ce23f95c", - "sha256:4b9390bf973e3907d967b75be199cf1978ca8443183cf1e78ad80ad8be9cf242", - "sha256:4f415624cf8b065796649a5e4621773dc5c9ea574a944c76a7f8a6d3d2906b41", - "sha256:534032a5ceb34bba1da193b7d386ac575127cc39338379f39a164b10d97ade89", - "sha256:558485218ee06458643b929765ac1eb04519ca3d1e2dcc288517de864c747c33", - "sha256:57cf05466917e08f90e323f025b96f493f92c0344694f5702579ab4b7e2eb10d", - "sha256:59d77bfa3bea13caee95bc0d3f1c518b15049b97dd61ea8b3d71ce677a67f808", - "sha256:5d5254c815c186744c8f922e2ce861a2bdeabc06520b4b30b2f7d9767791ce6e", - "sha256:5ea121cb66d7e5cb396b4c3ca90471252b94e01809805cfe3e4e44be2db3a99c", - "sha256:60aeb14ff9022d2687ef98ce55f6342944c40d00916452bb90899a191802137a", - "sha256:642eb4cabd997c9b949a994f9643cd8ae00cf4ca8c5cd9c273962296fadf1c44", - "sha256:6548fc551de15f310dd0564751d9dc3d405278d45ea9b2b369ed1eccf142e1f5", - "sha256:68a851176c931e2b3de6214347b767451243eeed3bea34c172127bbb5bf6c210", - "sha256:6e84edecc3a82f90d44ddee2ee2a2630d4994b8471816e226d2b771cda7ac4ca", - "sha256:73e8614258404b2689a26cb5d002512b8bc4dfa18aca86382f68f959aee9b0c8", - "sha256:7679bb6e4d9a3978a46ab19a3560e8d2b7265ef3c88152e7fdc130d649789887", - "sha256:76b6c296e4f7a1a8a128aec42d128646897f9ae9a700ef6839cdc9b3900db9b5", - "sha256:7f00cc64b49d2ef19ddae898a3def9dd8fda9c3d27c8a174c2889ee757918e71", - "sha256:8021eeff7fabde21b9858ed058a8250ad230cede91764d598c2466b0ba70db8b", - "sha256:87f8f7df70b90fbe7b49969f07b347e3f978f8bd1046bb8ecae659921869202b", - "sha256:916d457ad84e05b7db52700bad0a15c56e0c3000dcaf1263b2fb7a56fe148996", - "sha256:925174cafb0f1179a7fd38da90302555d7445e34c9ece68019e53c946be7f542", - "sha256:9801bcd52ac9c795a7d81ea67471a42cffe532e46cfb750cd5713befc5c019c0", - "sha256:99cf827f5a783038eb313beee6533dddb8bdb086d7269c5c144c1c952d142ace", - "sha256:a21b78af7e2e13bec6bea12fc33bc05730197674f3e5402ce214d07026ccfebd", - "sha256:a52e8f317336a44836475e9c802f51c2dc38d612eaa76532cb1d17690338b63b", - "sha256:a702005e447d712375433ed0499cb6e1503fadd6c96a47f51d707b4d37b76d3c", - "sha256:a708c291900c40a7ecf23f1d2384ed0bc0604e24094dd13417c7e7f8f7a50d93", - "sha256:a7790a273225b0c46e5f859c1327f0f659896cc72eaa537d23aa3ad9ff2a1cc1", - "sha256:abcf7daa5ebcc89328326254f6dd6d566adb483d4d00178892afd386ab389de2", - "sha256:add017c5bd6b9ec3a5f09248396b6ee2ce61c5621f087eb2269c813cd8813808", - "sha256:af4139172ff0263d269abdcc641e944c9de4b5d660894a3ec7e9f9db63b56ac9", - "sha256:b4015baed99d046c760f09a4c59d234d8f398a454380c3cf0b859aba97136090", - "sha256:ba0006799f21d83c3717fe20e2707a10bbc296475155aadf4f5850f6659b96b9", - "sha256:bdb98f4c9e8a1735efddfaa995b0c96559792da15d56b76428bdfc29f77c4cdb", - "sha256:c34234a1bc9e466c104372af74d11a9f98338a3f72fae22b80485171a64e0144", - "sha256:c580c2a61d8297a6e47f4d01f066517dbb019be98032880d19ece7f337a9401d", - "sha256:ca9a40497f7e97a2a961c04fa8a6f23d790b0521350a8b455759d786b0bcb203", - "sha256:cab343b265e38d4e00649cbbad9278b734c5715f9bcbb72c85a1f99b1a58e19a", - "sha256:ce52aad32ec6e46d1a91ff8b8014a91538800dd533914bfc4a82f5018d971408", - "sha256:da07c7e7fc9a3f40446b78c54dbba8bfd5c9100dfecb21b65bfe3f57844f5e71", - "sha256:dc8a0dbb2a10ae8bb609584f5c504789f0f3d0d81840da4849102ec84289f952", - "sha256:e5b4b0d9440046ead3bd425eb2b852499241ee0cef1ae151038e4f87ede888c4", - "sha256:f33d8efb42e4fc2b31b3b4527940b25cdebb3026fb56a80c1c1c11a4271d2352", - "sha256:f6befb83bca720b71d6bd6326a3b26e9496ae6649e26585de024890fe50f49b8", - "sha256:fcc849b28f584ed1dbf277291ded5c32bb3476a37032df4a1d523b55faa5f944", - "sha256:ff44de36772b05c2eb74f2b4b6d1ae29b8f41ed5506310ce1258d44826ee38c1" + "sha256:0607ff0988ad7e173e5ddf7bf55ee65534bd18a5461183c33e8e41a59e89edf4", + "sha256:09b738360af8cb2da275998a8bf79517a71225b0de41ab47339c2beebfff025f", + "sha256:0a5f0e4747f31cff87d1eb32a6000bde1e603107f632ef4666be0dc065889c7a", + "sha256:0b5e96e25e70917b28a5391c2ed3ffc6156513d3db0e1476c5253fcd50f7a944", + "sha256:1104a8d47967a414a436007c52f533e933e5d52574cab407b1e49a4e9b5ddbd1", + "sha256:13dbb5c7e8f3b6a2cf6e10b0948cacb2f4c9eb05029fe31c60592d08ac63180d", + "sha256:2a906c3890da6a63224d551c2967413b8790a6357a80bf6b257c9a7978c2c42d", + "sha256:317bd63870b4d875af3c1be1b19202de34c32623609ec803b81c99193a788c1e", + "sha256:34c22eb8c819d59cec4444d9eebe2e38b95d3dcdafe08965853f8799fd71161d", + "sha256:36b16fecb10246e599f178dd74f313cbdc9f41c56e77d52100d1361eed24f51a", + "sha256:38d9759733aa04fb1697d717bfabbedb21398046bd07734be7cccc3d19ea8675", + "sha256:3e26ad9bc48d610bf6cc76c506b9e5ad9360ed7a945d9be3b5b2c8535a0145e3", + "sha256:41358bfd24425c1673f184d7c26c6ae91943fe51dfecc3603b5e08187b4bcc55", + "sha256:447d5009d6b5447b2f237395d0018901dcc673f7d9f82ba26c1b9f9c3b444b60", + "sha256:44f552e0da3c8ee3c28e2eb82b0b784200631687fc6a71277ea8ab0828780e7d", + "sha256:490712b91c65988012e866c411a40cc65b595929ececf75eeb4c79fcc3bc80a6", + "sha256:4c093c571bc3da9ebcd484e001ba18b8452903cd428c0bc926d9b0141bcb710e", + "sha256:50d3dba341f1e583265c1a808e897b4159208d814ab07530202b6036a4d86da5", + "sha256:534e946bce61fd162af02bad7bfd2daec1521b71d27238869c23a672146c34a5", + "sha256:585ea241ee4961dc18a95e2f5581dbc26285fcf330e007459688096f76be8c42", + "sha256:59e7da839a1238807226f7143c68a479dee09244d1b3cf8c134f2fce777d12d0", + "sha256:5b0f782f0e03555c55e37d93d7a57454efe7495dab33ba0ccd2dbe25fc50f05d", + "sha256:5bee1b0cbfdb87686a7fb0e46f1d8bd34d52d6932c0723a86de1cc532b1aa489", + "sha256:610807cea990fd545b1559466971649e69302c8a9472cefe1d6d48a1dee97440", + "sha256:6308062534323f0d3edb4e702a0e26a76ca9e0e23ff99be5d82750772df32a9e", + "sha256:67fa5f028e8a01e1d7944a9fb616d1d0510d5d38b0c41708310bd1bc45ae89f6", + "sha256:6a2ab9d089324d77bb81745b01f4aeffe4094306d939e92ba5e71e9a6b99b71e", + "sha256:6c198bfc169419c09b85ab10cb0f572744e686f40d1e7f4ed09061284fc1303f", + "sha256:6e56521538f19c4a6690f439fefed551f0b296bd785adc67c1777c348beb943d", + "sha256:6ec829058785d028f467be70cd195cd0aaf1a763e4d09822584ede8c9eaa4b03", + "sha256:718d7208b9c2d86aaf0294d9381a6acb0158b5ff0f3515902751404e318e02c9", + "sha256:735e3b4ce9c0616e85f302f109bdc6e425ba1670a73f962c9f6b98a6d51b77c9", + "sha256:772057fba283c095db8c8ecde4634717a35c47061d24f889468dc67190327bcd", + "sha256:7b5e2acefd33c259c4a2e157119c4373c8773cf6793e225006a1649672ab47a6", + "sha256:82d16a64236970cb93c8d63ad18c5b9f138a704331e4b916b2737ddfad14e0c4", + "sha256:87c1b0496e8c87ec9db5383e30042357b4839b46c2d556abd49ec770ce2ad868", + "sha256:8e54945dd2eeb50925500957c7c579df3cd07c29db7810b83cf30495d79af267", + "sha256:9393a05b126a7e187f3e38758255e0edf948a65b22c377414002d488221fdaa2", + "sha256:9fbc0dee7ff5f15c4428775e6fa3ed20003140560ffa22b88326669d53b3c0f4", + "sha256:a1613838aa6b89af4ba10a0f3a972836128801ed008078f8c1244e65958f1b24", + "sha256:a1bbc4efa99ed1310b5009ce7f3a1784698082ed2c1ef3895332f5df9b3b92c2", + "sha256:a555e06566c6dc167fbcd0ad507ff05fd9328502aefc963cb0a0547cfe7f00db", + "sha256:a58d78653ae422df6837dd4ca0036610b8cb4962b5cfdbd337b7b24de9e5f98a", + "sha256:a5edc58d631170de90e50adc2cc0248083541affef82f8cd93bea458e4d96db8", + "sha256:a5f623aeaa24f71fce3177d7fee875371345eb9102b355b882243e33e04b7175", + "sha256:adaab25be351fff0d8a691c4f09153647804d09a87a4e4ea2c3f9fe9e8651851", + "sha256:ade74f5e3a0fd17df5782896ddca7ddb998845a5f7cd4b0be771e1ffc3b9aa5b", + "sha256:b1d381f58fcc3e63fcc0ea4f0a38335163883267f77e4c6e22d7a30877218a0e", + "sha256:bf6005708fc2e2c89a083f258b97709559a95f9a7a03e59f805dd23c93bc3986", + "sha256:d546431636edb1d6a608b348dd58cc9841b81f4116745857b6cb9f8dadb2725f", + "sha256:d5618d49de6ba63fe4510bdada62d06a8acfca0b4b5c904956c777d28382b419", + "sha256:dfd0d464f3d86a1460683cd742306d1138b4e99b79094f4e07e1ca85ee267fe7", + "sha256:e18281a7d80d76b66a9f9e68a98cf7e1d153182772400d9a9ce855264d7d0ce7", + "sha256:e410cf3a2272d0a85526d700782a2fa92c1e304fdcc519ba74ac80b8297adf36", + "sha256:e662c6266e3a275bdcb6bb049edc7cd77d0b0f7e119a53101d367c841afc66dc", + "sha256:ec9027d0beb785a35aa9951d14e06d48cfbf876d8ff67519403a2522b181943b", + "sha256:eed394099a7792834f0cb4a8f615319152b9d801444c1c9e1b1a2c36d2239f9e", + "sha256:f76dbe44e31abf516114f6347a46fa4e7c2e8bceaa4b6f7ee3a0a03c8eba3c17", + "sha256:fc15874816b9320581133ddc2096b644582ab870cf6a6ed63684433e7af4b0d3", + "sha256:fc9fb11b65e7bc49f7f75aaba1b700f7181d95d4e151cf2f24d51bfd14410b77" ], "index": "pypi", - "version": "==4.6.5" + "version": "==4.7.1" }, "maxminddb": { "hashes": [ @@ -1312,12 +1312,12 @@ "version": "==0.5.0" }, "sentry-sdk": { + "git": "https://github.com/beryju/sentry-python.git", "hashes": [ "sha256:0db297ab32e095705c20f742c3a5dac62fe15c4318681884053d0898e5abb2f6", "sha256:789a11a87ca02491896e121efdd64e8fd93327b69e8f2f7d42f03e2569648e88" ], - "index": "pypi", - "version": "==1.5.0" + "ref": "379aee28b15d3b87b381317746c4efd24b3d7bc3" }, "service-identity": { "hashes": [ @@ -2387,11 +2387,11 @@ }, "tomli": { "hashes": [ - "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee", - "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade" + "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f", + "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c" ], "markers": "python_version >= '3.6'", - "version": "==1.2.2" + "version": "==1.2.3" }, "trio": { "hashes": [ diff --git a/authentik/admin/api/metrics.py b/authentik/admin/api/metrics.py index 739fdba319..c7529d5361 100644 --- a/authentik/admin/api/metrics.py +++ b/authentik/admin/api/metrics.py @@ -1,13 +1,6 @@ """authentik administration metrics""" -import time -from collections import Counter -from datetime import timedelta - -from django.db.models import Count, ExpressionWrapper, F -from django.db.models.fields import DurationField -from django.db.models.functions import ExtractHour -from django.utils.timezone import now from drf_spectacular.utils import extend_schema, extend_schema_field +from guardian.shortcuts import get_objects_for_user from rest_framework.fields import IntegerField, SerializerMethodField from rest_framework.permissions import IsAdminUser from rest_framework.request import Request @@ -15,31 +8,7 @@ from rest_framework.response import Response from rest_framework.views import APIView from authentik.core.api.utils import PassiveSerializer -from authentik.events.models import Event, EventAction - - -def get_events_per_1h(**filter_kwargs) -> list[dict[str, int]]: - """Get event count by hour in the last day, fill with zeros""" - date_from = now() - timedelta(days=1) - result = ( - Event.objects.filter(created__gte=date_from, **filter_kwargs) - .annotate(age=ExpressionWrapper(now() - F("created"), output_field=DurationField())) - .annotate(age_hours=ExtractHour("age")) - .values("age_hours") - .annotate(count=Count("pk")) - .order_by("age_hours") - ) - data = Counter({int(d["age_hours"]): d["count"] for d in result}) - results = [] - _now = now() - for hour in range(0, -24, -1): - results.append( - { - "x_cord": time.mktime((_now + timedelta(hours=hour)).timetuple()) * 1000, - "y_cord": data[hour * -1], - } - ) - return results +from authentik.events.models import EventAction class CoordinateSerializer(PassiveSerializer): @@ -58,12 +27,22 @@ class LoginMetricsSerializer(PassiveSerializer): @extend_schema_field(CoordinateSerializer(many=True)) def get_logins_per_1h(self, _): """Get successful logins per hour for the last 24 hours""" - return get_events_per_1h(action=EventAction.LOGIN) + user = self.context["user"] + return ( + get_objects_for_user(user, "authentik_events.view_event") + .filter(action=EventAction.LOGIN) + .get_events_per_hour() + ) @extend_schema_field(CoordinateSerializer(many=True)) def get_logins_failed_per_1h(self, _): """Get failed logins per hour for the last 24 hours""" - return get_events_per_1h(action=EventAction.LOGIN_FAILED) + user = self.context["user"] + return ( + get_objects_for_user(user, "authentik_events.view_event") + .filter(action=EventAction.LOGIN_FAILED) + .get_events_per_hour() + ) class AdministrationMetricsViewSet(APIView): @@ -75,4 +54,5 @@ class AdministrationMetricsViewSet(APIView): def get(self, request: Request) -> Response: """Login Metrics per 1h""" serializer = LoginMetricsSerializer(True) + serializer.context["user"] = request.user return Response(serializer.data) diff --git a/authentik/core/api/applications.py b/authentik/core/api/applications.py index e8a92e3a64..eab41f4711 100644 --- a/authentik/core/api/applications.py +++ b/authentik/core/api/applications.py @@ -5,6 +5,7 @@ from django.http.response import HttpResponseBadRequest from django.shortcuts import get_object_or_404 from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema +from guardian.shortcuts import get_objects_for_user from rest_framework.decorators import action from rest_framework.fields import ReadOnlyField from rest_framework.parsers import MultiPartParser @@ -15,7 +16,7 @@ from rest_framework.viewsets import ModelViewSet from rest_framework_guardian.filters import ObjectPermissionsFilter from structlog.stdlib import get_logger -from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h +from authentik.admin.api.metrics import CoordinateSerializer from authentik.api.decorators import permission_required from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin @@ -239,8 +240,10 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet): """Metrics for application logins""" app = self.get_object() return Response( - get_events_per_1h( + get_objects_for_user(request.user, "authentik_events.view_event") + .filter( action=EventAction.AUTHORIZE_APPLICATION, context__authorized_application__pk=app.pk.hex, ) + .get_events_per_hour() ) diff --git a/authentik/core/api/sources.py b/authentik/core/api/sources.py index 9d56e7be84..63c028bceb 100644 --- a/authentik/core/api/sources.py +++ b/authentik/core/api/sources.py @@ -104,14 +104,14 @@ class SourceViewSet( ) matching_sources: list[UserSettingSerializer] = [] for source in _all_sources: - user_settings = source.ui_user_settings + user_settings = source.ui_user_settings() if not user_settings: continue policy_engine = PolicyEngine(source, request.user, request) policy_engine.build() if not policy_engine.passing: continue - source_settings = source.ui_user_settings + source_settings = source.ui_user_settings() source_settings.initial_data["object_uid"] = source.slug if not source_settings.is_valid(): LOGGER.warning(source_settings.errors) diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py index c22a63da73..f5dd9c290b 100644 --- a/authentik/core/api/users.py +++ b/authentik/core/api/users.py @@ -38,7 +38,7 @@ from rest_framework.viewsets import ModelViewSet from rest_framework_guardian.filters import ObjectPermissionsFilter from structlog.stdlib import get_logger -from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h +from authentik.admin.api.metrics import CoordinateSerializer from authentik.api.decorators import permission_required from authentik.core.api.groups import GroupSerializer from authentik.core.api.used_by import UsedByMixin @@ -184,19 +184,31 @@ class UserMetricsSerializer(PassiveSerializer): def get_logins_per_1h(self, _): """Get successful logins per hour for the last 24 hours""" user = self.context["user"] - return get_events_per_1h(action=EventAction.LOGIN, user__pk=user.pk) + return ( + get_objects_for_user(user, "authentik_events.view_event") + .filter(action=EventAction.LOGIN, user__pk=user.pk) + .get_events_per_hour() + ) @extend_schema_field(CoordinateSerializer(many=True)) def get_logins_failed_per_1h(self, _): """Get failed logins per hour for the last 24 hours""" user = self.context["user"] - return get_events_per_1h(action=EventAction.LOGIN_FAILED, context__username=user.username) + return ( + get_objects_for_user(user, "authentik_events.view_event") + .filter(action=EventAction.LOGIN_FAILED, context__username=user.username) + .get_events_per_hour() + ) @extend_schema_field(CoordinateSerializer(many=True)) def get_authorizations_per_1h(self, _): """Get failed logins per hour for the last 24 hours""" user = self.context["user"] - return get_events_per_1h(action=EventAction.AUTHORIZE_APPLICATION, user__pk=user.pk) + return ( + get_objects_for_user(user, "authentik_events.view_event") + .filter(action=EventAction.AUTHORIZE_APPLICATION, user__pk=user.pk) + .get_events_per_hour() + ) class UsersFilter(FilterSet): diff --git a/authentik/core/middleware.py b/authentik/core/middleware.py index 5dadd1f275..11834dbed4 100644 --- a/authentik/core/middleware.py +++ b/authentik/core/middleware.py @@ -5,6 +5,7 @@ from typing import Callable from uuid import uuid4 from django.http import HttpRequest, HttpResponse +from sentry_sdk.api import set_tag SESSION_IMPERSONATE_USER = "authentik_impersonate_user" SESSION_IMPERSONATE_ORIGINAL_USER = "authentik_impersonate_original_user" @@ -50,6 +51,7 @@ class RequestIDMiddleware: "request_id": request_id, "host": request.get_host(), } + set_tag("authentik.request_id", request_id) response = self.get_response(request) response[RESPONSE_HEADER_ID] = request.request_id setattr(response, "ak_context", {}) diff --git a/authentik/core/models.py b/authentik/core/models.py index ad07d3c12e..136db1c149 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -359,13 +359,11 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel): """Return component used to edit this object""" raise NotImplementedError - @property - def ui_login_button(self) -> Optional[UILoginButton]: + def ui_login_button(self, request: HttpRequest) -> Optional[UILoginButton]: """If source uses a http-based flow, return UI Information about the login button. If source doesn't use http-based flow, return None.""" return None - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: """Entrypoint to integrate with User settings. Can either return None if no user settings are available, or UserSettingSerializer.""" diff --git a/authentik/core/templates/base/skeleton.html b/authentik/core/templates/base/skeleton.html index 77b4cf7886..544f94449e 100644 --- a/authentik/core/templates/base/skeleton.html +++ b/authentik/core/templates/base/skeleton.html @@ -19,6 +19,7 @@ {% block head %} {% endblock %} + {% block body %} diff --git a/authentik/core/tests/test_models.py b/authentik/core/tests/test_models.py index 9dc17d7244..1fa924f7b5 100644 --- a/authentik/core/tests/test_models.py +++ b/authentik/core/tests/test_models.py @@ -2,7 +2,7 @@ from time import sleep from typing import Callable, Type -from django.test import TestCase +from django.test import RequestFactory, TestCase from django.utils.timezone import now from guardian.shortcuts import get_anonymous_user @@ -30,6 +30,9 @@ class TestModels(TestCase): def source_tester_factory(test_model: Type[Stage]) -> Callable: """Test source""" + factory = RequestFactory() + request = factory.get("/") + def tester(self: TestModels): model_class = None if test_model._meta.abstract: @@ -38,8 +41,8 @@ def source_tester_factory(test_model: Type[Stage]) -> Callable: model_class = test_model() model_class.slug = "test" self.assertIsNotNone(model_class.component) - _ = model_class.ui_login_button - _ = model_class.ui_user_settings + _ = model_class.ui_login_button(request) + _ = model_class.ui_user_settings() return tester diff --git a/authentik/core/tests/test_property_mapping_api.py b/authentik/core/tests/test_property_mapping_api.py index d5e74f626d..29e608c056 100644 --- a/authentik/core/tests/test_property_mapping_api.py +++ b/authentik/core/tests/test_property_mapping_api.py @@ -41,7 +41,7 @@ class TestPropertyMappingAPI(APITestCase): expr = "return True" self.assertEqual(PropertyMappingSerializer().validate_expression(expr), expr) with self.assertRaises(ValidationError): - print(PropertyMappingSerializer().validate_expression("/")) + PropertyMappingSerializer().validate_expression("/") def test_types(self): """Test PropertyMappigns's types endpoint""" diff --git a/authentik/crypto/models.py b/authentik/crypto/models.py index 111adf079d..037e8dffdf 100644 --- a/authentik/crypto/models.py +++ b/authentik/crypto/models.py @@ -11,10 +11,13 @@ from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.x509 import Certificate, load_pem_x509_certificate from django.db import models from django.utils.translation import gettext_lazy as _ +from structlog.stdlib import get_logger from authentik.lib.models import CreatedUpdatedModel from authentik.managed.models import ManagedModel +LOGGER = get_logger() + class CertificateKeyPair(ManagedModel, CreatedUpdatedModel): """CertificateKeyPair that can be used for signing or encrypting if `key_data` @@ -62,7 +65,8 @@ class CertificateKeyPair(ManagedModel, CreatedUpdatedModel): password=None, backend=default_backend(), ) - except ValueError: + except ValueError as exc: + LOGGER.warning(exc) return None return self._private_key diff --git a/authentik/crypto/tasks.py b/authentik/crypto/tasks.py index 81e50219c9..723a603ee1 100644 --- a/authentik/crypto/tasks.py +++ b/authentik/crypto/tasks.py @@ -2,6 +2,9 @@ from glob import glob from pathlib import Path +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.serialization import load_pem_private_key +from cryptography.x509.base import load_pem_x509_certificate from django.utils.translation import gettext_lazy as _ from structlog.stdlib import get_logger @@ -20,6 +23,22 @@ LOGGER = get_logger() MANAGED_DISCOVERED = "goauthentik.io/crypto/discovered/%s" +def ensure_private_key_valid(body: str): + """Attempt loading of an RSA Private key without password""" + load_pem_private_key( + str.encode("\n".join([x.strip() for x in body.split("\n")])), + password=None, + backend=default_backend(), + ) + return body + + +def ensure_certificate_valid(body: str): + """Attempt loading of a PEM-encoded certificate""" + load_pem_x509_certificate(body.encode("utf-8"), default_backend()) + return body + + @CELERY_APP.task(bind=True, base=MonitoredTask) @prefill_task def certificate_discovery(self: MonitoredTask): @@ -42,11 +61,11 @@ def certificate_discovery(self: MonitoredTask): with open(path, "r+", encoding="utf-8") as _file: body = _file.read() if "BEGIN RSA PRIVATE KEY" in body: - private_keys[cert_name] = body + private_keys[cert_name] = ensure_private_key_valid(body) else: - certs[cert_name] = body - except OSError as exc: - LOGGER.warning("Failed to open file", exc=exc, file=path) + certs[cert_name] = ensure_certificate_valid(body) + except (OSError, ValueError) as exc: + LOGGER.warning("Failed to open file or invalid format", exc=exc, file=path) discovered += 1 for name, cert_data in certs.items(): cert = CertificateKeyPair.objects.filter(managed=MANAGED_DISCOVERED % name).first() diff --git a/authentik/events/api/event.py b/authentik/events/api/event.py index 767f58a412..836789604c 100644 --- a/authentik/events/api/event.py +++ b/authentik/events/api/event.py @@ -1,4 +1,6 @@ """Events API Views""" +from json import loads + import django_filters from django.db.models.aggregates import Count from django.db.models.fields.json import KeyTextTransform @@ -12,6 +14,7 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet +from authentik.admin.api.metrics import CoordinateSerializer from authentik.core.api.utils import PassiveSerializer, TypeCreateSerializer from authentik.events.models import Event, EventAction @@ -110,13 +113,20 @@ class EventViewSet(ModelViewSet): @extend_schema( methods=["GET"], responses={200: EventTopPerUserSerializer(many=True)}, + filters=[], parameters=[ + OpenApiParameter( + "action", + type=OpenApiTypes.STR, + location=OpenApiParameter.QUERY, + required=False, + ), OpenApiParameter( "top_n", type=OpenApiTypes.INT, location=OpenApiParameter.QUERY, required=False, - ) + ), ], ) @action(detail=False, methods=["GET"], pagination_class=None) @@ -137,6 +147,40 @@ class EventViewSet(ModelViewSet): .order_by("-counted_events")[:top_n] ) + @extend_schema( + methods=["GET"], + responses={200: CoordinateSerializer(many=True)}, + filters=[], + parameters=[ + OpenApiParameter( + "action", + type=OpenApiTypes.STR, + location=OpenApiParameter.QUERY, + required=False, + ), + OpenApiParameter( + "query", + type=OpenApiTypes.STR, + location=OpenApiParameter.QUERY, + required=False, + ), + ], + ) + @action(detail=False, methods=["GET"], pagination_class=None) + def per_month(self, request: Request): + """Get the count of events per month""" + filtered_action = request.query_params.get("action", EventAction.LOGIN) + try: + query = loads(request.query_params.get("query", "{}")) + except ValueError: + return Response(status=400) + return Response( + get_objects_for_user(request.user, "authentik_events.view_event") + .filter(action=filtered_action) + .filter(**query) + .get_events_per_day() + ) + @extend_schema(responses={200: TypeCreateSerializer(many=True)}) @action(detail=False, pagination_class=None, filter_backends=[]) def actions(self, request: Request) -> Response: diff --git a/authentik/events/geo.py b/authentik/events/geo.py index 57e1cd4ed8..45b5c86bbc 100644 --- a/authentik/events/geo.py +++ b/authentik/events/geo.py @@ -7,6 +7,7 @@ from typing import Optional, TypedDict from geoip2.database import Reader from geoip2.errors import GeoIP2Error from geoip2.models import City +from sentry_sdk.hub import Hub from structlog.stdlib import get_logger from authentik.lib.config import CONFIG @@ -62,13 +63,17 @@ class GeoIPReader: def city(self, ip_address: str) -> Optional[City]: """Wrapper for Reader.city""" - if not self.enabled: - return None - self.__check_expired() - try: - return self.__reader.city(ip_address) - except (GeoIP2Error, ValueError): - return None + with Hub.current.start_span( + op="authentik.events.geo.city", + description=ip_address, + ): + if not self.enabled: + return None + self.__check_expired() + try: + return self.__reader.city(ip_address) + except (GeoIP2Error, ValueError): + return None def city_dict(self, ip_address: str) -> Optional[GeoIPDict]: """Wrapper for self.city that returns a dict""" diff --git a/authentik/events/migrations/0001_squashed_0019_alter_notificationtransport_webhook_url.py b/authentik/events/migrations/0001_squashed_0019_alter_notificationtransport_webhook_url.py index 10a3a04aae..57996d3bc9 100644 --- a/authentik/events/migrations/0001_squashed_0019_alter_notificationtransport_webhook_url.py +++ b/authentik/events/migrations/0001_squashed_0019_alter_notificationtransport_webhook_url.py @@ -314,169 +314,10 @@ class Migration(migrations.Migration): old_name="user_json", new_name="user", ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("sign_up", "Sign Up"), - ("authorize_application", "Authorize Application"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("invitation_created", "Invite Created"), - ("invitation_used", "Invite Used"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("custom_", "Custom Prefix"), - ] - ), - ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("invitation_created", "Invite Created"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("custom_", "Custom Prefix"), - ] - ), - ), migrations.RemoveField( model_name="event", name="date", ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("token_view", "Token View"), - ("invitation_created", "Invite Created"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("custom_", "Custom Prefix"), - ] - ), - ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("token_view", "Token View"), - ("invitation_created", "Invite Created"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("policy_execution", "Policy Execution"), - ("policy_exception", "Policy Exception"), - ("property_mapping_exception", "Property Mapping Exception"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("custom_", "Custom Prefix"), - ] - ), - ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("token_view", "Token View"), - ("invitation_created", "Invite Created"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("policy_execution", "Policy Execution"), - ("policy_exception", "Policy Exception"), - ("property_mapping_exception", "Property Mapping Exception"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("update_available", "Update Available"), - ("custom_", "Custom Prefix"), - ] - ), - ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("token_view", "Token View"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("policy_execution", "Policy Execution"), - ("policy_exception", "Policy Exception"), - ("property_mapping_exception", "Property Mapping Exception"), - ("configuration_error", "Configuration Error"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("update_available", "Update Available"), - ("custom_", "Custom Prefix"), - ] - ), - ), migrations.CreateModel( name="NotificationTransport", fields=[ @@ -610,68 +451,6 @@ class Migration(migrations.Migration): help_text="Only send notification once, for example when sending a webhook into a chat channel.", ), ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("token_view", "Token View"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("policy_execution", "Policy Execution"), - ("policy_exception", "Policy Exception"), - ("property_mapping_exception", "Property Mapping Exception"), - ("system_task_execution", "System Task Execution"), - ("system_task_exception", "System Task Exception"), - ("configuration_error", "Configuration Error"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("update_available", "Update Available"), - ("custom_", "Custom Prefix"), - ] - ), - ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("secret_view", "Secret View"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("policy_execution", "Policy Execution"), - ("policy_exception", "Policy Exception"), - ("property_mapping_exception", "Property Mapping Exception"), - ("system_task_execution", "System Task Execution"), - ("system_task_exception", "System Task Exception"), - ("configuration_error", "Configuration Error"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("update_available", "Update Available"), - ("custom_", "Custom Prefix"), - ] - ), - ), migrations.RunPython( code=token_view_to_secret_view, ), @@ -688,76 +467,11 @@ class Migration(migrations.Migration): migrations.RunPython( code=update_expires, ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("secret_view", "Secret View"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("policy_execution", "Policy Execution"), - ("policy_exception", "Policy Exception"), - ("property_mapping_exception", "Property Mapping Exception"), - ("system_task_execution", "System Task Execution"), - ("system_task_exception", "System Task Exception"), - ("configuration_error", "Configuration Error"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("email_sent", "Email Sent"), - ("update_available", "Update Available"), - ("custom_", "Custom Prefix"), - ] - ), - ), migrations.AddField( model_name="event", name="tenant", field=models.JSONField(blank=True, default=authentik.events.models.default_tenant), ), - migrations.AlterField( - model_name="event", - name="action", - field=models.TextField( - choices=[ - ("login", "Login"), - ("login_failed", "Login Failed"), - ("logout", "Logout"), - ("user_write", "User Write"), - ("suspicious_request", "Suspicious Request"), - ("password_set", "Password Set"), - ("secret_view", "Secret View"), - ("invitation_used", "Invite Used"), - ("authorize_application", "Authorize Application"), - ("source_linked", "Source Linked"), - ("impersonation_started", "Impersonation Started"), - ("impersonation_ended", "Impersonation Ended"), - ("policy_execution", "Policy Execution"), - ("policy_exception", "Policy Exception"), - ("property_mapping_exception", "Property Mapping Exception"), - ("system_task_execution", "System Task Execution"), - ("system_task_exception", "System Task Exception"), - ("system_exception", "System Exception"), - ("configuration_error", "Configuration Error"), - ("model_created", "Model Created"), - ("model_updated", "Model Updated"), - ("model_deleted", "Model Deleted"), - ("email_sent", "Email Sent"), - ("update_available", "Update Available"), - ("custom_", "Custom Prefix"), - ] - ), - ), migrations.AlterField( model_name="event", name="action", @@ -776,6 +490,7 @@ class Migration(migrations.Migration): ("source_linked", "Source Linked"), ("impersonation_started", "Impersonation Started"), ("impersonation_ended", "Impersonation Ended"), + ("flow_execution", "Flow Execution"), ("policy_execution", "Policy Execution"), ("policy_exception", "Policy Exception"), ("property_mapping_exception", "Property Mapping Exception"), diff --git a/authentik/events/models.py b/authentik/events/models.py index a2aa89680f..d08ab1e997 100644 --- a/authentik/events/models.py +++ b/authentik/events/models.py @@ -1,4 +1,6 @@ """authentik events models""" +import time +from collections import Counter from datetime import timedelta from inspect import getmodule, stack from smtplib import SMTPException @@ -7,6 +9,12 @@ from uuid import uuid4 from django.conf import settings from django.db import models +from django.db.models import Count, ExpressionWrapper, F +from django.db.models.fields import DurationField +from django.db.models.functions import ExtractHour +from django.db.models.functions.datetime import ExtractDay +from django.db.models.manager import Manager +from django.db.models.query import QuerySet from django.http import HttpRequest from django.http.request import QueryDict from django.utils.timezone import now @@ -70,6 +78,7 @@ class EventAction(models.TextChoices): IMPERSONATION_STARTED = "impersonation_started" IMPERSONATION_ENDED = "impersonation_ended" + FLOW_EXECUTION = "flow_execution" POLICY_EXECUTION = "policy_execution" POLICY_EXCEPTION = "policy_exception" PROPERTY_MAPPING_EXCEPTION = "property_mapping_exception" @@ -90,6 +99,72 @@ class EventAction(models.TextChoices): CUSTOM_PREFIX = "custom_" +class EventQuerySet(QuerySet): + """Custom events query set with helper functions""" + + def get_events_per_hour(self) -> list[dict[str, int]]: + """Get event count by hour in the last day, fill with zeros""" + date_from = now() - timedelta(days=1) + result = ( + self.filter(created__gte=date_from) + .annotate(age=ExpressionWrapper(now() - F("created"), output_field=DurationField())) + .annotate(age_hours=ExtractHour("age")) + .values("age_hours") + .annotate(count=Count("pk")) + .order_by("age_hours") + ) + data = Counter({int(d["age_hours"]): d["count"] for d in result}) + results = [] + _now = now() + for hour in range(0, -24, -1): + results.append( + { + "x_cord": time.mktime((_now + timedelta(hours=hour)).timetuple()) * 1000, + "y_cord": data[hour * -1], + } + ) + return results + + def get_events_per_day(self) -> list[dict[str, int]]: + """Get event count by hour in the last day, fill with zeros""" + date_from = now() - timedelta(weeks=4) + result = ( + self.filter(created__gte=date_from) + .annotate(age=ExpressionWrapper(now() - F("created"), output_field=DurationField())) + .annotate(age_days=ExtractDay("age")) + .values("age_days") + .annotate(count=Count("pk")) + .order_by("age_days") + ) + data = Counter({int(d["age_days"]): d["count"] for d in result}) + results = [] + _now = now() + for day in range(0, -30, -1): + results.append( + { + "x_cord": time.mktime((_now + timedelta(days=day)).timetuple()) * 1000, + "y_cord": data[day * -1], + } + ) + return results + + +class EventManager(Manager): + """Custom helper methods for Events""" + + def get_queryset(self) -> QuerySet: + """use custom queryset""" + return EventQuerySet(self.model, using=self._db) + + def get_events_per_hour(self) -> list[dict[str, int]]: + """Wrap method from queryset""" + return self.get_queryset().get_events_per_hour() + + def get_events_per_day(self) -> list[dict[str, int]]: + """Wrap method from queryset""" + return self.get_queryset().get_events_per_day() + + class Event(ExpiringModel): """An individual Audit/Metrics/Notification/Error Event""" @@ -105,6 +180,8 @@ class Event(ExpiringModel): # Shadow the expires attribute from ExpiringModel to override the default duration expires = models.DateTimeField(default=default_event_duration) + objects = EventManager() + @staticmethod def _get_app_from_request(request: HttpRequest) -> str: if not isinstance(request, HttpRequest): diff --git a/authentik/events/monitored_tasks.py b/authentik/events/monitored_tasks.py index 63330cddf3..1213d85b7e 100644 --- a/authentik/events/monitored_tasks.py +++ b/authentik/events/monitored_tasks.py @@ -46,7 +46,7 @@ class TaskResult: def with_error(self, exc: Exception) -> "TaskResult": """Since errors might not always be pickle-able, set the traceback""" - self.messages.extend(exception_to_string(exc).splitlines()) + self.messages.append(str(exc)) return self diff --git a/authentik/flows/api/stages.py b/authentik/flows/api/stages.py index 59cacb1ca6..d7a3948594 100644 --- a/authentik/flows/api/stages.py +++ b/authentik/flows/api/stages.py @@ -90,7 +90,7 @@ class StageViewSet( stages += list(configurable_stage.objects.all().order_by("name")) matching_stages: list[dict] = [] for stage in stages: - user_settings = stage.ui_user_settings + user_settings = stage.ui_user_settings() if not user_settings: continue user_settings.initial_data["object_uid"] = str(stage.pk) diff --git a/authentik/flows/models.py b/authentik/flows/models.py index dcfb715f03..fa466fb361 100644 --- a/authentik/flows/models.py +++ b/authentik/flows/models.py @@ -75,7 +75,6 @@ class Stage(SerializerModel): """Return component used to edit this object""" raise NotImplementedError - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: """Entrypoint to integrate with User settings. Can either return None if no user settings are available, or a challenge.""" diff --git a/authentik/flows/planner.py b/authentik/flows/planner.py index 5d3fdbd9fd..061b417592 100644 --- a/authentik/flows/planner.py +++ b/authentik/flows/planner.py @@ -126,7 +126,9 @@ class FlowPlanner: ) -> FlowPlan: """Check each of the flows' policies, check policies for each stage with PolicyBinding and return ordered list""" - with Hub.current.start_span(op="flow.planner.plan", description=self.flow.slug) as span: + with Hub.current.start_span( + op="authentik.flow.planner.plan", description=self.flow.slug + ) as span: span: Span span.set_data("flow", self.flow) span.set_data("request", request) @@ -181,7 +183,7 @@ class FlowPlanner: """Build flow plan by checking each stage in their respective order and checking the applied policies""" with Hub.current.start_span( - op="flow.planner.build_plan", + op="authentik.flow.planner.build_plan", description=self.flow.slug, ) as span, HIST_FLOWS_PLAN_TIME.labels(flow_slug=self.flow.slug).time(): span: Span diff --git a/authentik/flows/stage.py b/authentik/flows/stage.py index 4e29637ee1..729f9a07ae 100644 --- a/authentik/flows/stage.py +++ b/authentik/flows/stage.py @@ -6,6 +6,7 @@ from django.http.response import HttpResponse from django.urls import reverse from django.views.generic.base import View from rest_framework.request import Request +from sentry_sdk.hub import Hub from structlog.stdlib import get_logger from authentik.core.models import DEFAULT_AVATAR, User @@ -94,8 +95,16 @@ class ChallengeStageView(StageView): keep_context=keep_context, ) return self.executor.restart_flow(keep_context) - return self.challenge_invalid(challenge) - return self.challenge_valid(challenge) + with Hub.current.start_span( + op="authentik.flow.stage.challenge_invalid", + description=self.__class__.__name__, + ): + return self.challenge_invalid(challenge) + with Hub.current.start_span( + op="authentik.flow.stage.challenge_valid", + description=self.__class__.__name__, + ): + return self.challenge_valid(challenge) def format_title(self) -> str: """Allow usage of placeholder in flow title.""" @@ -104,7 +113,11 @@ class ChallengeStageView(StageView): } def _get_challenge(self, *args, **kwargs) -> Challenge: - challenge = self.get_challenge(*args, **kwargs) + with Hub.current.start_span( + op="authentik.flow.stage.get_challenge", + description=self.__class__.__name__, + ): + challenge = self.get_challenge(*args, **kwargs) if "flow_info" not in challenge.initial_data: flow_info = ContextualFlowInfo( data={ diff --git a/authentik/flows/tests/test_api.py b/authentik/flows/tests/test_api.py index b2ee2d734a..4b1d173ba6 100644 --- a/authentik/flows/tests/test_api.py +++ b/authentik/flows/tests/test_api.py @@ -32,7 +32,7 @@ class TestFlowsAPI(APITestCase): def test_models(self): """Test that ui_user_settings returns none""" - self.assertIsNone(Stage().ui_user_settings) + self.assertIsNone(Stage().ui_user_settings()) def test_api_serializer(self): """Test that stage serializer returns the correct type""" diff --git a/authentik/flows/tests/test_stage_model.py b/authentik/flows/tests/test_stage_model.py index feb3af6908..807442de34 100644 --- a/authentik/flows/tests/test_stage_model.py +++ b/authentik/flows/tests/test_stage_model.py @@ -23,7 +23,7 @@ def model_tester_factory(test_model: Type[Stage]) -> Callable: model_class = test_model() self.assertTrue(issubclass(model_class.type, StageView)) self.assertIsNotNone(test_model.component) - _ = model_class.ui_user_settings + _ = model_class.ui_user_settings() return tester diff --git a/authentik/flows/views/executor.py b/authentik/flows/views/executor.py index 6d017e3325..1e789ac17e 100644 --- a/authentik/flows/views/executor.py +++ b/authentik/flows/views/executor.py @@ -160,7 +160,7 @@ class FlowExecutorView(APIView): # pylint: disable=unused-argument, too-many-return-statements def dispatch(self, request: HttpRequest, flow_slug: str) -> HttpResponse: with Hub.current.start_span( - op="flow.executor.dispatch", description=self.flow.slug + op="authentik.flow.executor.dispatch", description=self.flow.slug ) as span: span.set_data("authentik Flow", self.flow.slug) get_params = QueryDict(request.GET.get("query", "")) @@ -275,7 +275,7 @@ class FlowExecutorView(APIView): ) try: with Hub.current.start_span( - op="flow.executor.stage", + op="authentik.flow.executor.stage", description=class_to_path(self.current_stage_view.__class__), ) as span: span.set_data("Method", "GET") @@ -319,7 +319,7 @@ class FlowExecutorView(APIView): ) try: with Hub.current.start_span( - op="flow.executor.stage", + op="authentik.flow.executor.stage", description=class_to_path(self.current_stage_view.__class__), ) as span: span.set_data("Method", "POST") @@ -371,6 +371,12 @@ class FlowExecutorView(APIView): NEXT_ARG_NAME, "authentik_core:root-redirect" ) self.cancel() + Event.new( + action=EventAction.FLOW_EXECUTION, + flow=self.flow, + designation=self.flow.designation, + successful=True, + ).from_http(self.request) return to_stage_response(self.request, redirect_with_qs(next_param)) def stage_ok(self) -> HttpResponse: diff --git a/authentik/flows/views/inspector.py b/authentik/flows/views/inspector.py index e894dc0f97..6d3fa32a16 100644 --- a/authentik/flows/views/inspector.py +++ b/authentik/flows/views/inspector.py @@ -106,7 +106,7 @@ class FlowInspectorView(APIView): else: try: current_plan = request.session[SESSION_KEY_HISTORY][-1] - except KeyError: + except IndexError: return Response(status=400) is_completed = True current_serializer = FlowInspectorPlanSerializer( diff --git a/authentik/lib/expression/evaluator.py b/authentik/lib/expression/evaluator.py index fe40556b59..b1c5fe2e58 100644 --- a/authentik/lib/expression/evaluator.py +++ b/authentik/lib/expression/evaluator.py @@ -80,8 +80,9 @@ class BaseEvaluator: """Parse and evaluate expression. If the syntax is incorrect, a SyntaxError is raised. If any exception is raised during execution, it is raised. The result is returned without any type-checking.""" - with Hub.current.start_span(op="lib.evaluator.evaluate") as span: + with Hub.current.start_span(op="authentik.lib.evaluator.evaluate") as span: span: Span + span.description = self._filename span.set_data("expression", expression_source) param_keys = self._context.keys() try: diff --git a/authentik/policies/engine.py b/authentik/policies/engine.py index 74dabe513d..d124988545 100644 --- a/authentik/policies/engine.py +++ b/authentik/policies/engine.py @@ -90,7 +90,7 @@ class PolicyEngine: def build(self) -> "PolicyEngine": """Build wrapper which monitors performance""" with Hub.current.start_span( - op="policy.engine.build", + op="authentik.policy.engine.build", description=self.__pbm, ) as span, HIST_POLICIES_BUILD_TIME.labels( object_name=self.__pbm, diff --git a/authentik/policies/event_matcher/migrations/0001_squashed_0018_alter_eventmatcherpolicy_action.py b/authentik/policies/event_matcher/migrations/0001_squashed_0018_alter_eventmatcherpolicy_action.py index e0bf3faaeb..af60245739 100644 --- a/authentik/policies/event_matcher/migrations/0001_squashed_0018_alter_eventmatcherpolicy_action.py +++ b/authentik/policies/event_matcher/migrations/0001_squashed_0018_alter_eventmatcherpolicy_action.py @@ -66,6 +66,7 @@ class Migration(migrations.Migration): ("source_linked", "Source Linked"), ("impersonation_started", "Impersonation Started"), ("impersonation_ended", "Impersonation Ended"), + ("flow_execution", "Flow Execution"), ("policy_execution", "Policy Execution"), ("policy_exception", "Policy Exception"), ("property_mapping_exception", "Property Mapping Exception"), diff --git a/authentik/policies/expression/tests.py b/authentik/policies/expression/tests.py index 1b1b1a279d..fac8338d0c 100644 --- a/authentik/policies/expression/tests.py +++ b/authentik/policies/expression/tests.py @@ -74,4 +74,4 @@ class TestExpressionPolicyAPI(APITestCase): expr = "return True" self.assertEqual(ExpressionPolicySerializer().validate_expression(expr), expr) with self.assertRaises(ValidationError): - print(ExpressionPolicySerializer().validate_expression("/")) + ExpressionPolicySerializer().validate_expression("/") diff --git a/authentik/policies/process.py b/authentik/policies/process.py index f5e07b8d5c..79494690d3 100644 --- a/authentik/policies/process.py +++ b/authentik/policies/process.py @@ -130,7 +130,7 @@ class PolicyProcess(PROCESS_CLASS): def profiling_wrapper(self): """Run with profiling enabled""" with Hub.current.start_span( - op="policy.process.execute", + op="authentik.policy.process.execute", ) as span, HIST_POLICIES_EXECUTION_TIME.labels( binding_order=self.binding.order, binding_target_type=self.binding.target_type, diff --git a/authentik/providers/oauth2/models.py b/authentik/providers/oauth2/models.py index 4dfd8e761e..132bd95dd4 100644 --- a/authentik/providers/oauth2/models.py +++ b/authentik/providers/oauth2/models.py @@ -8,7 +8,6 @@ from datetime import datetime from hashlib import sha256 from typing import Any, Optional, Type from urllib.parse import urlparse -from uuid import uuid4 from dacite import from_dict from django.db import models @@ -225,7 +224,7 @@ class OAuth2Provider(Provider): token = RefreshToken( user=user, provider=self, - refresh_token=uuid4().hex, + refresh_token=generate_key(), expires=timezone.now() + timedelta_from_string(self.token_validity), scope=scope, ) @@ -434,7 +433,7 @@ class RefreshToken(ExpiringModel, BaseGrantModel): """Create access token with a similar format as Okta, Keycloak, ADFS""" token = self.create_id_token(user, request).to_dict() token["cid"] = self.provider.client_id - token["uid"] = uuid4().hex + token["uid"] = generate_key() return self.provider.encode(token) def create_id_token(self, user: User, request: HttpRequest) -> IDToken: diff --git a/authentik/providers/oauth2/views/token.py b/authentik/providers/oauth2/views/token.py index bd0e0d0945..936ce1c0ec 100644 --- a/authentik/providers/oauth2/views/token.py +++ b/authentik/providers/oauth2/views/token.py @@ -194,8 +194,10 @@ class TokenView(View): self.params = TokenParams.parse(request, self.provider, client_id, client_secret) if self.params.grant_type == GRANT_TYPE_AUTHORIZATION_CODE: + LOGGER.info("Converting authorization code to refresh token") return TokenResponse(self.create_code_response()) if self.params.grant_type == GRANT_TYPE_REFRESH_TOKEN: + LOGGER.info("Refreshing refresh token") return TokenResponse(self.create_refresh_response()) raise ValueError(f"Invalid grant_type: {self.params.grant_type}") except TokenError as error: diff --git a/authentik/providers/saml/processors/assertion.py b/authentik/providers/saml/processors/assertion.py index fff3b7b670..c97f30e87b 100644 --- a/authentik/providers/saml/processors/assertion.py +++ b/authentik/providers/saml/processors/assertion.py @@ -70,13 +70,14 @@ class AssertionProcessor: """Get AttributeStatement Element with Attributes from Property Mappings.""" # https://commons.lbl.gov/display/IDMgmt/Attribute+Definitions attribute_statement = Element(f"{{{NS_SAML_ASSERTION}}}AttributeStatement") + user = self.http_request.user for mapping in self.provider.property_mappings.all().select_subclasses(): if not isinstance(mapping, SAMLPropertyMapping): continue try: mapping: SAMLPropertyMapping value = mapping.evaluate( - user=self.http_request.user, + user=user, request=self.http_request, provider=self.provider, ) diff --git a/authentik/sources/ldap/api.py b/authentik/sources/ldap/api.py index 7b1413c4b0..952fa7e86a 100644 --- a/authentik/sources/ldap/api.py +++ b/authentik/sources/ldap/api.py @@ -1,7 +1,6 @@ """Source API Views""" from typing import Any -from django.utils.text import slugify from django_filters.filters import AllValuesMultipleFilter from django_filters.filterset import FilterSet from drf_spectacular.types import OpenApiTypes @@ -110,7 +109,8 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet): GroupLDAPSynchronizer, MembershipLDAPSynchronizer, ]: - task = TaskInfo.by_name(f"ldap_sync_{slugify(source.name)}-{sync_class.__name__}") + sync_name = sync_class.__name__.replace("LDAPSynchronizer", "").lower() + task = TaskInfo.by_name(f"ldap_sync_{source.slug}_{sync_name}") if task: results.append(task) return Response(TaskSerializer(results, many=True).data) diff --git a/authentik/sources/ldap/sync/groups.py b/authentik/sources/ldap/sync/groups.py index 99c1793ad5..7a305a0286 100644 --- a/authentik/sources/ldap/sync/groups.py +++ b/authentik/sources/ldap/sync/groups.py @@ -29,7 +29,7 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer): group_dn = self._flatten(self._flatten(group.get("entryDN", group.get("dn")))) if self._source.object_uniqueness_field not in attributes: self.message( - f"Cannot find uniqueness field in attributes: '{group_dn}", + f"Cannot find uniqueness field in attributes: '{group_dn}'", attributes=attributes.keys(), dn=group_dn, ) diff --git a/authentik/sources/ldap/sync/users.py b/authentik/sources/ldap/sync/users.py index 8038303dab..c4ae4869e0 100644 --- a/authentik/sources/ldap/sync/users.py +++ b/authentik/sources/ldap/sync/users.py @@ -31,7 +31,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer): user_dn = self._flatten(user.get("entryDN", user.get("dn"))) if self._source.object_uniqueness_field not in attributes: self.message( - f"Cannot find uniqueness field in attributes: '{user_dn}", + f"Cannot find uniqueness field in attributes: '{user_dn}'", attributes=attributes.keys(), dn=user_dn, ) diff --git a/authentik/sources/ldap/tasks.py b/authentik/sources/ldap/tasks.py index d83786e2f6..f29eda6239 100644 --- a/authentik/sources/ldap/tasks.py +++ b/authentik/sources/ldap/tasks.py @@ -1,5 +1,4 @@ """LDAP Sync tasks""" -from django.utils.text import slugify from ldap3.core.exceptions import LDAPException from structlog.stdlib import get_logger @@ -39,7 +38,7 @@ def ldap_sync(self: MonitoredTask, source_pk: str, sync_class: str): # to set the state with return sync = path_to_class(sync_class) - self.set_uid(f"{slugify(source.name)}_{sync.__name__.replace('LDAPSynchronizer', '').lower()}") + self.set_uid(f"{source.slug}_{sync.__name__.replace('LDAPSynchronizer', '').lower()}") try: sync_inst = sync(source) count = sync_inst.sync() diff --git a/authentik/sources/oauth/apps.py b/authentik/sources/oauth/apps.py index d89838476c..1dbeb54e16 100644 --- a/authentik/sources/oauth/apps.py +++ b/authentik/sources/oauth/apps.py @@ -14,6 +14,7 @@ AUTHENTIK_SOURCES_OAUTH_TYPES = [ "authentik.sources.oauth.types.github", "authentik.sources.oauth.types.google", "authentik.sources.oauth.types.oidc", + "authentik.sources.oauth.types.okta", "authentik.sources.oauth.types.reddit", "authentik.sources.oauth.types.twitter", ] diff --git a/authentik/sources/oauth/models.py b/authentik/sources/oauth/models.py index 7276d75751..3d44f9e5e1 100644 --- a/authentik/sources/oauth/models.py +++ b/authentik/sources/oauth/models.py @@ -2,13 +2,13 @@ from typing import TYPE_CHECKING, Optional, Type from django.db import models +from django.http.request import HttpRequest from django.urls import reverse from django.utils.translation import gettext_lazy as _ from rest_framework.serializers import Serializer from authentik.core.models import Source, UserSourceConnection from authentik.core.types import UILoginButton, UserSettingSerializer -from authentik.flows.challenge import ChallengeTypes, RedirectChallenge if TYPE_CHECKING: from authentik.sources.oauth.types.manager import SourceType @@ -64,24 +64,15 @@ class OAuthSource(Source): return OAuthSourceSerializer - @property - def ui_login_button(self) -> UILoginButton: + def ui_login_button(self, request: HttpRequest) -> UILoginButton: provider_type = self.type + provider = provider_type() return UILoginButton( - challenge=RedirectChallenge( - instance={ - "type": ChallengeTypes.REDIRECT.value, - "to": reverse( - "authentik_sources_oauth:oauth-client-login", - kwargs={"source_slug": self.slug}, - ), - } - ), - icon_url=provider_type().icon_url(), name=self.name, + icon_url=provider.icon_url(), + challenge=provider.login_challenge(self, request), ) - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: return UserSettingSerializer( data={ @@ -183,6 +174,16 @@ class AppleOAuthSource(OAuthSource): verbose_name_plural = _("Apple OAuth Sources") +class OktaOAuthSource(OAuthSource): + """Login using a okta.com.""" + + class Meta: + + abstract = True + verbose_name = _("Okta OAuth Source") + verbose_name_plural = _("Okta OAuth Sources") + + class UserOAuthSourceConnection(UserSourceConnection): """Authorized remote OAuth provider.""" diff --git a/authentik/sources/oauth/types/apple.py b/authentik/sources/oauth/types/apple.py index 254c9da102..6265b6ccdb 100644 --- a/authentik/sources/oauth/types/apple.py +++ b/authentik/sources/oauth/types/apple.py @@ -2,10 +2,15 @@ from time import time from typing import Any, Optional +from django.http.request import HttpRequest +from django.urls.base import reverse from jwt import decode, encode +from rest_framework.fields import CharField from structlog.stdlib import get_logger +from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes from authentik.sources.oauth.clients.oauth2 import OAuth2Client +from authentik.sources.oauth.models import OAuthSource from authentik.sources.oauth.types.manager import MANAGER, SourceType from authentik.sources.oauth.views.callback import OAuthCallback from authentik.sources.oauth.views.redirect import OAuthRedirect @@ -13,18 +18,34 @@ from authentik.sources.oauth.views.redirect import OAuthRedirect LOGGER = get_logger() +class AppleLoginChallenge(Challenge): + """Special challenge for apple-native authentication flow, which happens on the client.""" + + client_id = CharField() + component = CharField(default="ak-flow-sources-oauth-apple") + scope = CharField() + redirect_uri = CharField() + state = CharField() + + +class AppleChallengeResponse(ChallengeResponse): + """Pseudo class for plex response""" + + component = CharField(default="ak-flow-sources-oauth-apple") + + class AppleOAuthClient(OAuth2Client): """Apple OAuth2 client""" def get_client_id(self) -> str: - parts = self.source.consumer_key.split(";") + parts: list[str] = self.source.consumer_key.split(";") if len(parts) < 3: return self.source.consumer_key - return parts[0] + return parts[0].strip() def get_client_secret(self) -> str: now = time() - parts = self.source.consumer_key.split(";") + parts: list[str] = self.source.consumer_key.split(";") if len(parts) < 3: raise ValueError( ( @@ -34,14 +55,14 @@ class AppleOAuthClient(OAuth2Client): ) LOGGER.debug("got values from client_id", team=parts[1], kid=parts[2]) payload = { - "iss": parts[1], + "iss": parts[1].strip(), "iat": now, "exp": now + 86400 * 180, "aud": "https://appleid.apple.com", - "sub": parts[0], + "sub": parts[0].strip(), } # pyright: reportGeneralTypeIssues=false - jwt = encode(payload, self.source.consumer_secret, "ES256", {"kid": parts[2]}) + jwt = encode(payload, self.source.consumer_secret, "ES256", {"kid": parts[2].strip()}) LOGGER.debug("signing payload as secret key", payload=payload, jwt=jwt) return jwt @@ -55,7 +76,7 @@ class AppleOAuthRedirect(OAuthRedirect): client_class = AppleOAuthClient - def get_additional_parameters(self, source): # pragma: no cover + def get_additional_parameters(self, source: OAuthSource): # pragma: no cover return { "scope": "name email", "response_mode": "form_post", @@ -74,7 +95,6 @@ class AppleOAuth2Callback(OAuthCallback): self, info: dict[str, Any], ) -> dict[str, Any]: - print(info) return { "email": info.get("email"), "name": info.get("name"), @@ -96,3 +116,24 @@ class AppleType(SourceType): def icon_url(self) -> str: return "https://appleid.cdn-apple.com/appleid/button/logo" + + def login_challenge(self, source: OAuthSource, request: HttpRequest) -> Challenge: + """Pre-general all the things required for the JS SDK""" + apple_client = AppleOAuthClient( + source, + request, + callback=reverse( + "authentik_sources_oauth:oauth-client-callback", + kwargs={"source_slug": source.slug}, + ), + ) + args = apple_client.get_redirect_args() + return AppleLoginChallenge( + instance={ + "client_id": apple_client.get_client_id(), + "scope": "name email", + "redirect_uri": args["redirect_uri"], + "state": args["state"], + "type": ChallengeTypes.NATIVE.value, + } + ) diff --git a/authentik/sources/oauth/types/manager.py b/authentik/sources/oauth/types/manager.py index f619148d8b..d88215dca6 100644 --- a/authentik/sources/oauth/types/manager.py +++ b/authentik/sources/oauth/types/manager.py @@ -2,9 +2,13 @@ from enum import Enum from typing import Callable, Optional, Type +from django.http.request import HttpRequest from django.templatetags.static import static +from django.urls.base import reverse from structlog.stdlib import get_logger +from authentik.flows.challenge import Challenge, ChallengeTypes, RedirectChallenge +from authentik.sources.oauth.models import OAuthSource from authentik.sources.oauth.views.callback import OAuthCallback from authentik.sources.oauth.views.redirect import OAuthRedirect @@ -37,6 +41,19 @@ class SourceType: """Get Icon URL for login""" return static(f"authentik/sources/{self.slug}.svg") + # pylint: disable=unused-argument + def login_challenge(self, source: OAuthSource, request: HttpRequest) -> Challenge: + """Allow types to return custom challenges""" + return RedirectChallenge( + instance={ + "type": ChallengeTypes.REDIRECT.value, + "to": reverse( + "authentik_sources_oauth:oauth-client-login", + kwargs={"source_slug": source.slug}, + ), + } + ) + class SourceTypeManager: """Manager to hold all Source types.""" diff --git a/authentik/sources/oauth/types/okta.py b/authentik/sources/oauth/types/okta.py new file mode 100644 index 0000000000..5f03bda535 --- /dev/null +++ b/authentik/sources/oauth/types/okta.py @@ -0,0 +1,51 @@ +"""Okta OAuth Views""" +from typing import Any + +from authentik.sources.oauth.models import OAuthSource +from authentik.sources.oauth.types.azure_ad import AzureADClient +from authentik.sources.oauth.types.manager import MANAGER, SourceType +from authentik.sources.oauth.views.callback import OAuthCallback +from authentik.sources.oauth.views.redirect import OAuthRedirect + + +class OktaOAuthRedirect(OAuthRedirect): + """Okta OAuth2 Redirect""" + + def get_additional_parameters(self, source: OAuthSource): # pragma: no cover + return { + "scope": "openid email profile", + } + + +class OktaOAuth2Callback(OAuthCallback): + """Okta OAuth2 Callback""" + + # Okta has the same quirk as azure and throws an error if the access token + # is set via query parameter, so we re-use the azure client + # see https://github.com/goauthentik/authentik/issues/1910 + client_class = AzureADClient + + def get_user_id(self, info: dict[str, str]) -> str: + return info.get("sub", "") + + def get_user_enroll_context( + self, + info: dict[str, Any], + ) -> dict[str, Any]: + return { + "username": info.get("nickname"), + "email": info.get("email"), + "name": info.get("name"), + } + + +@MANAGER.type() +class OktaType(SourceType): + """Okta Type definition""" + + callback_view = OktaOAuth2Callback + redirect_view = OktaOAuthRedirect + name = "Okta" + slug = "okta" + + urls_customizable = True diff --git a/authentik/sources/plex/models.py b/authentik/sources/plex/models.py index 6ccb0293ac..c16fd28dde 100644 --- a/authentik/sources/plex/models.py +++ b/authentik/sources/plex/models.py @@ -3,6 +3,7 @@ from typing import Optional from django.contrib.postgres.fields import ArrayField from django.db import models +from django.http.request import HttpRequest from django.templatetags.static import static from django.utils.translation import gettext_lazy as _ from rest_framework.fields import CharField @@ -62,8 +63,7 @@ class PlexSource(Source): return PlexSourceSerializer - @property - def ui_login_button(self) -> UILoginButton: + def ui_login_button(self, request: HttpRequest) -> UILoginButton: return UILoginButton( challenge=PlexAuthenticationChallenge( { @@ -77,7 +77,6 @@ class PlexSource(Source): name=self.name, ) - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: return UserSettingSerializer( data={ diff --git a/authentik/sources/saml/models.py b/authentik/sources/saml/models.py index 4127667575..882050fc3b 100644 --- a/authentik/sources/saml/models.py +++ b/authentik/sources/saml/models.py @@ -167,8 +167,7 @@ class SAMLSource(Source): reverse(f"authentik_sources_saml:{view}", kwargs={"source_slug": self.slug}) ) - @property - def ui_login_button(self) -> UILoginButton: + def ui_login_button(self, request: HttpRequest) -> UILoginButton: return UILoginButton( challenge=RedirectChallenge( instance={ diff --git a/authentik/stages/authenticator_duo/models.py b/authentik/stages/authenticator_duo/models.py index 4e9db04781..e69e7366b5 100644 --- a/authentik/stages/authenticator_duo/models.py +++ b/authentik/stages/authenticator_duo/models.py @@ -48,7 +48,6 @@ class AuthenticatorDuoStage(ConfigurableStage, Stage): def component(self) -> str: return "ak-stage-authenticator-duo-form" - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: return UserSettingSerializer( data={ diff --git a/authentik/stages/authenticator_sms/models.py b/authentik/stages/authenticator_sms/models.py index 1fb9dbbdf6..1deaa89daf 100644 --- a/authentik/stages/authenticator_sms/models.py +++ b/authentik/stages/authenticator_sms/models.py @@ -141,7 +141,6 @@ class AuthenticatorSMSStage(ConfigurableStage, Stage): def component(self) -> str: return "ak-stage-authenticator-sms-form" - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: return UserSettingSerializer( data={ diff --git a/authentik/stages/authenticator_sms/tests.py b/authentik/stages/authenticator_sms/tests.py index cb65c22563..a7c56d422a 100644 --- a/authentik/stages/authenticator_sms/tests.py +++ b/authentik/stages/authenticator_sms/tests.py @@ -90,6 +90,5 @@ class AuthenticatorSMSStageTests(APITestCase): "code": int(self.client.session[SESSION_SMS_DEVICE].token), }, ) - print(response.content) self.assertEqual(response.status_code, 200) sms_send_mock.assert_not_called() diff --git a/authentik/stages/authenticator_static/models.py b/authentik/stages/authenticator_static/models.py index 5b26ca8aa4..ad7f0f65ed 100644 --- a/authentik/stages/authenticator_static/models.py +++ b/authentik/stages/authenticator_static/models.py @@ -31,7 +31,6 @@ class AuthenticatorStaticStage(ConfigurableStage, Stage): def component(self) -> str: return "ak-stage-authenticator-static-form" - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: return UserSettingSerializer( data={ diff --git a/authentik/stages/authenticator_totp/models.py b/authentik/stages/authenticator_totp/models.py index 9b36fe3031..139a66f0be 100644 --- a/authentik/stages/authenticator_totp/models.py +++ b/authentik/stages/authenticator_totp/models.py @@ -38,7 +38,6 @@ class AuthenticatorTOTPStage(ConfigurableStage, Stage): def component(self) -> str: return "ak-stage-authenticator-totp-form" - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: return UserSettingSerializer( data={ diff --git a/authentik/stages/authenticator_webauthn/api.py b/authentik/stages/authenticator_webauthn/api.py index 7c7d4be54a..57d04cbc85 100644 --- a/authentik/stages/authenticator_webauthn/api.py +++ b/authentik/stages/authenticator_webauthn/api.py @@ -18,7 +18,7 @@ class AuthenticateWebAuthnStageSerializer(StageSerializer): class Meta: model = AuthenticateWebAuthnStage - fields = StageSerializer.Meta.fields + ["configure_flow"] + fields = StageSerializer.Meta.fields + ["configure_flow", "user_verification"] class AuthenticateWebAuthnStageViewSet(UsedByMixin, ModelViewSet): diff --git a/authentik/stages/authenticator_webauthn/migrations/0005_authenticatewebauthnstage_user_verification.py b/authentik/stages/authenticator_webauthn/migrations/0005_authenticatewebauthnstage_user_verification.py new file mode 100644 index 0000000000..12c4b18158 --- /dev/null +++ b/authentik/stages/authenticator_webauthn/migrations/0005_authenticatewebauthnstage_user_verification.py @@ -0,0 +1,25 @@ +# Generated by Django 4.0 on 2021-12-14 09:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_stages_authenticator_webauthn", "0004_auto_20210304_1850"), + ] + + operations = [ + migrations.AddField( + model_name="authenticatewebauthnstage", + name="user_verification", + field=models.TextField( + choices=[ + ("required", "Required"), + ("preferred", "Preferred"), + ("discouraged", "Discouraged"), + ], + default="preferred", + ), + ), + ] diff --git a/authentik/stages/authenticator_webauthn/models.py b/authentik/stages/authenticator_webauthn/models.py index a28b52c8bb..cfcba99063 100644 --- a/authentik/stages/authenticator_webauthn/models.py +++ b/authentik/stages/authenticator_webauthn/models.py @@ -15,9 +15,30 @@ from authentik.core.types import UserSettingSerializer from authentik.flows.models import ConfigurableStage, Stage +class UserVerification(models.TextChoices): + """The degree to which the Relying Party wishes to verify a user's identity. + + Members: + `REQUIRED`: User verification must occur + `PREFERRED`: User verification would be great, but if not that's okay too + `DISCOURAGED`: User verification should not occur, but it's okay if it does + + https://www.w3.org/TR/webauthn-2/#enumdef-userverificationrequirement + """ + + REQUIRED = "required" + PREFERRED = "preferred" + DISCOURAGED = "discouraged" + + class AuthenticateWebAuthnStage(ConfigurableStage, Stage): """WebAuthn stage""" + user_verification = models.TextField( + choices=UserVerification.choices, + default=UserVerification.PREFERRED, + ) + @property def serializer(self) -> BaseSerializer: from authentik.stages.authenticator_webauthn.api import AuthenticateWebAuthnStageSerializer @@ -34,7 +55,6 @@ class AuthenticateWebAuthnStage(ConfigurableStage, Stage): def component(self) -> str: return "ak-stage-authenticator-webauthn-form" - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: return UserSettingSerializer( data={ diff --git a/authentik/stages/authenticator_webauthn/stage.py b/authentik/stages/authenticator_webauthn/stage.py index 53a1926261..071e0e52ed 100644 --- a/authentik/stages/authenticator_webauthn/stage.py +++ b/authentik/stages/authenticator_webauthn/stage.py @@ -14,7 +14,6 @@ from webauthn.helpers.structs import ( PublicKeyCredentialCreationOptions, RegistrationCredential, ResidentKeyRequirement, - UserVerificationRequirement, ) from webauthn.registration.verify_registration_response import VerifiedRegistration @@ -27,7 +26,7 @@ from authentik.flows.challenge import ( ) from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.flows.stage import ChallengeStageView -from authentik.stages.authenticator_webauthn.models import WebAuthnDevice +from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnStage, WebAuthnDevice from authentik.stages.authenticator_webauthn.utils import get_origin, get_rp_id LOGGER = get_logger() @@ -83,7 +82,7 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView): def get_challenge(self, *args, **kwargs) -> Challenge: # clear session variables prior to starting a new registration self.request.session.pop("challenge", None) - + stage: AuthenticateWebAuthnStage = self.executor.current_stage user = self.get_pending_user() registration_options: PublicKeyCredentialCreationOptions = generate_registration_options( @@ -94,10 +93,9 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView): user_display_name=user.name, authenticator_selection=AuthenticatorSelectionCriteria( resident_key=ResidentKeyRequirement.PREFERRED, - user_verification=UserVerificationRequirement.PREFERRED, + user_verification=str(stage.user_verification), ), ) - registration_options.user.id = user.uid self.request.session["challenge"] = registration_options.challenge return AuthenticatorWebAuthnChallenge( diff --git a/authentik/stages/email/tests/test_api.py b/authentik/stages/email/tests/test_api.py index 56c8098709..ca501d321d 100644 --- a/authentik/stages/email/tests/test_api.py +++ b/authentik/stages/email/tests/test_api.py @@ -29,4 +29,4 @@ class TestEmailStageAPI(APITestCase): EmailTemplates.ACCOUNT_CONFIRM, ) with self.assertRaises(ValidationError): - print(EmailStageSerializer().validate_template("foobar")) + EmailStageSerializer().validate_template("foobar") diff --git a/authentik/stages/identification/stage.py b/authentik/stages/identification/stage.py index 925a936e07..97f8a6c06c 100644 --- a/authentik/stages/identification/stage.py +++ b/authentik/stages/identification/stage.py @@ -12,6 +12,7 @@ from django.utils.translation import gettext as _ from drf_spectacular.utils import PolymorphicProxySerializer, extend_schema_field from rest_framework.fields import BooleanField, CharField, DictField, ListField from rest_framework.serializers import ValidationError +from sentry_sdk.hub import Hub from structlog.stdlib import get_logger from authentik.core.api.utils import PassiveSerializer @@ -25,6 +26,7 @@ from authentik.flows.challenge import ( from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, ChallengeStageView from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE +from authentik.sources.oauth.types.apple import AppleLoginChallenge from authentik.sources.plex.models import PlexAuthenticationChallenge from authentik.stages.identification.models import IdentificationStage from authentik.stages.identification.signals import identification_failed @@ -39,6 +41,7 @@ LOGGER = get_logger() serializers={ RedirectChallenge().fields["component"].default: RedirectChallenge, PlexAuthenticationChallenge().fields["component"].default: PlexAuthenticationChallenge, + AppleLoginChallenge().fields["component"].default: AppleLoginChallenge, }, resource_type_field_name="component", ) @@ -88,8 +91,12 @@ class IdentificationChallengeResponse(ChallengeResponse): pre_user = self.stage.get_user(uid_field) if not pre_user: - # Sleep a random time (between 90 and 210ms) to "prevent" user enumeration attacks - sleep(0.30 * SystemRandom().randint(3, 7)) + with Hub.current.start_span( + op="authentik.stages.identification.validate_invalid_wait", + description="Sleep random time on invalid user identifier", + ): + # Sleep a random time (between 90 and 210ms) to "prevent" user enumeration attacks + sleep(0.030 * SystemRandom().randint(3, 7)) LOGGER.debug("invalid_login", identifier=uid_field) identification_failed.send(sender=self, request=self.stage.request, uid_field=uid_field) # We set the pending_user even on failure so it's part of the context, even @@ -112,12 +119,16 @@ class IdentificationChallengeResponse(ChallengeResponse): if not password: LOGGER.warning("Password not set for ident+auth attempt") try: - user = authenticate( - self.stage.request, - current_stage.password_stage.backends, - username=self.pre_user.username, - password=password, - ) + with Hub.current.start_span( + op="authentik.stages.identification.authenticate", + description="User authenticate call (combo stage)", + ): + user = authenticate( + self.stage.request, + current_stage.password_stage.backends, + username=self.pre_user.username, + password=password, + ) if not user: raise ValidationError("Failed to authenticate.") self.pre_user = user @@ -191,7 +202,7 @@ class IdentificationStageView(ChallengeStageView): current_stage.sources.filter(enabled=True).order_by("name").select_subclasses() ) for source in sources: - ui_login_button = source.ui_login_button + ui_login_button = source.ui_login_button(self.request) if ui_login_button: button = asdict(ui_login_button) button["challenge"] = ui_login_button.challenge.data diff --git a/authentik/stages/invitation/api.py b/authentik/stages/invitation/api.py index 8e85bcb1b9..9132504b93 100644 --- a/authentik/stages/invitation/api.py +++ b/authentik/stages/invitation/api.py @@ -5,8 +5,8 @@ from rest_framework.fields import JSONField from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet +from authentik.core.api.groups import GroupMemberSerializer from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.users import UserSerializer from authentik.core.api.utils import is_dict from authentik.flows.api.stages import StageSerializer from authentik.stages.invitation.models import Invitation, InvitationStage @@ -46,7 +46,7 @@ class InvitationStageViewSet(UsedByMixin, ModelViewSet): class InvitationSerializer(ModelSerializer): """Invitation Serializer""" - created_by = UserSerializer(read_only=True) + created_by = GroupMemberSerializer(read_only=True) fixed_data = JSONField(validators=[is_dict], required=False) class Meta: diff --git a/authentik/stages/password/models.py b/authentik/stages/password/models.py index 5369052a25..4ee783c912 100644 --- a/authentik/stages/password/models.py +++ b/authentik/stages/password/models.py @@ -63,7 +63,6 @@ class PasswordStage(ConfigurableStage, Stage): def component(self) -> str: return "ak-stage-password-form" - @property def ui_user_settings(self) -> Optional[UserSettingSerializer]: if not self.configure_flow: return None diff --git a/authentik/stages/password/stage.py b/authentik/stages/password/stage.py index ddcfe84dcb..c353102c52 100644 --- a/authentik/stages/password/stage.py +++ b/authentik/stages/password/stage.py @@ -10,6 +10,7 @@ from django.urls import reverse from django.utils.translation import gettext as _ from rest_framework.exceptions import ErrorDetail, ValidationError from rest_framework.fields import CharField +from sentry_sdk.hub import Hub from structlog.stdlib import get_logger from authentik.core.models import User @@ -43,7 +44,11 @@ def authenticate(request: HttpRequest, backends: list[str], **credentials: Any) LOGGER.warning("Failed to import backend", path=backend_path) continue LOGGER.debug("Attempting authentication...", backend=backend_path) - user = backend.authenticate(request, **credentials) + with Hub.current.start_span( + op="authentik.stages.password.authenticate", + description=backend_path, + ): + user = backend.authenticate(request, **credentials) if user is None: LOGGER.debug("Backend returned nothing, continuing", backend=backend_path) continue @@ -120,7 +125,13 @@ class PasswordStageView(ChallengeStageView): "username": pending_user.username, } try: - user = authenticate(self.request, self.executor.current_stage.backends, **auth_kwargs) + with Hub.current.start_span( + op="authentik.stages.password.authenticate", + description="User authenticate call", + ): + user = authenticate( + self.request, self.executor.current_stage.backends, **auth_kwargs + ) except PermissionDenied: del auth_kwargs["password"] # User was found, but permission was denied (i.e. user is not active) diff --git a/authentik/tenants/utils.py b/authentik/tenants/utils.py index c96c3cad2b..a59fd49c2f 100644 --- a/authentik/tenants/utils.py +++ b/authentik/tenants/utils.py @@ -4,6 +4,7 @@ from typing import Any from django.db.models import F, Q from django.db.models import Value as V from django.http.request import HttpRequest +from sentry_sdk.hub import Hub from authentik.lib.config import CONFIG from authentik.tenants.models import Tenant @@ -28,7 +29,12 @@ def get_tenant_for_request(request: HttpRequest) -> Tenant: def context_processor(request: HttpRequest) -> dict[str, Any]: """Context Processor that injects tenant object into every template""" tenant = getattr(request, "tenant", DEFAULT_TENANT) + trace = "" + span = Hub.current.scope.span + if span: + trace = span.to_traceparent() return { "tenant": tenant, "footer_links": CONFIG.y("footer_links"), + "sentry_trace": trace, } diff --git a/go.mod b/go.mod index a1c2e08fe0..96dd347e2d 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac // indirect github.com/prometheus/client_golang v1.11.0 github.com/sirupsen/logrus v1.8.1 - goauthentik.io/api v0.2021104.11 + goauthentik.io/api v0.2021104.17 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 diff --git a/go.sum b/go.sum index 813f1d18f6..d5bc347139 100644 --- a/go.sum +++ b/go.sum @@ -558,8 +558,8 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -goauthentik.io/api v0.2021104.11 h1:LqT0LM0e/RRrxPuo6Xl5uz3PCR5ytuE+YlNlfW9w0yU= -goauthentik.io/api v0.2021104.11/go.mod h1:02nnD4FRd8lu8A1+ZuzqownBgvAhdCKzqkKX8v7JMTE= +goauthentik.io/api v0.2021104.17 h1:NnfdoIlAekwPu+G7h7X/SGbWjWSypEy/pGQDD7/J+Vw= +goauthentik.io/api v0.2021104.17/go.mod h1:02nnD4FRd8lu8A1+ZuzqownBgvAhdCKzqkKX8v7JMTE= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/internal/outpost/ak/api.go b/internal/outpost/ak/api.go index e054e354c2..bd3de10483 100644 --- a/internal/outpost/ak/api.go +++ b/internal/outpost/ak/api.go @@ -47,7 +47,7 @@ type APIController struct { // NewAPIController initialise new API Controller instance from URL and API token func NewAPIController(akURL url.URL, token string) *APIController { - rsp := sentry.StartSpan(context.TODO(), "authentik.outposts.init") + rsp := sentry.StartSpan(context.Background(), "authentik.outposts.init") config := api.NewConfiguration() config.Host = akURL.Host diff --git a/internal/outpost/ak/api_ws.go b/internal/outpost/ak/api_ws.go index c1beb69a9b..64a52dc951 100644 --- a/internal/outpost/ak/api_ws.go +++ b/internal/outpost/ak/api_ws.go @@ -107,6 +107,7 @@ func (ac *APIController) reconnectWS() { } } else { ac.wsIsReconnecting = false + ac.wsBackoffMultiplier = 1 return } } diff --git a/internal/outpost/ak/http_tracing.go b/internal/outpost/ak/http_tracing.go index 4f267d403e..fb73ec1763 100644 --- a/internal/outpost/ak/http_tracing.go +++ b/internal/outpost/ak/http_tracing.go @@ -2,6 +2,7 @@ package ak import ( "context" + "fmt" "net/http" "github.com/getsentry/sentry-go" @@ -19,6 +20,8 @@ func NewTracingTransport(ctx context.Context, inner http.RoundTripper) *tracingT func (tt *tracingTransport) RoundTrip(r *http.Request) (*http.Response, error) { span := sentry.StartSpan(tt.ctx, "authentik.go.http_request") + r.Header.Set("sentry-trace", span.ToSentryTrace()) + span.Description = fmt.Sprintf("%s %s", r.Method, r.URL.String()) span.SetTag("url", r.URL.String()) span.SetTag("method", r.Method) defer span.Finish() diff --git a/internal/outpost/proxyv2/application/application.go b/internal/outpost/proxyv2/application/application.go index c88bc9b543..b500a5773b 100644 --- a/internal/outpost/proxyv2/application/application.go +++ b/internal/outpost/proxyv2/application/application.go @@ -168,6 +168,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore func (a *Application) IsAllowlisted(r *http.Request) bool { for _, u := range a.UnauthenticatedRegex { + a.log.WithField("regex", u.String()).WithField("url", r.URL.Path).Trace("Matching URL against allow list") if u.MatchString(r.URL.Path) { return true } diff --git a/internal/outpost/proxyv2/application/session.go b/internal/outpost/proxyv2/application/session.go index 6da1b20d2c..2407a7577c 100644 --- a/internal/outpost/proxyv2/application/session.go +++ b/internal/outpost/proxyv2/application/session.go @@ -2,6 +2,7 @@ package application import ( "fmt" + "math" "os" "strconv" @@ -18,6 +19,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig) sessions.Store { if err != nil { panic(err) } + rs.SetMaxLength(math.MaxInt64) if p.TokenValidity.IsSet() { t := p.TokenValidity.Get() // Add one to the validity to ensure we don't have a session with indefinite length @@ -27,14 +29,22 @@ func (a *Application) getStore(p api.ProxyOutpostConfig) sessions.Store { a.log.Info("using redis session backend") store = rs } else { - cs := sessions.NewFilesystemStore(os.TempDir(), []byte(*p.CookieSecret)) + dir := os.TempDir() + cs := sessions.NewFilesystemStore(dir, []byte(*p.CookieSecret)) cs.Options.Domain = *p.CookieDomain + // https://github.com/markbates/goth/commit/7276be0fdf719ddff753f3574ef0f967e4a5a5f7 + // set the maxLength of the cookies stored on the disk to a larger number to prevent issues with: + // securecookie: the value is too long + // when using OpenID Connect , since this can contain a large amount of extra information in the id_token + + // Note, when using the FilesystemStore only the session.ID is written to a browser cookie, so this is explicit for the storage on disk + cs.MaxLength(math.MaxInt64) if p.TokenValidity.IsSet() { t := p.TokenValidity.Get() // Add one to the validity to ensure we don't have a session with indefinite length cs.Options.MaxAge = int(*t) + 1 } - a.log.Info("using filesystem session backend") + a.log.WithField("dir", dir).Info("using filesystem session backend") store = cs } return store diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 0d69d5ab99..1111fcd776 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-28 20:14+0000\n" +"POT-Creation-Date: 2021-12-14 21:03+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -39,99 +39,99 @@ msgstr "" msgid "Create a SAML Provider by importing its Metadata." msgstr "" -#: authentik/core/models.py:69 +#: authentik/core/models.py:68 msgid "name" msgstr "" -#: authentik/core/models.py:71 +#: authentik/core/models.py:70 msgid "Users added to this group will be superusers." msgstr "" -#: authentik/core/models.py:129 +#: authentik/core/models.py:128 msgid "User's display name." msgstr "" -#: authentik/core/models.py:196 authentik/providers/oauth2/models.py:315 +#: authentik/core/models.py:195 authentik/providers/oauth2/models.py:314 msgid "User" msgstr "" -#: authentik/core/models.py:197 +#: authentik/core/models.py:196 msgid "Users" msgstr "" -#: authentik/core/models.py:208 +#: authentik/core/models.py:207 msgid "Flow used when authorizing this provider." msgstr "" -#: authentik/core/models.py:241 +#: authentik/core/models.py:240 msgid "Application's display Name." msgstr "" -#: authentik/core/models.py:242 +#: authentik/core/models.py:241 msgid "Internal application name, used in URLs." msgstr "" -#: authentik/core/models.py:289 +#: authentik/core/models.py:288 msgid "Application" msgstr "" -#: authentik/core/models.py:290 +#: authentik/core/models.py:289 msgid "Applications" msgstr "" -#: authentik/core/models.py:296 +#: authentik/core/models.py:295 msgid "Use the source-specific identifier" msgstr "" -#: authentik/core/models.py:304 +#: authentik/core/models.py:303 msgid "" "Use the user's email address, but deny enrollment when the email address " "already exists." msgstr "" -#: authentik/core/models.py:313 +#: authentik/core/models.py:312 msgid "" "Use the user's username, but deny enrollment when the username already " "exists." msgstr "" -#: authentik/core/models.py:320 +#: authentik/core/models.py:319 msgid "Source's display Name." msgstr "" -#: authentik/core/models.py:321 +#: authentik/core/models.py:320 msgid "Internal source name, used in URLs." msgstr "" -#: authentik/core/models.py:332 +#: authentik/core/models.py:331 msgid "Flow to use when authenticating existing users." msgstr "" -#: authentik/core/models.py:341 +#: authentik/core/models.py:340 msgid "Flow to use when enrolling new users." msgstr "" -#: authentik/core/models.py:473 +#: authentik/core/models.py:470 msgid "Token" msgstr "" -#: authentik/core/models.py:474 +#: authentik/core/models.py:471 msgid "Tokens" msgstr "" -#: authentik/core/models.py:517 +#: authentik/core/models.py:514 msgid "Property Mapping" msgstr "" -#: authentik/core/models.py:518 +#: authentik/core/models.py:515 msgid "Property Mappings" msgstr "" -#: authentik/core/models.py:554 +#: authentik/core/models.py:551 msgid "Authenticated Session" msgstr "" -#: authentik/core/models.py:555 +#: authentik/core/models.py:552 msgid "Authenticated Sessions" msgstr "" @@ -204,111 +204,116 @@ msgstr "" msgid "Powered by authentik" msgstr "" -#: authentik/crypto/api.py:120 +#: authentik/crypto/api.py:121 msgid "Subject-alt name" msgstr "" -#: authentik/crypto/models.py:26 +#: authentik/crypto/models.py:29 msgid "PEM-encoded Certificate data" msgstr "" -#: authentik/crypto/models.py:29 +#: authentik/crypto/models.py:32 msgid "" "Optional Private Key. If this is set, you can use this keypair for " "encryption." msgstr "" -#: authentik/crypto/models.py:89 +#: authentik/crypto/models.py:93 msgid "Certificate-Key Pair" msgstr "" -#: authentik/crypto/models.py:90 +#: authentik/crypto/models.py:94 msgid "Certificate-Key Pairs" msgstr "" -#: authentik/events/models.py:207 +#: authentik/crypto/tasks.py:90 +#, python-format +msgid "Successfully imported %(count)d files." +msgstr "" + +#: authentik/events/models.py:284 msgid "Event" msgstr "" -#: authentik/events/models.py:208 +#: authentik/events/models.py:285 msgid "Events" msgstr "" -#: authentik/events/models.py:214 +#: authentik/events/models.py:291 msgid "Generic Webhook" msgstr "" -#: authentik/events/models.py:215 +#: authentik/events/models.py:292 msgid "Slack Webhook (Slack/Discord)" msgstr "" -#: authentik/events/models.py:216 +#: authentik/events/models.py:293 msgid "Email" msgstr "" -#: authentik/events/models.py:234 +#: authentik/events/models.py:311 msgid "" "Only send notification once, for example when sending a webhook into a chat " "channel." msgstr "" -#: authentik/events/models.py:279 +#: authentik/events/models.py:356 msgid "Severity" msgstr "" -#: authentik/events/models.py:284 +#: authentik/events/models.py:361 msgid "Dispatched for user" msgstr "" -#: authentik/events/models.py:361 +#: authentik/events/models.py:438 msgid "Notification Transport" msgstr "" -#: authentik/events/models.py:362 +#: authentik/events/models.py:439 msgid "Notification Transports" msgstr "" -#: authentik/events/models.py:368 +#: authentik/events/models.py:445 msgid "Notice" msgstr "" -#: authentik/events/models.py:369 +#: authentik/events/models.py:446 msgid "Warning" msgstr "" -#: authentik/events/models.py:370 +#: authentik/events/models.py:447 msgid "Alert" msgstr "" -#: authentik/events/models.py:390 +#: authentik/events/models.py:467 msgid "Notification" msgstr "" -#: authentik/events/models.py:391 +#: authentik/events/models.py:468 msgid "Notifications" msgstr "" -#: authentik/events/models.py:410 +#: authentik/events/models.py:487 msgid "Controls which severity level the created notifications will have." msgstr "" -#: authentik/events/models.py:430 +#: authentik/events/models.py:507 msgid "Notification Rule" msgstr "" -#: authentik/events/models.py:431 +#: authentik/events/models.py:508 msgid "Notification Rules" msgstr "" -#: authentik/events/models.py:452 +#: authentik/events/models.py:529 msgid "Notification Webhook Mapping" msgstr "" -#: authentik/events/models.py:453 +#: authentik/events/models.py:530 msgid "Notification Webhook Mappings" msgstr "" -#: authentik/events/monitored_tasks.py:125 +#: authentik/events/monitored_tasks.py:197 msgid "Task has not been run yet." msgstr "" @@ -317,37 +322,37 @@ msgstr "" msgid "Flow not applicable to current user/request: %(messages)s" msgstr "" -#: authentik/flows/models.py:104 +#: authentik/flows/models.py:107 msgid "Visible in the URL." msgstr "" -#: authentik/flows/models.py:106 +#: authentik/flows/models.py:109 msgid "Shown as the Title in Flow pages." msgstr "" -#: authentik/flows/models.py:123 +#: authentik/flows/models.py:126 msgid "Background shown during execution" msgstr "" -#: authentik/flows/models.py:130 +#: authentik/flows/models.py:133 msgid "" "Enable compatibility mode, increases compatibility with password managers on " "mobile devices." msgstr "" -#: authentik/flows/models.py:175 +#: authentik/flows/models.py:178 msgid "Flow" msgstr "" -#: authentik/flows/models.py:176 +#: authentik/flows/models.py:179 msgid "Flows" msgstr "" -#: authentik/flows/models.py:206 +#: authentik/flows/models.py:209 msgid "Evaluate policies when the Stage is present to the user." msgstr "" -#: authentik/flows/models.py:213 +#: authentik/flows/models.py:216 msgid "" "Configure how the flow executor should handle an invalid response to a " "challenge. RETRY returns the error message and a similar challenge to the " @@ -355,14 +360,22 @@ msgid "" "RESTART_WITH_CONTEXT restarts the flow while keeping the current context." msgstr "" -#: authentik/flows/models.py:237 +#: authentik/flows/models.py:240 msgid "Flow Stage Binding" msgstr "" -#: authentik/flows/models.py:238 +#: authentik/flows/models.py:241 msgid "Flow Stage Bindings" msgstr "" +#: authentik/flows/models.py:291 +msgid "Flow Token" +msgstr "" + +#: authentik/flows/models.py:292 +msgid "Flow Tokens" +msgstr "" + #: authentik/flows/templates/flows/error.html:12 msgid "Whoops!" msgstr "" @@ -389,33 +402,33 @@ msgstr "" msgid "Invalid kubeconfig" msgstr "" -#: authentik/outposts/models.py:167 +#: authentik/outposts/models.py:165 msgid "Outpost Service-Connection" msgstr "" -#: authentik/outposts/models.py:168 +#: authentik/outposts/models.py:166 msgid "Outpost Service-Connections" msgstr "" -#: authentik/outposts/models.py:204 +#: authentik/outposts/models.py:202 msgid "" "Certificate/Key used for authentication. Can be left empty for no " "authentication." msgstr "" -#: authentik/outposts/models.py:246 +#: authentik/outposts/models.py:244 msgid "Docker Service-Connection" msgstr "" -#: authentik/outposts/models.py:247 +#: authentik/outposts/models.py:245 msgid "Docker Service-Connections" msgstr "" -#: authentik/outposts/models.py:293 +#: authentik/outposts/models.py:291 msgid "Kubernetes Service-Connection" msgstr "" -#: authentik/outposts/models.py:294 +#: authentik/outposts/models.py:292 msgid "Kubernetes Service-Connections" msgstr "" @@ -608,173 +621,173 @@ msgstr "" msgid "RS256 requires a Certificate-Key-Pair to be selected." msgstr "" -#: authentik/providers/oauth2/models.py:35 +#: authentik/providers/oauth2/models.py:34 msgid "Confidential" msgstr "" -#: authentik/providers/oauth2/models.py:36 +#: authentik/providers/oauth2/models.py:35 msgid "Public" msgstr "" -#: authentik/providers/oauth2/models.py:50 +#: authentik/providers/oauth2/models.py:49 msgid "Based on the Hashed User ID" msgstr "" -#: authentik/providers/oauth2/models.py:51 +#: authentik/providers/oauth2/models.py:50 msgid "Based on the username" msgstr "" -#: authentik/providers/oauth2/models.py:54 +#: authentik/providers/oauth2/models.py:53 msgid "Based on the User's Email. This is recommended over the UPN method." msgstr "" -#: authentik/providers/oauth2/models.py:70 +#: authentik/providers/oauth2/models.py:69 msgid "Same identifier is used for all providers" msgstr "" -#: authentik/providers/oauth2/models.py:72 +#: authentik/providers/oauth2/models.py:71 msgid "Each provider has a different issuer, based on the application slug." msgstr "" -#: authentik/providers/oauth2/models.py:79 +#: authentik/providers/oauth2/models.py:78 msgid "code (Authorization Code Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:80 +#: authentik/providers/oauth2/models.py:79 msgid "id_token (Implicit Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:81 +#: authentik/providers/oauth2/models.py:80 msgid "id_token token (Implicit Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:82 +#: authentik/providers/oauth2/models.py:81 msgid "code token (Hybrid Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:83 +#: authentik/providers/oauth2/models.py:82 msgid "code id_token (Hybrid Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:84 +#: authentik/providers/oauth2/models.py:83 msgid "code id_token token (Hybrid Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:90 +#: authentik/providers/oauth2/models.py:89 msgid "HS256 (Symmetric Encryption)" msgstr "" -#: authentik/providers/oauth2/models.py:91 +#: authentik/providers/oauth2/models.py:90 msgid "RS256 (Asymmetric Encryption)" msgstr "" -#: authentik/providers/oauth2/models.py:97 +#: authentik/providers/oauth2/models.py:96 msgid "Scope used by the client" msgstr "" -#: authentik/providers/oauth2/models.py:123 +#: authentik/providers/oauth2/models.py:122 msgid "Scope Mapping" msgstr "" -#: authentik/providers/oauth2/models.py:124 +#: authentik/providers/oauth2/models.py:123 msgid "Scope Mappings" msgstr "" -#: authentik/providers/oauth2/models.py:134 +#: authentik/providers/oauth2/models.py:133 msgid "Client Type" msgstr "" -#: authentik/providers/oauth2/models.py:140 +#: authentik/providers/oauth2/models.py:139 msgid "Client ID" msgstr "" -#: authentik/providers/oauth2/models.py:146 +#: authentik/providers/oauth2/models.py:145 msgid "Client Secret" msgstr "" -#: authentik/providers/oauth2/models.py:153 +#: authentik/providers/oauth2/models.py:152 msgid "JWT Algorithm" msgstr "" -#: authentik/providers/oauth2/models.py:159 +#: authentik/providers/oauth2/models.py:158 msgid "Redirect URIs" msgstr "" -#: authentik/providers/oauth2/models.py:160 +#: authentik/providers/oauth2/models.py:159 msgid "Enter each URI on a new line." msgstr "" -#: authentik/providers/oauth2/models.py:165 +#: authentik/providers/oauth2/models.py:164 msgid "Include claims in id_token" msgstr "" -#: authentik/providers/oauth2/models.py:213 +#: authentik/providers/oauth2/models.py:212 msgid "RSA Key" msgstr "" -#: authentik/providers/oauth2/models.py:217 +#: authentik/providers/oauth2/models.py:216 msgid "" "Key used to sign the tokens. Only required when JWT Algorithm is set to " "RS256." msgstr "" -#: authentik/providers/oauth2/models.py:307 +#: authentik/providers/oauth2/models.py:306 msgid "OAuth2/OpenID Provider" msgstr "" -#: authentik/providers/oauth2/models.py:308 +#: authentik/providers/oauth2/models.py:307 msgid "OAuth2/OpenID Providers" msgstr "" -#: authentik/providers/oauth2/models.py:316 +#: authentik/providers/oauth2/models.py:315 msgid "Scopes" msgstr "" -#: authentik/providers/oauth2/models.py:335 +#: authentik/providers/oauth2/models.py:334 msgid "Code" msgstr "" -#: authentik/providers/oauth2/models.py:336 +#: authentik/providers/oauth2/models.py:335 msgid "Nonce" msgstr "" -#: authentik/providers/oauth2/models.py:337 +#: authentik/providers/oauth2/models.py:336 msgid "Is Authentication?" msgstr "" -#: authentik/providers/oauth2/models.py:338 +#: authentik/providers/oauth2/models.py:337 msgid "Code Challenge" msgstr "" -#: authentik/providers/oauth2/models.py:340 +#: authentik/providers/oauth2/models.py:339 msgid "Code Challenge Method" msgstr "" -#: authentik/providers/oauth2/models.py:354 +#: authentik/providers/oauth2/models.py:353 msgid "Authorization Code" msgstr "" -#: authentik/providers/oauth2/models.py:355 +#: authentik/providers/oauth2/models.py:354 msgid "Authorization Codes" msgstr "" -#: authentik/providers/oauth2/models.py:398 +#: authentik/providers/oauth2/models.py:397 msgid "Access Token" msgstr "" -#: authentik/providers/oauth2/models.py:399 +#: authentik/providers/oauth2/models.py:398 msgid "Refresh Token" msgstr "" -#: authentik/providers/oauth2/models.py:400 +#: authentik/providers/oauth2/models.py:399 msgid "ID Token" msgstr "" -#: authentik/providers/oauth2/models.py:403 +#: authentik/providers/oauth2/models.py:402 msgid "OAuth2 Token" msgstr "" -#: authentik/providers/oauth2/models.py:404 +#: authentik/providers/oauth2/models.py:403 msgid "OAuth2 Tokens" msgstr "" @@ -823,11 +836,11 @@ msgstr "" msgid "Proxy Providers" msgstr "" -#: authentik/providers/saml/api.py:163 +#: authentik/providers/saml/api.py:176 msgid "Invalid XML Syntax" msgstr "" -#: authentik/providers/saml/api.py:173 +#: authentik/providers/saml/api.py:186 #, python-format msgid "Failed to import Metadata: %(message)s" msgstr "" @@ -924,71 +937,77 @@ msgstr "" msgid "Used recovery-link to authenticate." msgstr "" -#: authentik/sources/ldap/models.py:20 +#: authentik/sources/ldap/models.py:33 msgid "Server URI" msgstr "" -#: authentik/sources/ldap/models.py:22 +#: authentik/sources/ldap/models.py:41 +msgid "" +"Optionally verify the LDAP Server's Certificate against the CA Chain in this " +"keypair." +msgstr "" + +#: authentik/sources/ldap/models.py:46 msgid "Bind CN" msgstr "" -#: authentik/sources/ldap/models.py:24 +#: authentik/sources/ldap/models.py:48 msgid "Enable Start TLS" msgstr "" -#: authentik/sources/ldap/models.py:26 +#: authentik/sources/ldap/models.py:50 msgid "Base DN" msgstr "" -#: authentik/sources/ldap/models.py:28 +#: authentik/sources/ldap/models.py:52 msgid "Prepended to Base DN for User-queries." msgstr "" -#: authentik/sources/ldap/models.py:29 +#: authentik/sources/ldap/models.py:53 msgid "Addition User DN" msgstr "" -#: authentik/sources/ldap/models.py:33 +#: authentik/sources/ldap/models.py:57 msgid "Prepended to Base DN for Group-queries." msgstr "" -#: authentik/sources/ldap/models.py:34 +#: authentik/sources/ldap/models.py:58 msgid "Addition Group DN" msgstr "" -#: authentik/sources/ldap/models.py:40 +#: authentik/sources/ldap/models.py:64 msgid "Consider Objects matching this filter to be Users." msgstr "" -#: authentik/sources/ldap/models.py:43 +#: authentik/sources/ldap/models.py:67 msgid "Field which contains members of a group." msgstr "" -#: authentik/sources/ldap/models.py:47 +#: authentik/sources/ldap/models.py:71 msgid "Consider Objects matching this filter to be Groups." msgstr "" -#: authentik/sources/ldap/models.py:50 +#: authentik/sources/ldap/models.py:74 msgid "Field which contains a unique Identifier." msgstr "" -#: authentik/sources/ldap/models.py:57 +#: authentik/sources/ldap/models.py:81 msgid "Property mappings used for group creation/updating." msgstr "" -#: authentik/sources/ldap/models.py:107 +#: authentik/sources/ldap/models.py:146 msgid "LDAP Source" msgstr "" -#: authentik/sources/ldap/models.py:108 +#: authentik/sources/ldap/models.py:147 msgid "LDAP Sources" msgstr "" -#: authentik/sources/ldap/models.py:131 +#: authentik/sources/ldap/models.py:170 msgid "LDAP Property Mapping" msgstr "" -#: authentik/sources/ldap/models.py:132 +#: authentik/sources/ldap/models.py:171 msgid "LDAP Property Mappings" msgstr "" @@ -1029,83 +1048,91 @@ msgstr "" msgid "URL used by authentik to get user information." msgstr "" -#: authentik/sources/oauth/models.py:102 +#: authentik/sources/oauth/models.py:93 msgid "OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:103 +#: authentik/sources/oauth/models.py:94 msgid "OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:112 +#: authentik/sources/oauth/models.py:103 msgid "GitHub OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:113 +#: authentik/sources/oauth/models.py:104 msgid "GitHub OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:122 +#: authentik/sources/oauth/models.py:113 msgid "Twitter OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:123 +#: authentik/sources/oauth/models.py:114 msgid "Twitter OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:132 +#: authentik/sources/oauth/models.py:123 msgid "Facebook OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:133 +#: authentik/sources/oauth/models.py:124 msgid "Facebook OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:142 +#: authentik/sources/oauth/models.py:133 msgid "Discord OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:143 +#: authentik/sources/oauth/models.py:134 msgid "Discord OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:152 +#: authentik/sources/oauth/models.py:143 msgid "Google OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:153 +#: authentik/sources/oauth/models.py:144 msgid "Google OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:162 +#: authentik/sources/oauth/models.py:153 msgid "Azure AD OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:163 +#: authentik/sources/oauth/models.py:154 msgid "Azure AD OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:172 +#: authentik/sources/oauth/models.py:163 msgid "OpenID OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:173 +#: authentik/sources/oauth/models.py:164 msgid "OpenID OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:182 +#: authentik/sources/oauth/models.py:173 msgid "Apple OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:183 +#: authentik/sources/oauth/models.py:174 msgid "Apple OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:198 -msgid "User OAuth Source Connection" +#: authentik/sources/oauth/models.py:183 +msgid "Okta OAuth Source" +msgstr "" + +#: authentik/sources/oauth/models.py:184 +msgid "Okta OAuth Sources" msgstr "" #: authentik/sources/oauth/models.py:199 +msgid "User OAuth Source Connection" +msgstr "" + +#: authentik/sources/oauth/models.py:200 msgid "User OAuth Source Connections" msgstr "" @@ -1113,31 +1140,31 @@ msgstr "" msgid "Authentication Failed." msgstr "" -#: authentik/sources/plex/models.py:36 +#: authentik/sources/plex/models.py:37 msgid "Client identifier used to talk to Plex." msgstr "" -#: authentik/sources/plex/models.py:51 +#: authentik/sources/plex/models.py:52 msgid "Allow friends to authenticate, even if you don't share a server." msgstr "" -#: authentik/sources/plex/models.py:53 +#: authentik/sources/plex/models.py:54 msgid "Plex token used to check friends" msgstr "" -#: authentik/sources/plex/models.py:92 +#: authentik/sources/plex/models.py:91 msgid "Plex Source" msgstr "" -#: authentik/sources/plex/models.py:93 +#: authentik/sources/plex/models.py:92 msgid "Plex Sources" msgstr "" -#: authentik/sources/plex/models.py:104 +#: authentik/sources/plex/models.py:103 msgid "User Plex Source Connection" msgstr "" -#: authentik/sources/plex/models.py:105 +#: authentik/sources/plex/models.py:104 msgid "User Plex Source Connections" msgstr "" @@ -1202,43 +1229,43 @@ msgid "" "signing." msgstr "" -#: authentik/sources/saml/models.py:190 +#: authentik/sources/saml/models.py:189 msgid "SAML Source" msgstr "" -#: authentik/sources/saml/models.py:191 +#: authentik/sources/saml/models.py:190 msgid "SAML Sources" msgstr "" -#: authentik/stages/authenticator_duo/models.py:65 +#: authentik/stages/authenticator_duo/models.py:64 msgid "Duo Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_duo/models.py:66 +#: authentik/stages/authenticator_duo/models.py:65 msgid "Duo Authenticator Setup Stages" msgstr "" -#: authentik/stages/authenticator_duo/models.py:83 +#: authentik/stages/authenticator_duo/models.py:82 msgid "Duo Device" msgstr "" -#: authentik/stages/authenticator_duo/models.py:84 +#: authentik/stages/authenticator_duo/models.py:83 msgid "Duo Devices" msgstr "" -#: authentik/stages/authenticator_sms/models.py:158 +#: authentik/stages/authenticator_sms/models.py:157 msgid "SMS Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_sms/models.py:159 +#: authentik/stages/authenticator_sms/models.py:158 msgid "SMS Authenticator Setup Stages" msgstr "" -#: authentik/stages/authenticator_sms/models.py:176 +#: authentik/stages/authenticator_sms/models.py:175 msgid "SMS Device" msgstr "" -#: authentik/stages/authenticator_sms/models.py:177 +#: authentik/stages/authenticator_sms/models.py:176 msgid "SMS Devices" msgstr "" @@ -1247,11 +1274,11 @@ msgstr "" msgid "Code does not match" msgstr "" -#: authentik/stages/authenticator_static/models.py:48 +#: authentik/stages/authenticator_static/models.py:47 msgid "Static Authenticator Stage" msgstr "" -#: authentik/stages/authenticator_static/models.py:49 +#: authentik/stages/authenticator_static/models.py:48 msgid "Static Authenticator Stages" msgstr "" @@ -1263,11 +1290,11 @@ msgstr "" msgid "8 digits, not compatible with apps like Google Authenticator" msgstr "" -#: authentik/stages/authenticator_totp/models.py:55 +#: authentik/stages/authenticator_totp/models.py:54 msgid "TOTP Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_totp/models.py:56 +#: authentik/stages/authenticator_totp/models.py:55 msgid "TOTP Authenticator Setup Stages" msgstr "" @@ -1303,19 +1330,19 @@ msgstr "" msgid "Authenticator Validation Stages" msgstr "" -#: authentik/stages/authenticator_webauthn/models.py:51 +#: authentik/stages/authenticator_webauthn/models.py:71 msgid "WebAuthn Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_webauthn/models.py:52 +#: authentik/stages/authenticator_webauthn/models.py:72 msgid "WebAuthn Authenticator Setup Stages" msgstr "" -#: authentik/stages/authenticator_webauthn/models.py:85 +#: authentik/stages/authenticator_webauthn/models.py:105 msgid "WebAuthn Device" msgstr "" -#: authentik/stages/authenticator_webauthn/models.py:86 +#: authentik/stages/authenticator_webauthn/models.py:106 msgid "WebAuthn Devices" msgstr "" @@ -1393,19 +1420,15 @@ msgstr "" msgid "Email Stages" msgstr "" -#: authentik/stages/email/stage.py:103 -msgid "Invalid token" -msgstr "" - -#: authentik/stages/email/stage.py:107 +#: authentik/stages/email/stage.py:106 msgid "Successfully verified Email." msgstr "" -#: authentik/stages/email/stage.py:114 authentik/stages/email/stage.py:136 +#: authentik/stages/email/stage.py:113 authentik/stages/email/stage.py:135 msgid "No pending user." msgstr "" -#: authentik/stages/email/stage.py:126 +#: authentik/stages/email/stage.py:125 msgid "Email sent." msgstr "" @@ -1513,7 +1536,7 @@ msgstr "" msgid "Identification Stages" msgstr "" -#: authentik/stages/identification/stage.py:163 +#: authentik/stages/identification/stage.py:174 msgid "Log in" msgstr "" @@ -1557,15 +1580,15 @@ msgstr "" msgid "Selection of backends to test the password against." msgstr "" -#: authentik/stages/password/models.py:79 +#: authentik/stages/password/models.py:78 msgid "Password Stage" msgstr "" -#: authentik/stages/password/models.py:80 +#: authentik/stages/password/models.py:79 msgid "Password Stages" msgstr "" -#: authentik/stages/password/stage.py:141 +#: authentik/stages/password/stage.py:152 msgid "Invalid password" msgstr "" @@ -1597,19 +1620,19 @@ msgstr "" msgid "Name of the form field, also used to store the value" msgstr "" -#: authentik/stages/prompt/models.py:128 +#: authentik/stages/prompt/models.py:131 msgid "Prompt" msgstr "" -#: authentik/stages/prompt/models.py:129 +#: authentik/stages/prompt/models.py:132 msgid "Prompts" msgstr "" -#: authentik/stages/prompt/models.py:157 +#: authentik/stages/prompt/models.py:160 msgid "Prompt Stage" msgstr "" -#: authentik/stages/prompt/models.py:158 +#: authentik/stages/prompt/models.py:161 msgid "Prompt Stages" msgstr "" diff --git a/schema.yml b/schema.yml index 0a6f27ff70..a1748cdf18 100644 --- a/schema.yml +++ b/schema.yml @@ -3909,6 +3909,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /events/events/per_month/: + get: + operationId: events_events_per_month_list + description: Get the count of events per month + parameters: + - in: query + name: action + schema: + type: string + - in: query + name: query + schema: + type: string + tags: + - events + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Coordinate' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /events/events/top_per_user/: get: operationId: events_events_top_per_user_list @@ -3918,56 +3948,10 @@ paths: name: action schema: type: string - - in: query - name: client_ip - schema: - type: string - - in: query - name: context_authorized_app - schema: - type: string - description: Context Authorized application - - in: query - name: context_model_app - schema: - type: string - description: Context Model App - - in: query - name: context_model_name - schema: - type: string - description: Context Model Name - - in: query - name: context_model_pk - schema: - type: string - description: Context Model Primary Key - - name: ordering - required: false - in: query - description: Which field to use when ordering the results. - schema: - type: string - - name: search - required: false - in: query - description: A search term. - schema: - type: string - - in: query - name: tenant_name - schema: - type: string - description: Tenant name - in: query name: top_n schema: type: integer - - in: query - name: username - schema: - type: string - description: Username tags: - events security: @@ -7539,6 +7523,7 @@ paths: - configuration_error - custom_ - email_sent + - flow_execution - impersonation_ended - impersonation_started - invitation_used @@ -15395,6 +15380,14 @@ paths: schema: type: string format: uuid + - in: query + name: user_verification + schema: + type: string + enum: + - discouraged + - preferred + - required tags: - stages security: @@ -19086,6 +19079,46 @@ components: - authentik.managed - authentik.core type: string + AppleChallengeResponseRequest: + type: object + description: Pseudo class for plex response + properties: + component: + type: string + minLength: 1 + default: ak-flow-sources-oauth-apple + AppleLoginChallenge: + type: object + description: Special challenge for apple-native authentication flow, which happens + on the client. + properties: + type: + $ref: '#/components/schemas/ChallengeChoices' + flow_info: + $ref: '#/components/schemas/ContextualFlowInfo' + component: + type: string + default: ak-flow-sources-oauth-apple + response_errors: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/ErrorDetail' + client_id: + type: string + scope: + type: string + redirect_uri: + type: string + state: + type: string + required: + - client_id + - redirect_uri + - scope + - state + - type Application: type: object description: Application Serializer @@ -19200,6 +19233,8 @@ components: nullable: true description: Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage. + user_verification: + $ref: '#/components/schemas/UserVerificationEnum' required: - component - meta_model_name @@ -19224,6 +19259,8 @@ components: nullable: true description: Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage. + user_verification: + $ref: '#/components/schemas/UserVerificationEnum' required: - name AuthenticatedSession: @@ -20225,6 +20262,7 @@ components: ChallengeTypes: oneOf: - $ref: '#/components/schemas/AccessDeniedChallenge' + - $ref: '#/components/schemas/AppleLoginChallenge' - $ref: '#/components/schemas/AuthenticatorDuoChallenge' - $ref: '#/components/schemas/AuthenticatorSMSChallenge' - $ref: '#/components/schemas/AuthenticatorStaticChallenge' @@ -20246,6 +20284,7 @@ components: propertyName: component mapping: ak-stage-access-denied: '#/components/schemas/AccessDeniedChallenge' + ak-flow-sources-oauth-apple: '#/components/schemas/AppleLoginChallenge' ak-stage-authenticator-duo: '#/components/schemas/AuthenticatorDuoChallenge' ak-stage-authenticator-sms: '#/components/schemas/AuthenticatorSMSChallenge' ak-stage-authenticator-static: '#/components/schemas/AuthenticatorStaticChallenge' @@ -21080,6 +21119,7 @@ components: - source_linked - impersonation_started - impersonation_ended + - flow_execution - policy_execution - policy_exception - property_mapping_exception @@ -21387,6 +21427,7 @@ components: - title FlowChallengeResponseRequest: oneOf: + - $ref: '#/components/schemas/AppleChallengeResponseRequest' - $ref: '#/components/schemas/AuthenticatorDuoChallengeResponseRequest' - $ref: '#/components/schemas/AuthenticatorSMSChallengeResponseRequest' - $ref: '#/components/schemas/AuthenticatorStaticChallengeResponseRequest' @@ -21405,6 +21446,7 @@ components: discriminator: propertyName: component mapping: + ak-flow-sources-oauth-apple: '#/components/schemas/AppleChallengeResponseRequest' ak-stage-authenticator-duo: '#/components/schemas/AuthenticatorDuoChallengeResponseRequest' ak-stage-authenticator-sms: '#/components/schemas/AuthenticatorSMSChallengeResponseRequest' ak-stage-authenticator-static: '#/components/schemas/AuthenticatorStaticChallengeResponseRequest' @@ -22071,7 +22113,7 @@ components: additionalProperties: {} created_by: allOf: - - $ref: '#/components/schemas/User' + - $ref: '#/components/schemas/GroupMember' readOnly: true single_use: type: boolean @@ -22711,11 +22753,13 @@ components: oneOf: - $ref: '#/components/schemas/RedirectChallenge' - $ref: '#/components/schemas/PlexAuthenticationChallenge' + - $ref: '#/components/schemas/AppleLoginChallenge' discriminator: propertyName: component mapping: xak-flow-redirect: '#/components/schemas/RedirectChallenge' ak-flow-sources-plex: '#/components/schemas/PlexAuthenticationChallenge' + ak-flow-sources-oauth-apple: '#/components/schemas/AppleLoginChallenge' LoginMetrics: type: object description: Login Metrics per 1h @@ -26565,6 +26609,8 @@ components: nullable: true description: Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage. + user_verification: + $ref: '#/components/schemas/UserVerificationEnum' PatchedAuthenticatorDuoStageRequest: type: object description: AuthenticatorDuoStage Serializer @@ -28992,6 +29038,7 @@ components: - github - google - openidconnect + - okta - reddit - twitter type: string @@ -31188,6 +31235,12 @@ components: - pk - source - user + UserVerificationEnum: + enum: + - required + - preferred + - discouraged + type: string UserWriteStage: type: object description: UserWriteStage Serializer diff --git a/tests/e2e/test_provider_oauth2_oidc.py b/tests/e2e/test_provider_oauth2_oidc.py index 3d7553e847..fa0ca30ee1 100644 --- a/tests/e2e/test_provider_oauth2_oidc.py +++ b/tests/e2e/test_provider_oauth2_oidc.py @@ -40,7 +40,7 @@ class TestProviderOAuth2OIDC(SeleniumTestCase): sleep(1) client: DockerClient = from_env() container = client.containers.run( - image="beryju.org/oidc-test-client:latest", + image="ghcr.io/beryju/oidc-test-client:latest", detach=True, network_mode="host", auto_remove=True, diff --git a/tests/e2e/test_provider_oauth2_oidc_implicit.py b/tests/e2e/test_provider_oauth2_oidc_implicit.py index 6915595506..a9c47f1085 100644 --- a/tests/e2e/test_provider_oauth2_oidc_implicit.py +++ b/tests/e2e/test_provider_oauth2_oidc_implicit.py @@ -40,7 +40,7 @@ class TestProviderOAuth2OIDCImplicit(SeleniumTestCase): sleep(1) client: DockerClient = from_env() container = client.containers.run( - image="beryju.org/oidc-test-client:latest", + image="ghcr.io/beryju/oidc-test-client:latest", detach=True, network_mode="host", auto_remove=True, @@ -145,7 +145,6 @@ class TestProviderOAuth2OIDCImplicit(SeleniumTestCase): self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "pre"))) sleep(1) body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text) - print(body) self.assertEqual(body["profile"]["nickname"], self.user.username) self.assertEqual(body["profile"]["name"], self.user.name) self.assertEqual(body["profile"]["email"], self.user.email) diff --git a/tests/e2e/test_provider_saml.py b/tests/e2e/test_provider_saml.py index 147e742d09..3beef30626 100644 --- a/tests/e2e/test_provider_saml.py +++ b/tests/e2e/test_provider_saml.py @@ -39,7 +39,7 @@ class TestProviderSAML(SeleniumTestCase): if force_post: metadata_url += f"&force_binding={SAML_BINDING_POST}" container = client.containers.run( - image="beryju.org/saml-test-sp:latest", + image="ghcr.io/beryju/saml-test-sp:latest", detach=True, network_mode="host", auto_remove=True, diff --git a/tests/e2e/test_source_oauth.py b/tests/e2e/test_source_oauth.py index d7c5deb987..6288d3d2e3 100644 --- a/tests/e2e/test_source_oauth.py +++ b/tests/e2e/test_source_oauth.py @@ -229,7 +229,7 @@ class TestSourceOAuth1(SeleniumTestCase): def get_container_specs(self) -> Optional[dict[str, Any]]: return { - "image": "beryju.org/oauth1-test-server:latest", + "image": "ghcr.io/beryju/oauth1-test-server:latest", "detach": True, "network_mode": "host", "auto_remove": True, diff --git a/web/authentik/sources/okta.svg b/web/authentik/sources/okta.svg new file mode 100644 index 0000000000..5595186b2a --- /dev/null +++ b/web/authentik/sources/okta.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + diff --git a/web/package-lock.json b/web/package-lock.json index ba888b0afb..6f0b0c3089 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -9,24 +9,24 @@ "version": "0.0.0", "license": "GNU GPLv3", "dependencies": { - "@babel/core": "^7.16.0", - "@babel/plugin-proposal-decorators": "^7.16.4", - "@babel/plugin-transform-runtime": "^7.16.4", - "@babel/preset-env": "^7.16.4", - "@babel/preset-typescript": "^7.16.0", + "@babel/core": "^7.16.5", + "@babel/plugin-proposal-decorators": "^7.16.5", + "@babel/plugin-transform-runtime": "^7.16.5", + "@babel/preset-env": "^7.16.5", + "@babel/preset-typescript": "^7.16.5", "@fortawesome/fontawesome-free": "^5.15.4", - "@goauthentik/api": "^2021.10.4-1639076050", + "@goauthentik/api": "^2021.10.4-1639516687", "@jackfranklin/rollup-plugin-markdown": "^0.3.0", "@lingui/cli": "^3.13.0", "@lingui/core": "^3.13.0", "@lingui/detect-locale": "^3.13.0", "@lingui/macro": "^3.13.0", - "@patternfly/patternfly": "^4.159.1", + "@patternfly/patternfly": "^4.164.2", "@polymer/iron-form": "^3.0.1", "@polymer/paper-input": "^3.2.1", "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-commonjs": "^21.0.1", - "@rollup/plugin-node-resolve": "^13.0.6", + "@rollup/plugin-node-resolve": "^13.1.1", "@rollup/plugin-replace": "^3.0.0", "@rollup/plugin-typescript": "^8.3.0", "@sentry/browser": "^6.16.1", @@ -36,8 +36,8 @@ "@types/chart.js": "^2.9.34", "@types/codemirror": "5.60.5", "@types/grecaptcha": "^3.0.3", - "@typescript-eslint/eslint-plugin": "^5.6.0", - "@typescript-eslint/parser": "^5.6.0", + "@typescript-eslint/eslint-plugin": "^5.7.0", + "@typescript-eslint/parser": "^5.7.0", "@webcomponents/webcomponentsjs": "^2.6.0", "babel-plugin-macros": "^3.1.0", "base64-js": "^1.5.1", @@ -63,7 +63,7 @@ "rollup-plugin-terser": "^7.0.2", "ts-lit-plugin": "^1.2.1", "tslib": "^2.3.1", - "typescript": "^4.5.3", + "typescript": "^4.5.4", "webcomponent-qr-code": "^1.0.5", "yaml": "^1.10.2" } @@ -96,18 +96,18 @@ } }, "node_modules/@babel/core": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.0.tgz", - "integrity": "sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.5.tgz", + "integrity": "sha512-wUcenlLzuWMZ9Zt8S0KmFwGlH6QKRh3vsm/dhDA3CHkiTA45YuG1XkHRcNRl73EFPXDp/d5kVOU0/y7x2w6OaQ==", "dependencies": { "@babel/code-frame": "^7.16.0", - "@babel/generator": "^7.16.0", - "@babel/helper-compilation-targets": "^7.16.0", - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helpers": "^7.16.0", - "@babel/parser": "^7.16.0", + "@babel/generator": "^7.16.5", + "@babel/helper-compilation-targets": "^7.16.3", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helpers": "^7.16.5", + "@babel/parser": "^7.16.5", "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", @@ -125,9 +125,9 @@ } }, "node_modules/@babel/generator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz", - "integrity": "sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.5.tgz", + "integrity": "sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA==", "dependencies": { "@babel/types": "^7.16.0", "jsesc": "^2.5.1", @@ -149,9 +149,9 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.0.tgz", - "integrity": "sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.5.tgz", + "integrity": "sha512-3JEA9G5dmmnIWdzaT9d0NmFRgYnWUThLsDaL7982H0XqqWr56lRrsmwheXFMjR+TMl7QMBb6mzy9kvgr1lRLUA==", "dependencies": { "@babel/helper-explode-assignable-expression": "^7.16.0", "@babel/types": "^7.16.0" @@ -178,15 +178,16 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz", - "integrity": "sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.5.tgz", + "integrity": "sha512-NEohnYA7mkB8L5JhU7BLwcBdU3j83IziR9aseMueWGeAjblbul3zzb8UvJ3a1zuBiqCMObzCJHFqKIQE6hTVmg==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-environment-visitor": "^7.16.5", "@babel/helper-function-name": "^7.16.0", - "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-member-expression-to-functions": "^7.16.5", "@babel/helper-optimise-call-expression": "^7.16.0", - "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-replace-supers": "^7.16.5", "@babel/helper-split-export-declaration": "^7.16.0" }, "engines": { @@ -229,6 +230,17 @@ "@babel/core": "^7.4.0-0" } }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.5.tgz", + "integrity": "sha512-ODQyc5AnxmZWm/R2W7fzhamOk1ey8gSguo5SGvF0zcB3uUzRpTRmM/jmLSm9bDMyPlvbyJ+PwPEK0BWIoZ9wjg==", + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-explode-assignable-expression": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz", @@ -276,9 +288,9 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz", - "integrity": "sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.5.tgz", + "integrity": "sha512-7fecSXq7ZrLE+TWshbGT+HyCLkxloWNhTbU2QM1NTI/tDqyf0oZiMcEfYtDuUDCo528EOlt39G1rftea4bRZIw==", "dependencies": { "@babel/types": "^7.16.0" }, @@ -298,17 +310,17 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz", - "integrity": "sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.5.tgz", + "integrity": "sha512-CkvMxgV4ZyyioElFwcuWnDCcNIeyqTkCm9BxXZi73RR1ozqlpboqsbGUNvRTflgZtFbbJ1v5Emvm+lkjMYY/LQ==", "dependencies": { + "@babel/helper-environment-visitor": "^7.16.5", "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-replace-supers": "^7.16.0", "@babel/helper-simple-access": "^7.16.0", "@babel/helper-split-export-declaration": "^7.16.0", "@babel/helper-validator-identifier": "^7.15.7", "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0" }, "engines": { @@ -327,20 +339,20 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.5.tgz", + "integrity": "sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.4.tgz", - "integrity": "sha512-vGERmmhR+s7eH5Y/cp8PCVzj4XEjerq8jooMfxFdA5xVtAk9Sh4AQsrWgiErUEBjtGrBtOFKDUcWQFW4/dFwMA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.5.tgz", + "integrity": "sha512-X+aAJldyxrOmN9v3FKp+Hu1NO69VWgYgDGq6YDykwRPzxs5f2N+X988CBXS7EQahDU+Vpet5QYMqLk+nsp+Qxw==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.0", - "@babel/helper-wrap-function": "^7.16.0", + "@babel/helper-wrap-function": "^7.16.5", "@babel/types": "^7.16.0" }, "engines": { @@ -348,13 +360,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz", - "integrity": "sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.5.tgz", + "integrity": "sha512-ao3seGVa/FZCMCCNDuBcqnBFSbdr8N2EW35mzojx3TwfIbdPmNK+JV6+2d5bR0Z71W5ocLnQp9en/cTF7pBJiQ==", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-environment-visitor": "^7.16.5", + "@babel/helper-member-expression-to-functions": "^7.16.5", "@babel/helper-optimise-call-expression": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0" }, "engines": { @@ -411,13 +424,13 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.0.tgz", - "integrity": "sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.5.tgz", + "integrity": "sha512-2J2pmLBqUqVdJw78U0KPNdeE2qeuIyKoG4mKV7wAq3mc4jJG282UgjZw4ZYDnqiWQuS3Y3IYdF/AQ6CpyBV3VA==", "dependencies": { "@babel/helper-function-name": "^7.16.0", "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0" }, "engines": { @@ -425,12 +438,12 @@ } }, "node_modules/@babel/helpers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.0.tgz", - "integrity": "sha512-dVRM0StFMdKlkt7cVcGgwD8UMaBfWJHl3A83Yfs8GQ3MO0LHIIIMvK7Fa0RGOGUQ10qikLaX6D7o5htcQWgTMQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.5.tgz", + "integrity": "sha512-TLgi6Lh71vvMZGEkFuIxzaPsyeYCHQ5jJOOX1f0xXn0uciFuE8cEk0wyBquMcCxBXZ5BJhE2aUB7pnWTD150Tw==", "dependencies": { "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0" }, "engines": { @@ -451,9 +464,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-TEHWXf0xxpi9wKVyBCmRcSSDjbJ/cl6LUdlbYUHEaNQUJGhreJbZrXT6sR4+fZLxVUJqNRB4KyOvjuy/D9009A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.5.tgz", + "integrity": "sha512-+Ce7T5iPNWzfu9C1aB5tN3Lyafs5xb3Ic7vBWyZL2KXT3QSdD1dD3CvgOzPmQKoNNRt6uauc0XwNJTQtXC2/Mw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -492,12 +505,12 @@ } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.4.tgz", - "integrity": "sha512-/CUekqaAaZCQHleSK/9HajvcD/zdnJiKRiuUFq8ITE+0HsPzquf53cpFiqAwl/UfmJbR6n5uGPQSPdrmKOvHHg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.5.tgz", + "integrity": "sha512-C/FX+3HNLV6sz7AqbTQqEo1L9/kfrKjxcVtgyBCmvIgOjvuBVUWooDoi7trsLxOzCEo5FccjRvKHkfDsJFZlfA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.16.4", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-remap-async-to-generator": "^7.16.5", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -508,12 +521,12 @@ } }, "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz", - "integrity": "sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.5.tgz", + "integrity": "sha512-pJD3HjgRv83s5dv1sTnDbZOaTjghKEz8KUn1Kbh2eAIRhGuyQ1XSeI4xVXU3UlIEVA3DAyIdxqT1eRn7Wcn55A==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -523,12 +536,12 @@ } }, "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.0.tgz", - "integrity": "sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.5.tgz", + "integrity": "sha512-EEFzuLZcm/rNJ8Q5krK+FRKdVkd6FjfzT9tuSZql9sQn64K0hHA2KLJ0DqVot9/iV6+SsuadC5yI39zWnm+nmQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -539,13 +552,13 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.16.4.tgz", - "integrity": "sha512-RESBNX16eNqnBeEVR5sCJpnW0mHiNLNNvGA8PrRuK/4ZJ4TO+6bHleRUuGQYDERVySOKtOhSya/C4MIhwAMAgg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.16.5.tgz", + "integrity": "sha512-XAiZll5oCdp2Dd2RbXA3LVPlFyIRhhcQy+G34p9ePpl6mjFkbqHAYHovyw2j5mqUrlBf0/+MtOIJ3JGYtz8qaw==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-decorators": "^7.16.0" + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-decorators": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -555,11 +568,11 @@ } }, "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz", - "integrity": "sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.5.tgz", + "integrity": "sha512-P05/SJZTTvHz79LNYTF8ff5xXge0kk5sIIWAypcWgX4BTRUgyHc8wRxJ/Hk+mU0KXldgOOslKaeqnhthcDJCJQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -570,11 +583,11 @@ } }, "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.0.tgz", - "integrity": "sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.5.tgz", + "integrity": "sha512-i+sltzEShH1vsVydvNaTRsgvq2vZsfyrd7K7vPLUU/KgS0D5yZMe6uipM0+izminnkKrEfdUnz7CxMRb6oHZWw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -585,11 +598,11 @@ } }, "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.0.tgz", - "integrity": "sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.5.tgz", + "integrity": "sha512-QQJueTFa0y9E4qHANqIvMsuxM/qcLQmKttBACtPCQzGUEizsXDACGonlPiSwynHfOa3vNw0FPMVvQzbuXwh4SQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -600,11 +613,11 @@ } }, "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz", - "integrity": "sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.5.tgz", + "integrity": "sha512-xqibl7ISO2vjuQM+MzR3rkd0zfNWltk7n9QhaD8ghMmMceVguYrNDt7MikRyj4J4v3QehpnrU8RYLnC7z/gZLA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -615,11 +628,11 @@ } }, "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz", - "integrity": "sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.5.tgz", + "integrity": "sha512-YwMsTp/oOviSBhrjwi0vzCUycseCYwoXnLiXIL3YNjHSMBHicGTz7GjVU/IGgz4DtOEXBdCNG72pvCX22ehfqg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -630,11 +643,11 @@ } }, "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz", - "integrity": "sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.5.tgz", + "integrity": "sha512-DvB9l/TcsCRvsIV9v4jxR/jVP45cslTVC0PMVHvaJhhNuhn2Y1SOhCSFlPK777qLB5wb8rVDaNoqMTyOqtY5Iw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -645,15 +658,15 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.0.tgz", - "integrity": "sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.5.tgz", + "integrity": "sha512-UEd6KpChoyPhCoE840KRHOlGhEZFutdPDMGj+0I56yuTTOaT51GzmnEl/0uT41fB/vD2nT+Pci2KjezyE3HmUw==", "dependencies": { - "@babel/compat-data": "^7.16.0", - "@babel/helper-compilation-targets": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/compat-data": "^7.16.4", + "@babel/helper-compilation-targets": "^7.16.3", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.16.0" + "@babel/plugin-transform-parameters": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -663,11 +676,11 @@ } }, "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.0.tgz", - "integrity": "sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.5.tgz", + "integrity": "sha512-ihCMxY1Iljmx4bWy/PIMJGXN4NS4oUj1MKynwO07kiKms23pNvIn1DMB92DNB2R0EA882sw0VXIelYGdtF7xEQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -678,11 +691,11 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz", - "integrity": "sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.5.tgz", + "integrity": "sha512-kzdHgnaXRonttiTfKYnSVafbWngPPr2qKw9BWYBESl91W54e+9R5pP70LtWxV56g0f05f/SQrwHYkfvbwcdQ/A==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, @@ -694,12 +707,12 @@ } }, "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz", - "integrity": "sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.5.tgz", + "integrity": "sha512-+yFMO4BGT3sgzXo+lrq7orX5mAZt57DwUK6seqII6AcJnJOIhBJ8pzKH47/ql/d426uQ7YhN8DpUFirQzqYSUA==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -709,13 +722,13 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz", - "integrity": "sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.5.tgz", + "integrity": "sha512-+YGh5Wbw0NH3y/E5YMu6ci5qTDmAEVNoZ3I54aB6nVEOZ5BQ7QJlwKq5pYVucQilMByGn/bvX0af+uNaPRCabA==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.0", - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -726,12 +739,12 @@ } }, "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.0.tgz", - "integrity": "sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.5.tgz", + "integrity": "sha512-s5sKtlKQyFSatt781HQwv1hoM5BQ9qRH30r+dK56OLDsHmV74mzwJNX7R1yMuE7VZKG5O6q/gmOGSAO6ikTudg==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=4" @@ -777,11 +790,11 @@ } }, "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.16.0.tgz", - "integrity": "sha512-nxnnngZClvlY13nHJAIDow0S7Qzhq64fQ/NlqS+VER3kjW/4F0jLhXjeL8jcwSwz6Ca3rotT5NJD2T9I7lcv7g==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.16.5.tgz", + "integrity": "sha512-3CbYTXfflvyy8O819uhZcZSMedZG4J8yS/NLTc/8T24M9ke1GssTGvg8VZu3Yn2LU5IyQSv1CmPq0a9JWHXJwg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -946,11 +959,11 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.0.tgz", - "integrity": "sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.5.tgz", + "integrity": "sha512-8bTHiiZyMOyfZFULjsCnYOWG059FVMes0iljEHSfARhNgFfpsqE92OrCffv3veSw9rwMkYcFe9bj0ZoXU2IGtQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -960,13 +973,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.0.tgz", - "integrity": "sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.5.tgz", + "integrity": "sha512-TMXgfioJnkXU+XRoj7P2ED7rUm5jbnDWwlCuFVTpQboMfbSya5WrmubNBAMlk7KXvywpo8rd8WuYZkis1o2H8w==", "dependencies": { "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.16.0" + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-remap-async-to-generator": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -976,11 +989,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.0.tgz", - "integrity": "sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.5.tgz", + "integrity": "sha512-BxmIyKLjUGksJ99+hJyL/HIxLIGnLKtw772zYDER7UuycDZ+Xvzs98ZQw6NGgM2ss4/hlFAaGiZmMNKvValEjw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -990,11 +1003,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.0.tgz", - "integrity": "sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.5.tgz", + "integrity": "sha512-JxjSPNZSiOtmxjX7PBRBeRJTUKTyJ607YUYeT0QJCNdsedOe+/rXITjP08eG8xUpsLfPirgzdCFN+h0w6RI+pQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1004,15 +1017,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.0.tgz", - "integrity": "sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.5.tgz", + "integrity": "sha512-DzJ1vYf/7TaCYy57J3SJ9rV+JEuvmlnvvyvYKFbk5u46oQbBvuB9/0w+YsVsxkOv8zVWKpDmUoj4T5ILHoXevA==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-environment-visitor": "^7.16.5", "@babel/helper-function-name": "^7.16.0", "@babel/helper-optimise-call-expression": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-replace-supers": "^7.16.5", "@babel/helper-split-export-declaration": "^7.16.0", "globals": "^11.1.0" }, @@ -1024,11 +1038,11 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.0.tgz", - "integrity": "sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.5.tgz", + "integrity": "sha512-n1+O7xtU5lSLraRzX88CNcpl7vtGdPakKzww74bVwpAIRgz9JVLJJpOLb0uYqcOaXVM0TL6X0RVeIJGD2CnCkg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1038,11 +1052,11 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.0.tgz", - "integrity": "sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.5.tgz", + "integrity": "sha512-GuRVAsjq+c9YPK6NeTkRLWyQskDC099XkBSVO+6QzbnOnH2d/4mBVXYStaPrZD3dFRfg00I6BFJ9Atsjfs8mlg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1052,12 +1066,12 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.0.tgz", - "integrity": "sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.5.tgz", + "integrity": "sha512-iQiEMt8Q4/5aRGHpGVK2Zc7a6mx7qEAO7qehgSug3SDImnuMzgmm/wtJALXaz25zUj1PmnNHtShjFgk4PDx4nw==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1067,11 +1081,11 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.0.tgz", - "integrity": "sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.5.tgz", + "integrity": "sha512-81tijpDg2a6I1Yhj4aWY1l3O1J4Cg/Pd7LfvuaH2VVInAkXtzibz9+zSPdUM1WvuUi128ksstAP0hM5w48vQgg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1081,12 +1095,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.0.tgz", - "integrity": "sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.5.tgz", + "integrity": "sha512-12rba2HwemQPa7BLIKCzm1pT2/RuQHtSFHdNl41cFiC6oi4tcrp7gjB07pxQvFpcADojQywSjblQth6gJyE6CA==", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1096,11 +1110,11 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.0.tgz", - "integrity": "sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.5.tgz", + "integrity": "sha512-+DpCAJFPAvViR17PIMi9x2AE34dll5wNlXO43wagAX2YcRGgEVHCNFC4azG85b4YyyFarvkc/iD5NPrz4Oneqw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1110,12 +1124,12 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.0.tgz", - "integrity": "sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.5.tgz", + "integrity": "sha512-Fuec/KPSpVLbGo6z1RPw4EE1X+z9gZk1uQmnYy7v4xr4TO9p41v1AoUuXEtyqAI7H+xNJYSICzRqZBhDEkd3kQ==", "dependencies": { "@babel/helper-function-name": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1125,11 +1139,11 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.0.tgz", - "integrity": "sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.5.tgz", + "integrity": "sha512-B1j9C/IfvshnPcklsc93AVLTrNVa69iSqztylZH6qnmiAsDDOmmjEYqOm3Ts2lGSgTSywnBNiqC949VdD0/gfw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1139,11 +1153,11 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.0.tgz", - "integrity": "sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.5.tgz", + "integrity": "sha512-d57i3vPHWgIde/9Y8W/xSFUndhvhZN5Wu2TjRrN1MVz5KzdUihKnfDVlfP1U7mS5DNj/WHHhaE4/tTi4hIyHwQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1153,12 +1167,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.0.tgz", - "integrity": "sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.5.tgz", + "integrity": "sha512-oHI15S/hdJuSCfnwIz+4lm6wu/wBn7oJ8+QrkzPPwSFGXk8kgdI/AIKcbR/XnD1nQVMg/i6eNaXpszbGuwYDRQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { @@ -1169,12 +1183,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz", - "integrity": "sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.5.tgz", + "integrity": "sha512-ABhUkxvoQyqhCWyb8xXtfwqNMJD7tx+irIRnUh6lmyFud7Jln1WzONXKlax1fg/ey178EXbs4bSGNd6PngO+SQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-simple-access": "^7.16.0", "babel-plugin-dynamic-import-node": "^2.3.3" }, @@ -1186,13 +1200,13 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.0.tgz", - "integrity": "sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.5.tgz", + "integrity": "sha512-53gmLdScNN28XpjEVIm7LbWnD/b/TpbwKbLk6KV4KqC9WyU6rq1jnNmVG6UgAdQZVVGZVoik3DqHNxk4/EvrjA==", "dependencies": { "@babel/helper-hoist-variables": "^7.16.0", - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-validator-identifier": "^7.15.7", "babel-plugin-dynamic-import-node": "^2.3.3" }, @@ -1204,12 +1218,12 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.0.tgz", - "integrity": "sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.5.tgz", + "integrity": "sha512-qTFnpxHMoenNHkS3VoWRdwrcJ3FhX567GvDA3hRZKF0Dj8Fmg0UzySZp3AP2mShl/bzcywb/UWAMQIjA1bhXvw==", "dependencies": { - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1219,9 +1233,9 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.0.tgz", - "integrity": "sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.5.tgz", + "integrity": "sha512-/wqGDgvFUeKELW6ex6QB7dLVRkd5ehjw34tpXu1nhKC0sFfmaLabIswnpf8JgDyV2NeDmZiwoOb0rAmxciNfjA==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.0" }, @@ -1233,11 +1247,11 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.0.tgz", - "integrity": "sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.5.tgz", + "integrity": "sha512-ZaIrnXF08ZC8jnKR4/5g7YakGVL6go6V9ql6Jl3ecO8PQaQqFE74CuM384kezju7Z9nGCCA20BqZaR1tJ/WvHg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1247,12 +1261,12 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.0.tgz", - "integrity": "sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.5.tgz", + "integrity": "sha512-tded+yZEXuxt9Jdtkc1RraW1zMF/GalVxaVVxh41IYwirdRgyAxxxCKZ9XB7LxZqmsjfjALxupNE1MIz9KH+Zg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.16.0" + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-replace-supers": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1262,11 +1276,11 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.16.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.3.tgz", - "integrity": "sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.5.tgz", + "integrity": "sha512-B3O6AL5oPop1jAVg8CV+haeUte9oFuY85zu0jwnRNZZi3tVAbJriu5tag/oaO2kGaQM/7q7aGPBlTI5/sr9enA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1276,11 +1290,11 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.0.tgz", - "integrity": "sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.5.tgz", + "integrity": "sha512-+IRcVW71VdF9pEH/2R/Apab4a19LVvdVsr/gEeotH00vSDVlKD+XgfSIw+cgGWsjDB/ziqGv/pGoQZBIiQVXHg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1290,9 +1304,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.0.tgz", - "integrity": "sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.5.tgz", + "integrity": "sha512-2z+it2eVWU8TtQQRauvGUqZwLy4+7rTfo6wO4npr+fvvN1SW30ZF3O/ZRCNmTuu4F5MIP8OJhXAhRV5QMJOuYg==", "dependencies": { "regenerator-transform": "^0.14.2" }, @@ -1304,11 +1318,11 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.0.tgz", - "integrity": "sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.5.tgz", + "integrity": "sha512-aIB16u8lNcf7drkhXJRoggOxSTUAuihTSTfAcpynowGJOZiGf+Yvi7RuTwFzVYSYPmWyARsPqUGoZWWWxLiknw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1318,12 +1332,12 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.4.tgz", - "integrity": "sha512-pru6+yHANMTukMtEZGC4fs7XPwg35v8sj5CIEmE+gEkFljFiVJxEWxx/7ZDkTK+iZRYo1bFXBtfIN95+K3cJ5A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.5.tgz", + "integrity": "sha512-gxpfS8XQWDbQ8oP5NcmpXxtEgCJkbO+W9VhZlOhr0xPyVaRjAQPOv7ZDj9fg0d5s9+NiVvMCE6gbkEkcsxwGRw==", "dependencies": { "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "babel-plugin-polyfill-corejs2": "^0.3.0", "babel-plugin-polyfill-corejs3": "^0.4.0", "babel-plugin-polyfill-regenerator": "^0.3.0", @@ -1337,11 +1351,11 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.0.tgz", - "integrity": "sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.5.tgz", + "integrity": "sha512-ZbuWVcY+MAXJuuW7qDoCwoxDUNClfZxoo7/4swVbOW1s/qYLOMHlm9YRWMsxMFuLs44eXsv4op1vAaBaBaDMVg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1351,11 +1365,11 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.0.tgz", - "integrity": "sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.5.tgz", + "integrity": "sha512-5d6l/cnG7Lw4tGHEoga4xSkYp1euP7LAtrah1h1PgJ3JY7yNsjybsxQAnVK4JbtReZ/8z6ASVmd3QhYYKLaKZw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" }, "engines": { @@ -1366,11 +1380,11 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.0.tgz", - "integrity": "sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.5.tgz", + "integrity": "sha512-usYsuO1ID2LXxzuUxifgWtJemP7wL2uZtyrTVM4PKqsmJycdS4U4mGovL5xXkfUheds10Dd2PjoQLXw6zCsCbg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1380,11 +1394,11 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.0.tgz", - "integrity": "sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.5.tgz", + "integrity": "sha512-gnyKy9RyFhkovex4BjKWL3BVYzUDG6zC0gba7VMLbQoDuqMfJ1SDXs8k/XK41Mmt1Hyp4qNAvGFb9hKzdCqBRQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1394,11 +1408,11 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.0.tgz", - "integrity": "sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.5.tgz", + "integrity": "sha512-ldxCkW180qbrvyCVDzAUZqB0TAeF8W/vGJoRcaf75awm6By+PxfJKvuqVAnq8N9wz5Xa6mSpM19OfVKKVmGHSQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1424,11 +1438,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.0.tgz", - "integrity": "sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.5.tgz", + "integrity": "sha512-shiCBHTIIChGLdyojsKQjoAyB8MBwat25lKM7MJjbe1hE0bgIppD+LX9afr41lLHOhqceqeWl4FkLp+Bgn9o1Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1438,12 +1452,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.0.tgz", - "integrity": "sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.5.tgz", + "integrity": "sha512-GTJ4IW012tiPEMMubd7sD07iU9O/LOo8Q/oU4xNhcaq0Xn8+6TcUQaHtC8YxySo1T+ErQ8RaWogIEeFhKGNPzw==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" }, "engines": { "node": ">=6.9.0" @@ -1453,31 +1467,31 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.4.tgz", - "integrity": "sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.5.tgz", + "integrity": "sha512-MiJJW5pwsktG61NDxpZ4oJ1CKxM1ncam9bzRtx9g40/WkLRkxFP6mhpkYV0/DxcciqoiHicx291+eUQrXb/SfQ==", "dependencies": { "@babel/compat-data": "^7.16.4", "@babel/helper-compilation-targets": "^7.16.3", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-validator-option": "^7.14.5", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.2", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.0", - "@babel/plugin-proposal-async-generator-functions": "^7.16.4", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/plugin-proposal-class-static-block": "^7.16.0", - "@babel/plugin-proposal-dynamic-import": "^7.16.0", - "@babel/plugin-proposal-export-namespace-from": "^7.16.0", - "@babel/plugin-proposal-json-strings": "^7.16.0", - "@babel/plugin-proposal-logical-assignment-operators": "^7.16.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", - "@babel/plugin-proposal-numeric-separator": "^7.16.0", - "@babel/plugin-proposal-object-rest-spread": "^7.16.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.0", - "@babel/plugin-proposal-private-methods": "^7.16.0", - "@babel/plugin-proposal-private-property-in-object": "^7.16.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.16.0", + "@babel/plugin-proposal-async-generator-functions": "^7.16.5", + "@babel/plugin-proposal-class-properties": "^7.16.5", + "@babel/plugin-proposal-class-static-block": "^7.16.5", + "@babel/plugin-proposal-dynamic-import": "^7.16.5", + "@babel/plugin-proposal-export-namespace-from": "^7.16.5", + "@babel/plugin-proposal-json-strings": "^7.16.5", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.5", + "@babel/plugin-proposal-numeric-separator": "^7.16.5", + "@babel/plugin-proposal-object-rest-spread": "^7.16.5", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.5", + "@babel/plugin-proposal-optional-chaining": "^7.16.5", + "@babel/plugin-proposal-private-methods": "^7.16.5", + "@babel/plugin-proposal-private-property-in-object": "^7.16.5", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.5", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", @@ -1492,38 +1506,38 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.16.0", - "@babel/plugin-transform-async-to-generator": "^7.16.0", - "@babel/plugin-transform-block-scoped-functions": "^7.16.0", - "@babel/plugin-transform-block-scoping": "^7.16.0", - "@babel/plugin-transform-classes": "^7.16.0", - "@babel/plugin-transform-computed-properties": "^7.16.0", - "@babel/plugin-transform-destructuring": "^7.16.0", - "@babel/plugin-transform-dotall-regex": "^7.16.0", - "@babel/plugin-transform-duplicate-keys": "^7.16.0", - "@babel/plugin-transform-exponentiation-operator": "^7.16.0", - "@babel/plugin-transform-for-of": "^7.16.0", - "@babel/plugin-transform-function-name": "^7.16.0", - "@babel/plugin-transform-literals": "^7.16.0", - "@babel/plugin-transform-member-expression-literals": "^7.16.0", - "@babel/plugin-transform-modules-amd": "^7.16.0", - "@babel/plugin-transform-modules-commonjs": "^7.16.0", - "@babel/plugin-transform-modules-systemjs": "^7.16.0", - "@babel/plugin-transform-modules-umd": "^7.16.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.0", - "@babel/plugin-transform-new-target": "^7.16.0", - "@babel/plugin-transform-object-super": "^7.16.0", - "@babel/plugin-transform-parameters": "^7.16.3", - "@babel/plugin-transform-property-literals": "^7.16.0", - "@babel/plugin-transform-regenerator": "^7.16.0", - "@babel/plugin-transform-reserved-words": "^7.16.0", - "@babel/plugin-transform-shorthand-properties": "^7.16.0", - "@babel/plugin-transform-spread": "^7.16.0", - "@babel/plugin-transform-sticky-regex": "^7.16.0", - "@babel/plugin-transform-template-literals": "^7.16.0", - "@babel/plugin-transform-typeof-symbol": "^7.16.0", - "@babel/plugin-transform-unicode-escapes": "^7.16.0", - "@babel/plugin-transform-unicode-regex": "^7.16.0", + "@babel/plugin-transform-arrow-functions": "^7.16.5", + "@babel/plugin-transform-async-to-generator": "^7.16.5", + "@babel/plugin-transform-block-scoped-functions": "^7.16.5", + "@babel/plugin-transform-block-scoping": "^7.16.5", + "@babel/plugin-transform-classes": "^7.16.5", + "@babel/plugin-transform-computed-properties": "^7.16.5", + "@babel/plugin-transform-destructuring": "^7.16.5", + "@babel/plugin-transform-dotall-regex": "^7.16.5", + "@babel/plugin-transform-duplicate-keys": "^7.16.5", + "@babel/plugin-transform-exponentiation-operator": "^7.16.5", + "@babel/plugin-transform-for-of": "^7.16.5", + "@babel/plugin-transform-function-name": "^7.16.5", + "@babel/plugin-transform-literals": "^7.16.5", + "@babel/plugin-transform-member-expression-literals": "^7.16.5", + "@babel/plugin-transform-modules-amd": "^7.16.5", + "@babel/plugin-transform-modules-commonjs": "^7.16.5", + "@babel/plugin-transform-modules-systemjs": "^7.16.5", + "@babel/plugin-transform-modules-umd": "^7.16.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.5", + "@babel/plugin-transform-new-target": "^7.16.5", + "@babel/plugin-transform-object-super": "^7.16.5", + "@babel/plugin-transform-parameters": "^7.16.5", + "@babel/plugin-transform-property-literals": "^7.16.5", + "@babel/plugin-transform-regenerator": "^7.16.5", + "@babel/plugin-transform-reserved-words": "^7.16.5", + "@babel/plugin-transform-shorthand-properties": "^7.16.5", + "@babel/plugin-transform-spread": "^7.16.5", + "@babel/plugin-transform-sticky-regex": "^7.16.5", + "@babel/plugin-transform-template-literals": "^7.16.5", + "@babel/plugin-transform-typeof-symbol": "^7.16.5", + "@babel/plugin-transform-unicode-escapes": "^7.16.5", + "@babel/plugin-transform-unicode-regex": "^7.16.5", "@babel/preset-modules": "^0.1.5", "@babel/types": "^7.16.0", "babel-plugin-polyfill-corejs2": "^0.3.0", @@ -1555,13 +1569,13 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.0.tgz", - "integrity": "sha512-txegdrZYgO9DlPbv+9QOVpMnKbOtezsLHWsnsRF4AjbSIsVaujrq1qg8HK0mxQpWv0jnejt0yEoW1uWpvbrDTg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.5.tgz", + "integrity": "sha512-lmAWRoJ9iOSvs3DqOndQpj8XqXkzaiQs50VG/zESiI9D3eoZhGriU675xNCr0UwvsuXrhMAGvyk1w+EVWF3u8Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-typescript": "^7.16.0" + "@babel/plugin-transform-typescript": "^7.16.1" }, "engines": { "node": ">=6.9.0" @@ -1607,16 +1621,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.0.tgz", - "integrity": "sha512-qQ84jIs1aRQxaGaxSysII9TuDaguZ5yVrEuC0BN2vcPlalwfLovVmCjbFDPECPXcYM/wLvNFfp8uDOliLxIoUQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.5.tgz", + "integrity": "sha512-FOCODAzqUMROikDYLYxl4nmwiLlu85rNqBML/A5hKRVXG2LV8d0iMqgPzdYTcIpjZEBB7D6UDU9vxRZiriASdQ==", "dependencies": { "@babel/code-frame": "^7.16.0", - "@babel/generator": "^7.16.0", + "@babel/generator": "^7.16.5", + "@babel/helper-environment-visitor": "^7.16.5", "@babel/helper-function-name": "^7.16.0", "@babel/helper-hoist-variables": "^7.16.0", "@babel/helper-split-export-declaration": "^7.16.0", - "@babel/parser": "^7.16.0", + "@babel/parser": "^7.16.5", "@babel/types": "^7.16.0", "debug": "^4.1.0", "globals": "^11.1.0" @@ -1708,9 +1723,9 @@ } }, "node_modules/@goauthentik/api": { - "version": "2021.10.4-1639076050", - "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2021.10.4-1639076050.tgz", - "integrity": "sha512-Ud8hYHeaz9BCpJwYlOGce41MqhHeHiGVh7nlsWdUIOGCyrraJD3lFaPBgnG1l0M2RpxUeHz2owSUetS23X164g==" + "version": "2021.10.4-1639516687", + "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2021.10.4-1639516687.tgz", + "integrity": "sha512-tnhKa98g2CJY71IS7FgFuxM0lIQkeCUPVfQVNfBq6hq2D4GII7ccWRwiT/krO0syc6w+zPcZriqqAHSCNThdDg==" }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.2", @@ -2113,9 +2128,9 @@ } }, "node_modules/@patternfly/patternfly": { - "version": "4.159.1", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.159.1.tgz", - "integrity": "sha512-CPLE7yAmtETH8TAdQhHkyFmyvjGwsv/7PeR4k57DY9X4IHpx41m4SXrv9cBCr/+Uy8o2SjvE8dtlZb+h0rLByQ==" + "version": "4.164.2", + "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.164.2.tgz", + "integrity": "sha512-gezQi83JKd6tW0z1J6Q5VvMCW/a58+ys4TWcTuXUMqcV3APQdNxVP+ZV6FIv5353oIPi9HuWAaApVwcCxYZYYg==" }, "node_modules/@polymer/font-roboto": { "version": "3.0.2", @@ -2298,9 +2313,9 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@rollup/plugin-node-resolve": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.6.tgz", - "integrity": "sha512-sFsPDMPd4gMqnh2gS0uIxELnoRUp5kBl5knxD2EO0778G1oOJv4G1vyT2cpWz75OU2jDVcXhjVUuTAczGyFNKA==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.1.tgz", + "integrity": "sha512-6QKtRevXLrmEig9UiMYt2fSvee9TyltGRfw+qSs6xjUnxwjOzTOqy+/Lpxsgjb8mJn1EQNbCDAvt89O4uzL5kw==", "dependencies": { "@rollup/pluginutils": "^3.1.0", "@types/resolve": "1.17.1", @@ -2781,12 +2796,12 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.6.0.tgz", - "integrity": "sha512-MIbeMy5qfLqtgs1hWd088k1hOuRsN9JrHUPwVVKCD99EOUqScd7SrwoZl4Gso05EAP9w1kvLWUVGJOVpRPkDPA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz", + "integrity": "sha512-8RTGBpNn5a9M628wBPrCbJ+v3YTEOE2qeZb7TDkGKTDXSj36KGRg92SpFFaR/0S3rSXQxM0Og/kV9EyadsYSBg==", "dependencies": { - "@typescript-eslint/experimental-utils": "5.6.0", - "@typescript-eslint/scope-manager": "5.6.0", + "@typescript-eslint/experimental-utils": "5.7.0", + "@typescript-eslint/scope-manager": "5.7.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -2834,14 +2849,14 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.6.0.tgz", - "integrity": "sha512-VDoRf3Qj7+W3sS/ZBXZh3LBzp0snDLEgvp6qj0vOAIiAPM07bd5ojQ3CTzF/QFl5AKh7Bh1ycgj6lFBJHUt/DA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.7.0.tgz", + "integrity": "sha512-u57eZ5FbEpzN5kSjmVrSesovWslH2ZyNPnaXQMXWgH57d5+EVHEt76W75vVuI9qKZ5BMDKNfRN+pxcPEjQjb2A==", "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.6.0", - "@typescript-eslint/types": "5.6.0", - "@typescript-eslint/typescript-estree": "5.6.0", + "@typescript-eslint/scope-manager": "5.7.0", + "@typescript-eslint/types": "5.7.0", + "@typescript-eslint/typescript-estree": "5.7.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -2857,13 +2872,13 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.6.0.tgz", - "integrity": "sha512-YVK49NgdUPQ8SpCZaOpiq1kLkYRPMv9U5gcMrywzI8brtwZjr/tG3sZpuHyODt76W/A0SufNjYt9ZOgrC4tLIQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.7.0.tgz", + "integrity": "sha512-m/gWCCcS4jXw6vkrPQ1BjZ1vomP01PArgzvauBqzsoZ3urLbsRChexB8/YV8z9HwE3qlJM35FxfKZ1nfP/4x8g==", "dependencies": { - "@typescript-eslint/scope-manager": "5.6.0", - "@typescript-eslint/types": "5.6.0", - "@typescript-eslint/typescript-estree": "5.6.0", + "@typescript-eslint/scope-manager": "5.7.0", + "@typescript-eslint/types": "5.7.0", + "@typescript-eslint/typescript-estree": "5.7.0", "debug": "^4.3.2" }, "engines": { @@ -2883,12 +2898,12 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.6.0.tgz", - "integrity": "sha512-1U1G77Hw2jsGWVsO2w6eVCbOg0HZ5WxL/cozVSTfqnL/eB9muhb8THsP0G3w+BB5xAHv9KptwdfYFAUfzcIh4A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.7.0.tgz", + "integrity": "sha512-7mxR520DGq5F7sSSgM0HSSMJ+TFUymOeFRMfUfGFAVBv8BR+Jv1vHgAouYUvWRZeszVBJlLcc9fDdktxb5kmxA==", "dependencies": { - "@typescript-eslint/types": "5.6.0", - "@typescript-eslint/visitor-keys": "5.6.0" + "@typescript-eslint/types": "5.7.0", + "@typescript-eslint/visitor-keys": "5.7.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2899,9 +2914,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.6.0.tgz", - "integrity": "sha512-OIZffked7mXv4mXzWU5MgAEbCf9ecNJBKi+Si6/I9PpTaj+cf2x58h2oHW5/P/yTnPkKaayfjhLvx+crnl5ubA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.7.0.tgz", + "integrity": "sha512-5AeYIF5p2kAneIpnLFve8g50VyAjq7udM7ApZZ9JYjdPjkz0LvODfuSHIDUVnIuUoxafoWzpFyU7Sqbxgi79mA==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2911,12 +2926,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.6.0.tgz", - "integrity": "sha512-92vK5tQaE81rK7fOmuWMrSQtK1IMonESR+RJR2Tlc7w4o0MeEdjgidY/uO2Gobh7z4Q1hhS94Cr7r021fMVEeA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.7.0.tgz", + "integrity": "sha512-aO1Ql+izMrTnPj5aFFlEJkpD4jRqC4Gwhygu2oHK2wfVQpmOPbyDSveJ+r/NQo+PWV43M6uEAeLVbTi09dFLhg==", "dependencies": { - "@typescript-eslint/types": "5.6.0", - "@typescript-eslint/visitor-keys": "5.6.0", + "@typescript-eslint/types": "5.7.0", + "@typescript-eslint/visitor-keys": "5.7.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -2951,11 +2966,11 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.6.0.tgz", - "integrity": "sha512-1p7hDp5cpRFUyE3+lvA74egs+RWSgumrBpzBCDzfTFv0aQ7lIeay80yU0hIxgAhwQ6PcasW35kaOCyDOv6O/Ng==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.7.0.tgz", + "integrity": "sha512-hdohahZ4lTFcglZSJ3DGdzxQHBSxsLVqHzkiOmKi7xVAWC4y2c1bIMKmPJSrA4aOEoRUPOKQ87Y/taC7yVHpFg==", "dependencies": { - "@typescript-eslint/types": "5.6.0", + "@typescript-eslint/types": "5.7.0", "eslint-visitor-keys": "^3.0.0" }, "engines": { @@ -8331,9 +8346,9 @@ } }, "node_modules/typescript": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.3.tgz", - "integrity": "sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", + "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8820,18 +8835,18 @@ "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==" }, "@babel/core": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.0.tgz", - "integrity": "sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.5.tgz", + "integrity": "sha512-wUcenlLzuWMZ9Zt8S0KmFwGlH6QKRh3vsm/dhDA3CHkiTA45YuG1XkHRcNRl73EFPXDp/d5kVOU0/y7x2w6OaQ==", "requires": { "@babel/code-frame": "^7.16.0", - "@babel/generator": "^7.16.0", - "@babel/helper-compilation-targets": "^7.16.0", - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helpers": "^7.16.0", - "@babel/parser": "^7.16.0", + "@babel/generator": "^7.16.5", + "@babel/helper-compilation-targets": "^7.16.3", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helpers": "^7.16.5", + "@babel/parser": "^7.16.5", "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", @@ -8842,9 +8857,9 @@ } }, "@babel/generator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz", - "integrity": "sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.5.tgz", + "integrity": "sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA==", "requires": { "@babel/types": "^7.16.0", "jsesc": "^2.5.1", @@ -8860,9 +8875,9 @@ } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.0.tgz", - "integrity": "sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.5.tgz", + "integrity": "sha512-3JEA9G5dmmnIWdzaT9d0NmFRgYnWUThLsDaL7982H0XqqWr56lRrsmwheXFMjR+TMl7QMBb6mzy9kvgr1lRLUA==", "requires": { "@babel/helper-explode-assignable-expression": "^7.16.0", "@babel/types": "^7.16.0" @@ -8880,15 +8895,16 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz", - "integrity": "sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.5.tgz", + "integrity": "sha512-NEohnYA7mkB8L5JhU7BLwcBdU3j83IziR9aseMueWGeAjblbul3zzb8UvJ3a1zuBiqCMObzCJHFqKIQE6hTVmg==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-environment-visitor": "^7.16.5", "@babel/helper-function-name": "^7.16.0", - "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-member-expression-to-functions": "^7.16.5", "@babel/helper-optimise-call-expression": "^7.16.0", - "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-replace-supers": "^7.16.5", "@babel/helper-split-export-declaration": "^7.16.0" } }, @@ -8916,6 +8932,14 @@ "semver": "^6.1.2" } }, + "@babel/helper-environment-visitor": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.5.tgz", + "integrity": "sha512-ODQyc5AnxmZWm/R2W7fzhamOk1ey8gSguo5SGvF0zcB3uUzRpTRmM/jmLSm9bDMyPlvbyJ+PwPEK0BWIoZ9wjg==", + "requires": { + "@babel/types": "^7.16.0" + } + }, "@babel/helper-explode-assignable-expression": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz", @@ -8951,9 +8975,9 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz", - "integrity": "sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.5.tgz", + "integrity": "sha512-7fecSXq7ZrLE+TWshbGT+HyCLkxloWNhTbU2QM1NTI/tDqyf0oZiMcEfYtDuUDCo528EOlt39G1rftea4bRZIw==", "requires": { "@babel/types": "^7.16.0" } @@ -8967,17 +8991,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz", - "integrity": "sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.5.tgz", + "integrity": "sha512-CkvMxgV4ZyyioElFwcuWnDCcNIeyqTkCm9BxXZi73RR1ozqlpboqsbGUNvRTflgZtFbbJ1v5Emvm+lkjMYY/LQ==", "requires": { + "@babel/helper-environment-visitor": "^7.16.5", "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-replace-supers": "^7.16.0", "@babel/helper-simple-access": "^7.16.0", "@babel/helper-split-export-declaration": "^7.16.0", "@babel/helper-validator-identifier": "^7.15.7", "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0" } }, @@ -8990,28 +9014,29 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==" + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.5.tgz", + "integrity": "sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ==" }, "@babel/helper-remap-async-to-generator": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.4.tgz", - "integrity": "sha512-vGERmmhR+s7eH5Y/cp8PCVzj4XEjerq8jooMfxFdA5xVtAk9Sh4AQsrWgiErUEBjtGrBtOFKDUcWQFW4/dFwMA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.5.tgz", + "integrity": "sha512-X+aAJldyxrOmN9v3FKp+Hu1NO69VWgYgDGq6YDykwRPzxs5f2N+X988CBXS7EQahDU+Vpet5QYMqLk+nsp+Qxw==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.0", - "@babel/helper-wrap-function": "^7.16.0", + "@babel/helper-wrap-function": "^7.16.5", "@babel/types": "^7.16.0" } }, "@babel/helper-replace-supers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz", - "integrity": "sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.5.tgz", + "integrity": "sha512-ao3seGVa/FZCMCCNDuBcqnBFSbdr8N2EW35mzojx3TwfIbdPmNK+JV6+2d5bR0Z71W5ocLnQp9en/cTF7pBJiQ==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-environment-visitor": "^7.16.5", + "@babel/helper-member-expression-to-functions": "^7.16.5", "@babel/helper-optimise-call-expression": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0" } }, @@ -9050,23 +9075,23 @@ "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==" }, "@babel/helper-wrap-function": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.0.tgz", - "integrity": "sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.5.tgz", + "integrity": "sha512-2J2pmLBqUqVdJw78U0KPNdeE2qeuIyKoG4mKV7wAq3mc4jJG282UgjZw4ZYDnqiWQuS3Y3IYdF/AQ6CpyBV3VA==", "requires": { "@babel/helper-function-name": "^7.16.0", "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0" } }, "@babel/helpers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.0.tgz", - "integrity": "sha512-dVRM0StFMdKlkt7cVcGgwD8UMaBfWJHl3A83Yfs8GQ3MO0LHIIIMvK7Fa0RGOGUQ10qikLaX6D7o5htcQWgTMQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.5.tgz", + "integrity": "sha512-TLgi6Lh71vvMZGEkFuIxzaPsyeYCHQ5jJOOX1f0xXn0uciFuE8cEk0wyBquMcCxBXZ5BJhE2aUB7pnWTD150Tw==", "requires": { "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.0", + "@babel/traverse": "^7.16.5", "@babel/types": "^7.16.0" } }, @@ -9081,9 +9106,9 @@ } }, "@babel/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-TEHWXf0xxpi9wKVyBCmRcSSDjbJ/cl6LUdlbYUHEaNQUJGhreJbZrXT6sR4+fZLxVUJqNRB4KyOvjuy/D9009A==" + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.5.tgz", + "integrity": "sha512-+Ce7T5iPNWzfu9C1aB5tN3Lyafs5xb3Ic7vBWyZL2KXT3QSdD1dD3CvgOzPmQKoNNRt6uauc0XwNJTQtXC2/Mw==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.16.2", @@ -9104,156 +9129,156 @@ } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.4.tgz", - "integrity": "sha512-/CUekqaAaZCQHleSK/9HajvcD/zdnJiKRiuUFq8ITE+0HsPzquf53cpFiqAwl/UfmJbR6n5uGPQSPdrmKOvHHg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.5.tgz", + "integrity": "sha512-C/FX+3HNLV6sz7AqbTQqEo1L9/kfrKjxcVtgyBCmvIgOjvuBVUWooDoi7trsLxOzCEo5FccjRvKHkfDsJFZlfA==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.16.4", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-remap-async-to-generator": "^7.16.5", "@babel/plugin-syntax-async-generators": "^7.8.4" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz", - "integrity": "sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.5.tgz", + "integrity": "sha512-pJD3HjgRv83s5dv1sTnDbZOaTjghKEz8KUn1Kbh2eAIRhGuyQ1XSeI4xVXU3UlIEVA3DAyIdxqT1eRn7Wcn55A==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-proposal-class-static-block": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.0.tgz", - "integrity": "sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.5.tgz", + "integrity": "sha512-EEFzuLZcm/rNJ8Q5krK+FRKdVkd6FjfzT9tuSZql9sQn64K0hHA2KLJ0DqVot9/iV6+SsuadC5yI39zWnm+nmQ==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" } }, "@babel/plugin-proposal-decorators": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.16.4.tgz", - "integrity": "sha512-RESBNX16eNqnBeEVR5sCJpnW0mHiNLNNvGA8PrRuK/4ZJ4TO+6bHleRUuGQYDERVySOKtOhSya/C4MIhwAMAgg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.16.5.tgz", + "integrity": "sha512-XAiZll5oCdp2Dd2RbXA3LVPlFyIRhhcQy+G34p9ePpl6mjFkbqHAYHovyw2j5mqUrlBf0/+MtOIJ3JGYtz8qaw==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-decorators": "^7.16.0" + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-decorators": "^7.16.5" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz", - "integrity": "sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.5.tgz", + "integrity": "sha512-P05/SJZTTvHz79LNYTF8ff5xXge0kk5sIIWAypcWgX4BTRUgyHc8wRxJ/Hk+mU0KXldgOOslKaeqnhthcDJCJQ==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-proposal-export-namespace-from": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.0.tgz", - "integrity": "sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.5.tgz", + "integrity": "sha512-i+sltzEShH1vsVydvNaTRsgvq2vZsfyrd7K7vPLUU/KgS0D5yZMe6uipM0+izminnkKrEfdUnz7CxMRb6oHZWw==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.0.tgz", - "integrity": "sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.5.tgz", + "integrity": "sha512-QQJueTFa0y9E4qHANqIvMsuxM/qcLQmKttBACtPCQzGUEizsXDACGonlPiSwynHfOa3vNw0FPMVvQzbuXwh4SQ==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz", - "integrity": "sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.5.tgz", + "integrity": "sha512-xqibl7ISO2vjuQM+MzR3rkd0zfNWltk7n9QhaD8ghMmMceVguYrNDt7MikRyj4J4v3QehpnrU8RYLnC7z/gZLA==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz", - "integrity": "sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.5.tgz", + "integrity": "sha512-YwMsTp/oOviSBhrjwi0vzCUycseCYwoXnLiXIL3YNjHSMBHicGTz7GjVU/IGgz4DtOEXBdCNG72pvCX22ehfqg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz", - "integrity": "sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.5.tgz", + "integrity": "sha512-DvB9l/TcsCRvsIV9v4jxR/jVP45cslTVC0PMVHvaJhhNuhn2Y1SOhCSFlPK777qLB5wb8rVDaNoqMTyOqtY5Iw==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.0.tgz", - "integrity": "sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.5.tgz", + "integrity": "sha512-UEd6KpChoyPhCoE840KRHOlGhEZFutdPDMGj+0I56yuTTOaT51GzmnEl/0uT41fB/vD2nT+Pci2KjezyE3HmUw==", "requires": { - "@babel/compat-data": "^7.16.0", - "@babel/helper-compilation-targets": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/compat-data": "^7.16.4", + "@babel/helper-compilation-targets": "^7.16.3", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.16.0" + "@babel/plugin-transform-parameters": "^7.16.5" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.0.tgz", - "integrity": "sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.5.tgz", + "integrity": "sha512-ihCMxY1Iljmx4bWy/PIMJGXN4NS4oUj1MKynwO07kiKms23pNvIn1DMB92DNB2R0EA882sw0VXIelYGdtF7xEQ==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz", - "integrity": "sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.5.tgz", + "integrity": "sha512-kzdHgnaXRonttiTfKYnSVafbWngPPr2qKw9BWYBESl91W54e+9R5pP70LtWxV56g0f05f/SQrwHYkfvbwcdQ/A==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-proposal-private-methods": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz", - "integrity": "sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.5.tgz", + "integrity": "sha512-+yFMO4BGT3sgzXo+lrq7orX5mAZt57DwUK6seqII6AcJnJOIhBJ8pzKH47/ql/d426uQ7YhN8DpUFirQzqYSUA==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-proposal-private-property-in-object": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz", - "integrity": "sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.5.tgz", + "integrity": "sha512-+YGh5Wbw0NH3y/E5YMu6ci5qTDmAEVNoZ3I54aB6nVEOZ5BQ7QJlwKq5pYVucQilMByGn/bvX0af+uNaPRCabA==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.0", - "@babel/helper-create-class-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.0.tgz", - "integrity": "sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.5.tgz", + "integrity": "sha512-s5sKtlKQyFSatt781HQwv1hoM5BQ9qRH30r+dK56OLDsHmV74mzwJNX7R1yMuE7VZKG5O6q/gmOGSAO6ikTudg==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-syntax-async-generators": { @@ -9281,11 +9306,11 @@ } }, "@babel/plugin-syntax-decorators": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.16.0.tgz", - "integrity": "sha512-nxnnngZClvlY13nHJAIDow0S7Qzhq64fQ/NlqS+VER3kjW/4F0jLhXjeL8jcwSwz6Ca3rotT5NJD2T9I7lcv7g==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.16.5.tgz", + "integrity": "sha512-3CbYTXfflvyy8O819uhZcZSMedZG4J8yS/NLTc/8T24M9ke1GssTGvg8VZu3Yn2LU5IyQSv1CmPq0a9JWHXJwg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-syntax-dynamic-import": { @@ -9393,234 +9418,235 @@ } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.0.tgz", - "integrity": "sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.5.tgz", + "integrity": "sha512-8bTHiiZyMOyfZFULjsCnYOWG059FVMes0iljEHSfARhNgFfpsqE92OrCffv3veSw9rwMkYcFe9bj0ZoXU2IGtQ==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.0.tgz", - "integrity": "sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.5.tgz", + "integrity": "sha512-TMXgfioJnkXU+XRoj7P2ED7rUm5jbnDWwlCuFVTpQboMfbSya5WrmubNBAMlk7KXvywpo8rd8WuYZkis1o2H8w==", "requires": { "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.16.0" + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-remap-async-to-generator": "^7.16.5" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.0.tgz", - "integrity": "sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.5.tgz", + "integrity": "sha512-BxmIyKLjUGksJ99+hJyL/HIxLIGnLKtw772zYDER7UuycDZ+Xvzs98ZQw6NGgM2ss4/hlFAaGiZmMNKvValEjw==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.0.tgz", - "integrity": "sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.5.tgz", + "integrity": "sha512-JxjSPNZSiOtmxjX7PBRBeRJTUKTyJ607YUYeT0QJCNdsedOe+/rXITjP08eG8xUpsLfPirgzdCFN+h0w6RI+pQ==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-classes": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.0.tgz", - "integrity": "sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.5.tgz", + "integrity": "sha512-DzJ1vYf/7TaCYy57J3SJ9rV+JEuvmlnvvyvYKFbk5u46oQbBvuB9/0w+YsVsxkOv8zVWKpDmUoj4T5ILHoXevA==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-environment-visitor": "^7.16.5", "@babel/helper-function-name": "^7.16.0", "@babel/helper-optimise-call-expression": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-replace-supers": "^7.16.5", "@babel/helper-split-export-declaration": "^7.16.0", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.0.tgz", - "integrity": "sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.5.tgz", + "integrity": "sha512-n1+O7xtU5lSLraRzX88CNcpl7vtGdPakKzww74bVwpAIRgz9JVLJJpOLb0uYqcOaXVM0TL6X0RVeIJGD2CnCkg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-destructuring": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.0.tgz", - "integrity": "sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.5.tgz", + "integrity": "sha512-GuRVAsjq+c9YPK6NeTkRLWyQskDC099XkBSVO+6QzbnOnH2d/4mBVXYStaPrZD3dFRfg00I6BFJ9Atsjfs8mlg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.0.tgz", - "integrity": "sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.5.tgz", + "integrity": "sha512-iQiEMt8Q4/5aRGHpGVK2Zc7a6mx7qEAO7qehgSug3SDImnuMzgmm/wtJALXaz25zUj1PmnNHtShjFgk4PDx4nw==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.0.tgz", - "integrity": "sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.5.tgz", + "integrity": "sha512-81tijpDg2a6I1Yhj4aWY1l3O1J4Cg/Pd7LfvuaH2VVInAkXtzibz9+zSPdUM1WvuUi128ksstAP0hM5w48vQgg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.0.tgz", - "integrity": "sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.5.tgz", + "integrity": "sha512-12rba2HwemQPa7BLIKCzm1pT2/RuQHtSFHdNl41cFiC6oi4tcrp7gjB07pxQvFpcADojQywSjblQth6gJyE6CA==", "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-for-of": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.0.tgz", - "integrity": "sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.5.tgz", + "integrity": "sha512-+DpCAJFPAvViR17PIMi9x2AE34dll5wNlXO43wagAX2YcRGgEVHCNFC4azG85b4YyyFarvkc/iD5NPrz4Oneqw==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-function-name": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.0.tgz", - "integrity": "sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.5.tgz", + "integrity": "sha512-Fuec/KPSpVLbGo6z1RPw4EE1X+z9gZk1uQmnYy7v4xr4TO9p41v1AoUuXEtyqAI7H+xNJYSICzRqZBhDEkd3kQ==", "requires": { "@babel/helper-function-name": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-literals": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.0.tgz", - "integrity": "sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.5.tgz", + "integrity": "sha512-B1j9C/IfvshnPcklsc93AVLTrNVa69iSqztylZH6qnmiAsDDOmmjEYqOm3Ts2lGSgTSywnBNiqC949VdD0/gfw==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.0.tgz", - "integrity": "sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.5.tgz", + "integrity": "sha512-d57i3vPHWgIde/9Y8W/xSFUndhvhZN5Wu2TjRrN1MVz5KzdUihKnfDVlfP1U7mS5DNj/WHHhaE4/tTi4hIyHwQ==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.0.tgz", - "integrity": "sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.5.tgz", + "integrity": "sha512-oHI15S/hdJuSCfnwIz+4lm6wu/wBn7oJ8+QrkzPPwSFGXk8kgdI/AIKcbR/XnD1nQVMg/i6eNaXpszbGuwYDRQ==", "requires": { - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz", - "integrity": "sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.5.tgz", + "integrity": "sha512-ABhUkxvoQyqhCWyb8xXtfwqNMJD7tx+irIRnUh6lmyFud7Jln1WzONXKlax1fg/ey178EXbs4bSGNd6PngO+SQ==", "requires": { - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-simple-access": "^7.16.0", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.0.tgz", - "integrity": "sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.5.tgz", + "integrity": "sha512-53gmLdScNN28XpjEVIm7LbWnD/b/TpbwKbLk6KV4KqC9WyU6rq1jnNmVG6UgAdQZVVGZVoik3DqHNxk4/EvrjA==", "requires": { "@babel/helper-hoist-variables": "^7.16.0", - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-validator-identifier": "^7.15.7", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.0.tgz", - "integrity": "sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.5.tgz", + "integrity": "sha512-qTFnpxHMoenNHkS3VoWRdwrcJ3FhX567GvDA3hRZKF0Dj8Fmg0UzySZp3AP2mShl/bzcywb/UWAMQIjA1bhXvw==", "requires": { - "@babel/helper-module-transforms": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.0.tgz", - "integrity": "sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.5.tgz", + "integrity": "sha512-/wqGDgvFUeKELW6ex6QB7dLVRkd5ehjw34tpXu1nhKC0sFfmaLabIswnpf8JgDyV2NeDmZiwoOb0rAmxciNfjA==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.0" } }, "@babel/plugin-transform-new-target": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.0.tgz", - "integrity": "sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.5.tgz", + "integrity": "sha512-ZaIrnXF08ZC8jnKR4/5g7YakGVL6go6V9ql6Jl3ecO8PQaQqFE74CuM384kezju7Z9nGCCA20BqZaR1tJ/WvHg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-object-super": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.0.tgz", - "integrity": "sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.5.tgz", + "integrity": "sha512-tded+yZEXuxt9Jdtkc1RraW1zMF/GalVxaVVxh41IYwirdRgyAxxxCKZ9XB7LxZqmsjfjALxupNE1MIz9KH+Zg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.16.0" + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-replace-supers": "^7.16.5" } }, "@babel/plugin-transform-parameters": { - "version": "7.16.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.3.tgz", - "integrity": "sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.5.tgz", + "integrity": "sha512-B3O6AL5oPop1jAVg8CV+haeUte9oFuY85zu0jwnRNZZi3tVAbJriu5tag/oaO2kGaQM/7q7aGPBlTI5/sr9enA==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-property-literals": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.0.tgz", - "integrity": "sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.5.tgz", + "integrity": "sha512-+IRcVW71VdF9pEH/2R/Apab4a19LVvdVsr/gEeotH00vSDVlKD+XgfSIw+cgGWsjDB/ziqGv/pGoQZBIiQVXHg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-regenerator": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.0.tgz", - "integrity": "sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.5.tgz", + "integrity": "sha512-2z+it2eVWU8TtQQRauvGUqZwLy4+7rTfo6wO4npr+fvvN1SW30ZF3O/ZRCNmTuu4F5MIP8OJhXAhRV5QMJOuYg==", "requires": { "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.0.tgz", - "integrity": "sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.5.tgz", + "integrity": "sha512-aIB16u8lNcf7drkhXJRoggOxSTUAuihTSTfAcpynowGJOZiGf+Yvi7RuTwFzVYSYPmWyARsPqUGoZWWWxLiknw==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-runtime": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.4.tgz", - "integrity": "sha512-pru6+yHANMTukMtEZGC4fs7XPwg35v8sj5CIEmE+gEkFljFiVJxEWxx/7ZDkTK+iZRYo1bFXBtfIN95+K3cJ5A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.5.tgz", + "integrity": "sha512-gxpfS8XQWDbQ8oP5NcmpXxtEgCJkbO+W9VhZlOhr0xPyVaRjAQPOv7ZDj9fg0d5s9+NiVvMCE6gbkEkcsxwGRw==", "requires": { "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "babel-plugin-polyfill-corejs2": "^0.3.0", "babel-plugin-polyfill-corejs3": "^0.4.0", "babel-plugin-polyfill-regenerator": "^0.3.0", @@ -9628,44 +9654,44 @@ } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.0.tgz", - "integrity": "sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.5.tgz", + "integrity": "sha512-ZbuWVcY+MAXJuuW7qDoCwoxDUNClfZxoo7/4swVbOW1s/qYLOMHlm9YRWMsxMFuLs44eXsv4op1vAaBaBaDMVg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-spread": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.0.tgz", - "integrity": "sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.5.tgz", + "integrity": "sha512-5d6l/cnG7Lw4tGHEoga4xSkYp1euP7LAtrah1h1PgJ3JY7yNsjybsxQAnVK4JbtReZ/8z6ASVmd3QhYYKLaKZw==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.0.tgz", - "integrity": "sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.5.tgz", + "integrity": "sha512-usYsuO1ID2LXxzuUxifgWtJemP7wL2uZtyrTVM4PKqsmJycdS4U4mGovL5xXkfUheds10Dd2PjoQLXw6zCsCbg==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-template-literals": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.0.tgz", - "integrity": "sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.5.tgz", + "integrity": "sha512-gnyKy9RyFhkovex4BjKWL3BVYzUDG6zC0gba7VMLbQoDuqMfJ1SDXs8k/XK41Mmt1Hyp4qNAvGFb9hKzdCqBRQ==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.0.tgz", - "integrity": "sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.5.tgz", + "integrity": "sha512-ldxCkW180qbrvyCVDzAUZqB0TAeF8W/vGJoRcaf75awm6By+PxfJKvuqVAnq8N9wz5Xa6mSpM19OfVKKVmGHSQ==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-typescript": { @@ -9679,48 +9705,48 @@ } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.0.tgz", - "integrity": "sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.5.tgz", + "integrity": "sha512-shiCBHTIIChGLdyojsKQjoAyB8MBwat25lKM7MJjbe1hE0bgIppD+LX9afr41lLHOhqceqeWl4FkLp+Bgn9o1Q==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.0.tgz", - "integrity": "sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.5.tgz", + "integrity": "sha512-GTJ4IW012tiPEMMubd7sD07iU9O/LOo8Q/oU4xNhcaq0Xn8+6TcUQaHtC8YxySo1T+ErQ8RaWogIEeFhKGNPzw==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.0", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.5" } }, "@babel/preset-env": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.4.tgz", - "integrity": "sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.5.tgz", + "integrity": "sha512-MiJJW5pwsktG61NDxpZ4oJ1CKxM1ncam9bzRtx9g40/WkLRkxFP6mhpkYV0/DxcciqoiHicx291+eUQrXb/SfQ==", "requires": { "@babel/compat-data": "^7.16.4", "@babel/helper-compilation-targets": "^7.16.3", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-validator-option": "^7.14.5", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.2", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.0", - "@babel/plugin-proposal-async-generator-functions": "^7.16.4", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/plugin-proposal-class-static-block": "^7.16.0", - "@babel/plugin-proposal-dynamic-import": "^7.16.0", - "@babel/plugin-proposal-export-namespace-from": "^7.16.0", - "@babel/plugin-proposal-json-strings": "^7.16.0", - "@babel/plugin-proposal-logical-assignment-operators": "^7.16.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", - "@babel/plugin-proposal-numeric-separator": "^7.16.0", - "@babel/plugin-proposal-object-rest-spread": "^7.16.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.0", - "@babel/plugin-proposal-private-methods": "^7.16.0", - "@babel/plugin-proposal-private-property-in-object": "^7.16.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.16.0", + "@babel/plugin-proposal-async-generator-functions": "^7.16.5", + "@babel/plugin-proposal-class-properties": "^7.16.5", + "@babel/plugin-proposal-class-static-block": "^7.16.5", + "@babel/plugin-proposal-dynamic-import": "^7.16.5", + "@babel/plugin-proposal-export-namespace-from": "^7.16.5", + "@babel/plugin-proposal-json-strings": "^7.16.5", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.5", + "@babel/plugin-proposal-numeric-separator": "^7.16.5", + "@babel/plugin-proposal-object-rest-spread": "^7.16.5", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.5", + "@babel/plugin-proposal-optional-chaining": "^7.16.5", + "@babel/plugin-proposal-private-methods": "^7.16.5", + "@babel/plugin-proposal-private-property-in-object": "^7.16.5", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.5", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", @@ -9735,38 +9761,38 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.16.0", - "@babel/plugin-transform-async-to-generator": "^7.16.0", - "@babel/plugin-transform-block-scoped-functions": "^7.16.0", - "@babel/plugin-transform-block-scoping": "^7.16.0", - "@babel/plugin-transform-classes": "^7.16.0", - "@babel/plugin-transform-computed-properties": "^7.16.0", - "@babel/plugin-transform-destructuring": "^7.16.0", - "@babel/plugin-transform-dotall-regex": "^7.16.0", - "@babel/plugin-transform-duplicate-keys": "^7.16.0", - "@babel/plugin-transform-exponentiation-operator": "^7.16.0", - "@babel/plugin-transform-for-of": "^7.16.0", - "@babel/plugin-transform-function-name": "^7.16.0", - "@babel/plugin-transform-literals": "^7.16.0", - "@babel/plugin-transform-member-expression-literals": "^7.16.0", - "@babel/plugin-transform-modules-amd": "^7.16.0", - "@babel/plugin-transform-modules-commonjs": "^7.16.0", - "@babel/plugin-transform-modules-systemjs": "^7.16.0", - "@babel/plugin-transform-modules-umd": "^7.16.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.0", - "@babel/plugin-transform-new-target": "^7.16.0", - "@babel/plugin-transform-object-super": "^7.16.0", - "@babel/plugin-transform-parameters": "^7.16.3", - "@babel/plugin-transform-property-literals": "^7.16.0", - "@babel/plugin-transform-regenerator": "^7.16.0", - "@babel/plugin-transform-reserved-words": "^7.16.0", - "@babel/plugin-transform-shorthand-properties": "^7.16.0", - "@babel/plugin-transform-spread": "^7.16.0", - "@babel/plugin-transform-sticky-regex": "^7.16.0", - "@babel/plugin-transform-template-literals": "^7.16.0", - "@babel/plugin-transform-typeof-symbol": "^7.16.0", - "@babel/plugin-transform-unicode-escapes": "^7.16.0", - "@babel/plugin-transform-unicode-regex": "^7.16.0", + "@babel/plugin-transform-arrow-functions": "^7.16.5", + "@babel/plugin-transform-async-to-generator": "^7.16.5", + "@babel/plugin-transform-block-scoped-functions": "^7.16.5", + "@babel/plugin-transform-block-scoping": "^7.16.5", + "@babel/plugin-transform-classes": "^7.16.5", + "@babel/plugin-transform-computed-properties": "^7.16.5", + "@babel/plugin-transform-destructuring": "^7.16.5", + "@babel/plugin-transform-dotall-regex": "^7.16.5", + "@babel/plugin-transform-duplicate-keys": "^7.16.5", + "@babel/plugin-transform-exponentiation-operator": "^7.16.5", + "@babel/plugin-transform-for-of": "^7.16.5", + "@babel/plugin-transform-function-name": "^7.16.5", + "@babel/plugin-transform-literals": "^7.16.5", + "@babel/plugin-transform-member-expression-literals": "^7.16.5", + "@babel/plugin-transform-modules-amd": "^7.16.5", + "@babel/plugin-transform-modules-commonjs": "^7.16.5", + "@babel/plugin-transform-modules-systemjs": "^7.16.5", + "@babel/plugin-transform-modules-umd": "^7.16.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.5", + "@babel/plugin-transform-new-target": "^7.16.5", + "@babel/plugin-transform-object-super": "^7.16.5", + "@babel/plugin-transform-parameters": "^7.16.5", + "@babel/plugin-transform-property-literals": "^7.16.5", + "@babel/plugin-transform-regenerator": "^7.16.5", + "@babel/plugin-transform-reserved-words": "^7.16.5", + "@babel/plugin-transform-shorthand-properties": "^7.16.5", + "@babel/plugin-transform-spread": "^7.16.5", + "@babel/plugin-transform-sticky-regex": "^7.16.5", + "@babel/plugin-transform-template-literals": "^7.16.5", + "@babel/plugin-transform-typeof-symbol": "^7.16.5", + "@babel/plugin-transform-unicode-escapes": "^7.16.5", + "@babel/plugin-transform-unicode-regex": "^7.16.5", "@babel/preset-modules": "^0.1.5", "@babel/types": "^7.16.0", "babel-plugin-polyfill-corejs2": "^0.3.0", @@ -9789,13 +9815,13 @@ } }, "@babel/preset-typescript": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.0.tgz", - "integrity": "sha512-txegdrZYgO9DlPbv+9QOVpMnKbOtezsLHWsnsRF4AjbSIsVaujrq1qg8HK0mxQpWv0jnejt0yEoW1uWpvbrDTg==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.5.tgz", + "integrity": "sha512-lmAWRoJ9iOSvs3DqOndQpj8XqXkzaiQs50VG/zESiI9D3eoZhGriU675xNCr0UwvsuXrhMAGvyk1w+EVWF3u8Q==", "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.5", "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-typescript": "^7.16.0" + "@babel/plugin-transform-typescript": "^7.16.1" } }, "@babel/runtime": { @@ -9826,16 +9852,17 @@ } }, "@babel/traverse": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.0.tgz", - "integrity": "sha512-qQ84jIs1aRQxaGaxSysII9TuDaguZ5yVrEuC0BN2vcPlalwfLovVmCjbFDPECPXcYM/wLvNFfp8uDOliLxIoUQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.5.tgz", + "integrity": "sha512-FOCODAzqUMROikDYLYxl4nmwiLlu85rNqBML/A5hKRVXG2LV8d0iMqgPzdYTcIpjZEBB7D6UDU9vxRZiriASdQ==", "requires": { "@babel/code-frame": "^7.16.0", - "@babel/generator": "^7.16.0", + "@babel/generator": "^7.16.5", + "@babel/helper-environment-visitor": "^7.16.5", "@babel/helper-function-name": "^7.16.0", "@babel/helper-hoist-variables": "^7.16.0", "@babel/helper-split-export-declaration": "^7.16.0", - "@babel/parser": "^7.16.0", + "@babel/parser": "^7.16.5", "@babel/types": "^7.16.0", "debug": "^4.1.0", "globals": "^11.1.0" @@ -9898,9 +9925,9 @@ "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==" }, "@goauthentik/api": { - "version": "2021.10.4-1639076050", - "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2021.10.4-1639076050.tgz", - "integrity": "sha512-Ud8hYHeaz9BCpJwYlOGce41MqhHeHiGVh7nlsWdUIOGCyrraJD3lFaPBgnG1l0M2RpxUeHz2owSUetS23X164g==" + "version": "2021.10.4-1639516687", + "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2021.10.4-1639516687.tgz", + "integrity": "sha512-tnhKa98g2CJY71IS7FgFuxM0lIQkeCUPVfQVNfBq6hq2D4GII7ccWRwiT/krO0syc6w+zPcZriqqAHSCNThdDg==" }, "@humanwhocodes/config-array": { "version": "0.9.2", @@ -10199,9 +10226,9 @@ } }, "@patternfly/patternfly": { - "version": "4.159.1", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.159.1.tgz", - "integrity": "sha512-CPLE7yAmtETH8TAdQhHkyFmyvjGwsv/7PeR4k57DY9X4IHpx41m4SXrv9cBCr/+Uy8o2SjvE8dtlZb+h0rLByQ==" + "version": "4.164.2", + "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.164.2.tgz", + "integrity": "sha512-gezQi83JKd6tW0z1J6Q5VvMCW/a58+ys4TWcTuXUMqcV3APQdNxVP+ZV6FIv5353oIPi9HuWAaApVwcCxYZYYg==" }, "@polymer/font-roboto": { "version": "3.0.2", @@ -10367,9 +10394,9 @@ } }, "@rollup/plugin-node-resolve": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.6.tgz", - "integrity": "sha512-sFsPDMPd4gMqnh2gS0uIxELnoRUp5kBl5knxD2EO0778G1oOJv4G1vyT2cpWz75OU2jDVcXhjVUuTAczGyFNKA==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.1.tgz", + "integrity": "sha512-6QKtRevXLrmEig9UiMYt2fSvee9TyltGRfw+qSs6xjUnxwjOzTOqy+/Lpxsgjb8mJn1EQNbCDAvt89O4uzL5kw==", "requires": { "@rollup/pluginutils": "^3.1.0", "@types/resolve": "1.17.1", @@ -10793,12 +10820,12 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" }, "@typescript-eslint/eslint-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.6.0.tgz", - "integrity": "sha512-MIbeMy5qfLqtgs1hWd088k1hOuRsN9JrHUPwVVKCD99EOUqScd7SrwoZl4Gso05EAP9w1kvLWUVGJOVpRPkDPA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz", + "integrity": "sha512-8RTGBpNn5a9M628wBPrCbJ+v3YTEOE2qeZb7TDkGKTDXSj36KGRg92SpFFaR/0S3rSXQxM0Og/kV9EyadsYSBg==", "requires": { - "@typescript-eslint/experimental-utils": "5.6.0", - "@typescript-eslint/scope-manager": "5.6.0", + "@typescript-eslint/experimental-utils": "5.7.0", + "@typescript-eslint/scope-manager": "5.7.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -10823,50 +10850,50 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.6.0.tgz", - "integrity": "sha512-VDoRf3Qj7+W3sS/ZBXZh3LBzp0snDLEgvp6qj0vOAIiAPM07bd5ojQ3CTzF/QFl5AKh7Bh1ycgj6lFBJHUt/DA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.7.0.tgz", + "integrity": "sha512-u57eZ5FbEpzN5kSjmVrSesovWslH2ZyNPnaXQMXWgH57d5+EVHEt76W75vVuI9qKZ5BMDKNfRN+pxcPEjQjb2A==", "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.6.0", - "@typescript-eslint/types": "5.6.0", - "@typescript-eslint/typescript-estree": "5.6.0", + "@typescript-eslint/scope-manager": "5.7.0", + "@typescript-eslint/types": "5.7.0", + "@typescript-eslint/typescript-estree": "5.7.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/parser": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.6.0.tgz", - "integrity": "sha512-YVK49NgdUPQ8SpCZaOpiq1kLkYRPMv9U5gcMrywzI8brtwZjr/tG3sZpuHyODt76W/A0SufNjYt9ZOgrC4tLIQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.7.0.tgz", + "integrity": "sha512-m/gWCCcS4jXw6vkrPQ1BjZ1vomP01PArgzvauBqzsoZ3urLbsRChexB8/YV8z9HwE3qlJM35FxfKZ1nfP/4x8g==", "requires": { - "@typescript-eslint/scope-manager": "5.6.0", - "@typescript-eslint/types": "5.6.0", - "@typescript-eslint/typescript-estree": "5.6.0", + "@typescript-eslint/scope-manager": "5.7.0", + "@typescript-eslint/types": "5.7.0", + "@typescript-eslint/typescript-estree": "5.7.0", "debug": "^4.3.2" } }, "@typescript-eslint/scope-manager": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.6.0.tgz", - "integrity": "sha512-1U1G77Hw2jsGWVsO2w6eVCbOg0HZ5WxL/cozVSTfqnL/eB9muhb8THsP0G3w+BB5xAHv9KptwdfYFAUfzcIh4A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.7.0.tgz", + "integrity": "sha512-7mxR520DGq5F7sSSgM0HSSMJ+TFUymOeFRMfUfGFAVBv8BR+Jv1vHgAouYUvWRZeszVBJlLcc9fDdktxb5kmxA==", "requires": { - "@typescript-eslint/types": "5.6.0", - "@typescript-eslint/visitor-keys": "5.6.0" + "@typescript-eslint/types": "5.7.0", + "@typescript-eslint/visitor-keys": "5.7.0" } }, "@typescript-eslint/types": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.6.0.tgz", - "integrity": "sha512-OIZffked7mXv4mXzWU5MgAEbCf9ecNJBKi+Si6/I9PpTaj+cf2x58h2oHW5/P/yTnPkKaayfjhLvx+crnl5ubA==" + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.7.0.tgz", + "integrity": "sha512-5AeYIF5p2kAneIpnLFve8g50VyAjq7udM7ApZZ9JYjdPjkz0LvODfuSHIDUVnIuUoxafoWzpFyU7Sqbxgi79mA==" }, "@typescript-eslint/typescript-estree": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.6.0.tgz", - "integrity": "sha512-92vK5tQaE81rK7fOmuWMrSQtK1IMonESR+RJR2Tlc7w4o0MeEdjgidY/uO2Gobh7z4Q1hhS94Cr7r021fMVEeA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.7.0.tgz", + "integrity": "sha512-aO1Ql+izMrTnPj5aFFlEJkpD4jRqC4Gwhygu2oHK2wfVQpmOPbyDSveJ+r/NQo+PWV43M6uEAeLVbTi09dFLhg==", "requires": { - "@typescript-eslint/types": "5.6.0", - "@typescript-eslint/visitor-keys": "5.6.0", + "@typescript-eslint/types": "5.7.0", + "@typescript-eslint/visitor-keys": "5.7.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -10885,11 +10912,11 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.6.0.tgz", - "integrity": "sha512-1p7hDp5cpRFUyE3+lvA74egs+RWSgumrBpzBCDzfTFv0aQ7lIeay80yU0hIxgAhwQ6PcasW35kaOCyDOv6O/Ng==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.7.0.tgz", + "integrity": "sha512-hdohahZ4lTFcglZSJ3DGdzxQHBSxsLVqHzkiOmKi7xVAWC4y2c1bIMKmPJSrA4aOEoRUPOKQ87Y/taC7yVHpFg==", "requires": { - "@typescript-eslint/types": "5.6.0", + "@typescript-eslint/types": "5.7.0", "eslint-visitor-keys": "^3.0.0" }, "dependencies": { @@ -14916,9 +14943,9 @@ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" }, "typescript": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.3.tgz", - "integrity": "sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ==" + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", + "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==" }, "uglify-js": { "version": "3.14.1", diff --git a/web/package.json b/web/package.json index 5d05e7ded5..26164f6162 100644 --- a/web/package.json +++ b/web/package.json @@ -45,24 +45,24 @@ ] }, "dependencies": { - "@babel/core": "^7.16.0", - "@babel/plugin-proposal-decorators": "^7.16.4", - "@babel/plugin-transform-runtime": "^7.16.4", - "@babel/preset-env": "^7.16.4", - "@babel/preset-typescript": "^7.16.0", + "@babel/core": "^7.16.5", + "@babel/plugin-proposal-decorators": "^7.16.5", + "@babel/plugin-transform-runtime": "^7.16.5", + "@babel/preset-env": "^7.16.5", + "@babel/preset-typescript": "^7.16.5", "@fortawesome/fontawesome-free": "^5.15.4", - "@goauthentik/api": "^2021.10.4-1639076050", + "@goauthentik/api": "^2021.10.4-1639516687", "@jackfranklin/rollup-plugin-markdown": "^0.3.0", "@lingui/cli": "^3.13.0", "@lingui/core": "^3.13.0", "@lingui/detect-locale": "^3.13.0", "@lingui/macro": "^3.13.0", - "@patternfly/patternfly": "^4.159.1", + "@patternfly/patternfly": "^4.164.2", "@polymer/iron-form": "^3.0.1", "@polymer/paper-input": "^3.2.1", "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-commonjs": "^21.0.1", - "@rollup/plugin-node-resolve": "^13.0.6", + "@rollup/plugin-node-resolve": "^13.1.1", "@rollup/plugin-replace": "^3.0.0", "@rollup/plugin-typescript": "^8.3.0", "@sentry/browser": "^6.16.1", @@ -72,8 +72,8 @@ "@types/chart.js": "^2.9.34", "@types/codemirror": "5.60.5", "@types/grecaptcha": "^3.0.3", - "@typescript-eslint/eslint-plugin": "^5.6.0", - "@typescript-eslint/parser": "^5.6.0", + "@typescript-eslint/eslint-plugin": "^5.7.0", + "@typescript-eslint/parser": "^5.7.0", "@webcomponents/webcomponentsjs": "^2.6.0", "babel-plugin-macros": "^3.1.0", "base64-js": "^1.5.1", @@ -99,7 +99,7 @@ "rollup-plugin-terser": "^7.0.2", "ts-lit-plugin": "^1.2.1", "tslib": "^2.3.1", - "typescript": "^4.5.3", + "typescript": "^4.5.4", "webcomponent-qr-code": "^1.0.5", "yaml": "^1.10.2" } diff --git a/web/src/api/Config.ts b/web/src/api/Config.ts index a8875d224f..01568ae6d2 100644 --- a/web/src/api/Config.ts +++ b/web/src/api/Config.ts @@ -3,6 +3,7 @@ import { getCookie } from "../utils"; import { APIMiddleware } from "../elements/notifications/APIDrawer"; import { MessageMiddleware } from "../elements/messages/Middleware"; import { VERSION } from "../constants"; +import { getMetaContent } from "@sentry/tracing/dist/browser/browsertracing"; export class LoggingMiddleware implements Middleware { @@ -53,6 +54,7 @@ export const DEFAULT_CONFIG = new Configuration({ basePath: process.env.AK_API_BASE_PATH + "/api/v3", headers: { "X-CSRFToken": getCookie("authentik_csrf"), + "sentry-trace": getMetaContent("sentry-trace") || "", }, middleware: [ new APIMiddleware(), diff --git a/web/src/api/Sentry.ts b/web/src/api/Sentry.ts index 210f54e409..8014b2e70d 100644 --- a/web/src/api/Sentry.ts +++ b/web/src/api/Sentry.ts @@ -27,7 +27,10 @@ export function configureSentry(canDoPpi: boolean = false): Promise { ], tracesSampleRate: config.errorReporting.tracesSampleRate, environment: config.errorReporting.environment, - beforeSend: async (event: Sentry.Event, hint: Sentry.EventHint): Promise => { + beforeSend: async (event: Sentry.Event, hint: Sentry.EventHint | undefined): Promise => { + if (!hint) { + return event; + } if (hint.originalException instanceof SentryIgnoredError) { return null; } @@ -40,8 +43,13 @@ export function configureSentry(canDoPpi: boolean = false): Promise { Sentry.setTag(TAG_SENTRY_CAPABILITIES, config.capabilities.join(",")); if (window.location.pathname.includes("if/")) { // Get the interface name from URL - const intf = window.location.pathname.replace(/.+if\/(.+)\//, "$1"); - Sentry.setTag(TAG_SENTRY_COMPONENT, `web/${intf}`); + const pathMatches = window.location.pathname.match(/.+if\/(\w+)\//); + let currentInterface = "unknown"; + if (pathMatches && pathMatches.length >= 2) { + currentInterface = pathMatches[1]; + } + Sentry.setTag(TAG_SENTRY_COMPONENT, `web/${currentInterface}`); + Sentry.configureScope((scope) => scope.setTransactionName(`authentik.web.if.${currentInterface}`)); } if (config.errorReporting.sendPii && canDoPpi) { me().then(user => { diff --git a/web/src/elements/PageHeader.ts b/web/src/elements/PageHeader.ts index 5b53d6ace9..17042ff613 100644 --- a/web/src/elements/PageHeader.ts +++ b/web/src/elements/PageHeader.ts @@ -108,10 +108,11 @@ export class PageHeader extends LitElement { renderIcon(): TemplateResult { if (this.icon) { - if (this.iconImage) { + if (this.iconImage && !this.icon.startsWith("fa://")) { return html` `; } - return html` `; + const icon = this.icon.replaceAll("fa://", "fa "); + return html` `; } return html``; } @@ -132,7 +133,10 @@ export class PageHeader extends LitElement {
-

${this.renderIcon()} ${this.header}

+

+ ${this.renderIcon()} + ${this.header} +

${this.description ? html`

${this.description}

` : html``}
diff --git a/web/src/elements/cards/AggregateCard.ts b/web/src/elements/cards/AggregateCard.ts index 147b8c76d4..ef7fb942a9 100644 --- a/web/src/elements/cards/AggregateCard.ts +++ b/web/src/elements/cards/AggregateCard.ts @@ -18,6 +18,9 @@ export class AggregateCard extends LitElement { @property() headerLink?: string; + @property({ type: Boolean }) + isCenter = true; + static get styles(): CSSResult[] { return [PFBase, PFCard, PFFlex, AKGlobal].concat([ css` @@ -59,7 +62,9 @@ export class AggregateCard extends LitElement { ${this.renderHeaderLink()} -
${this.renderInner()}
+
+ ${this.renderInner()} +
`; } } diff --git a/web/src/elements/charts/AdminModelPerDay.ts b/web/src/elements/charts/AdminModelPerDay.ts new file mode 100644 index 0000000000..547761e418 --- /dev/null +++ b/web/src/elements/charts/AdminModelPerDay.ts @@ -0,0 +1,52 @@ +import { ChartData, Tick } from "chart.js"; + +import { t } from "@lingui/macro"; + +import { customElement, property } from "lit/decorators.js"; + +import { Coordinate, EventActions, EventsApi } from "@goauthentik/api"; + +import { DEFAULT_CONFIG } from "../../api/Config"; +import { AKChart } from "./Chart"; + +@customElement("ak-charts-admin-model-per-day") +export class AdminModelPerDay extends AKChart { + @property() + action: EventActions = EventActions.ModelCreated; + + @property({ attribute: false }) + query?: { [key: string]: unknown } | undefined; + + apiRequest(): Promise { + return new EventsApi(DEFAULT_CONFIG).eventsEventsPerMonthList({ + action: this.action, + query: JSON.stringify(this.query || {}), + }); + } + + timeTickCallback(tickValue: string | number, index: number, ticks: Tick[]): string { + const valueStamp = ticks[index]; + const delta = Date.now() - valueStamp.value; + const ago = Math.round(delta / 1000 / 3600 / 24); + return t`${ago} days ago`; + } + + getChartData(data: Coordinate[]): ChartData { + return { + datasets: [ + { + label: t`Objects created`, + backgroundColor: "rgba(189, 229, 184, .5)", + spanGaps: true, + data: + data.map((cord) => { + return { + x: cord.xCord || 0, + y: cord.yCord || 0, + }; + }) || [], + }, + ], + }; + } +} diff --git a/web/src/elements/charts/Chart.ts b/web/src/elements/charts/Chart.ts index 687063b29f..348e4398d1 100644 --- a/web/src/elements/charts/Chart.ts +++ b/web/src/elements/charts/Chart.ts @@ -5,6 +5,8 @@ import { ArcElement, BarElement } from "chart.js"; import { LinearScale, TimeScale } from "chart.js"; import "chartjs-adapter-moment"; +import { t } from "@lingui/macro"; + import { CSSResult, LitElement, TemplateResult, css, html } from "lit"; import { property } from "lit/decorators.js"; @@ -114,6 +116,13 @@ export abstract class AKChart extends LitElement { ]; } + timeTickCallback(tickValue: string | number, index: number, ticks: Tick[]): string { + const valueStamp = ticks[index]; + const delta = Date.now() - valueStamp.value; + const ago = Math.round(delta / 1000 / 3600); + return t`${ago} hours ago`; + } + getOptions(): ChartOptions { return { maintainAspectRatio: false, @@ -122,15 +131,8 @@ export abstract class AKChart extends LitElement { type: "time", display: true, ticks: { - callback: function ( - tickValue: string | number, - index: number, - ticks: Tick[], - ): string { - const valueStamp = ticks[index]; - const delta = Date.now() - valueStamp.value; - const ago = Math.round(delta / 1000 / 3600); - return `${ago} Hours ago`; + callback: (tickValue: string | number, index: number, ticks: Tick[]) => { + return this.timeTickCallback(tickValue, index, ticks); }, autoSkip: true, maxTicksLimit: 8, diff --git a/web/src/elements/forms/DeleteBulkForm.ts b/web/src/elements/forms/DeleteBulkForm.ts index 1222ecbf36..e8d6deb7d4 100644 --- a/web/src/elements/forms/DeleteBulkForm.ts +++ b/web/src/elements/forms/DeleteBulkForm.ts @@ -187,6 +187,7 @@ export class DeleteBulkForm extends ModalButton {

${t`Are you sure you want to delete ${this.objects.length} ${this.objectLabel}?`}

+
diff --git a/web/src/elements/notifications/APIDrawer.ts b/web/src/elements/notifications/APIDrawer.ts index 4bbe047c9d..e601de427c 100644 --- a/web/src/elements/notifications/APIDrawer.ts +++ b/web/src/elements/notifications/APIDrawer.ts @@ -102,6 +102,7 @@ export class APIDrawer extends LitElement {

${t`API Requests`}

+ ${t`Open API Browser`}
diff --git a/web/src/elements/router/RouterOutlet.ts b/web/src/elements/router/RouterOutlet.ts index 6a7bc852aa..9329887ecd 100644 --- a/web/src/elements/router/RouterOutlet.ts +++ b/web/src/elements/router/RouterOutlet.ts @@ -30,6 +30,19 @@ window.addEventListener("load", () => { })(); }); +export function paramURL(url: string, params?: { [key: string]: unknown }): string { + let finalUrl = "#"; + finalUrl += url; + if (params) { + finalUrl += ";"; + finalUrl += encodeURIComponent(JSON.stringify(params)); + } + return finalUrl; +} +export function navigate(url: string, params?: { [key: string]: unknown }): void { + window.location.assign(paramURL(url, params)); +} + @customElement("ak-router-outlet") export class RouterOutlet extends LitElement { @property({ attribute: false }) diff --git a/web/src/flows/FlowExecutor.ts b/web/src/flows/FlowExecutor.ts index 47cf78973d..1687eb4859 100644 --- a/web/src/flows/FlowExecutor.ts +++ b/web/src/flows/FlowExecutor.ts @@ -32,6 +32,7 @@ import "../elements/LoadingOverlay"; import { first } from "../utils"; import "./FlowInspector"; import "./access_denied/FlowAccessDenied"; +import "./sources/apple/AppleLoginInit"; import "./sources/plex/PlexLoginInit"; import "./stages/RedirectStage"; import "./stages/authenticator_duo/AuthenticatorDuoStage"; @@ -321,6 +322,11 @@ export class FlowExecutor extends LitElement implements StageHost { .host=${this as StageHost} .challenge=${this.challenge} >`; + case "ak-flow-sources-oauth-apple": + return html``; default: break; } diff --git a/web/src/flows/sources/apple/AppleLoginInit.ts b/web/src/flows/sources/apple/AppleLoginInit.ts new file mode 100644 index 0000000000..3fa505cafe --- /dev/null +++ b/web/src/flows/sources/apple/AppleLoginInit.ts @@ -0,0 +1,79 @@ +import { t } from "@lingui/macro"; + +import { CSSResult, TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import AKGlobal from "../../../authentik.css"; +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFForm from "@patternfly/patternfly/components/Form/form.css"; +import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; +import PFLogin from "@patternfly/patternfly/components/Login/login.css"; +import PFTitle from "@patternfly/patternfly/components/Title/title.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { AppleChallengeResponseRequest, AppleLoginChallenge } from "@goauthentik/api"; + +import "../../../elements/EmptyState"; +import { BaseStage } from "../../stages/base"; + +@customElement("ak-flow-sources-oauth-apple") +export class AppleLoginInit extends BaseStage { + @property({ type: Boolean }) + isModalShown = false; + + static get styles(): CSSResult[] { + return [PFBase, PFLogin, PFForm, PFFormControl, PFButton, PFTitle, AKGlobal]; + } + + firstUpdated(): void { + const appleAuth = document.createElement("script"); + appleAuth.src = + "https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"; + appleAuth.type = "text/javascript"; + appleAuth.onload = () => { + AppleID.auth.init({ + clientId: this.challenge?.clientId, + scope: this.challenge.scope, + redirectURI: this.challenge.redirectUri, + state: this.challenge.state, + usePopup: false, + }); + AppleID.auth.signIn(); + this.isModalShown = true; + }; + document.head.append(appleAuth); + //Listen for authorization success + document.addEventListener("AppleIDSignInOnSuccess", () => { + //handle successful response + }); + //Listen for authorization failures + document.addEventListener("AppleIDSignInOnFailure", (error) => { + console.warn(error); + this.isModalShown = false; + }); + } + + render(): TemplateResult { + return html` + +
+ +
`; + } +} diff --git a/web/src/flows/sources/apple/apple.d.ts b/web/src/flows/sources/apple/apple.d.ts new file mode 100644 index 0000000000..c547d88d0e --- /dev/null +++ b/web/src/flows/sources/apple/apple.d.ts @@ -0,0 +1,14 @@ +declare namespace AppleID { + const auth: AppleIDAuth; + + class AppleIDAuth { + init({ + clientId: string, + scope: string, + redirectURI: string, + state: string, + usePopup: boolean, + }): void; + async signIn(): Promise; + } +} diff --git a/web/src/flows/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts b/web/src/flows/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts index 64d23b0ef8..6ffe9b755b 100644 --- a/web/src/flows/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts +++ b/web/src/flows/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts @@ -51,6 +51,7 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage< // byte arrays as expected by the spec. const publicKeyCredentialCreateOptions = transformCredentialCreateOptions( this.challenge?.registration as PublicKeyCredentialCreationOptions, + this.challenge?.registration.user.id, ); // request the authenticator(s) to create a new credential keypair. diff --git a/web/src/flows/stages/authenticator_webauthn/utils.ts b/web/src/flows/stages/authenticator_webauthn/utils.ts index 77be2556e1..01b1f05f63 100644 --- a/web/src/flows/stages/authenticator_webauthn/utils.ts +++ b/web/src/flows/stages/authenticator_webauthn/utils.ts @@ -8,15 +8,26 @@ export function b64RawEnc(buf: Uint8Array): string { return base64js.fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_"); } +export function u8arr(input: string): Uint8Array { + return Uint8Array.from(atob(input.replace(/_/g, "/").replace(/-/g, "+")), (c) => + c.charCodeAt(0), + ); +} + /** * Transforms items in the credentialCreateOptions generated on the server * into byte arrays expected by the navigator.credentials.create() call */ export function transformCredentialCreateOptions( credentialCreateOptions: PublicKeyCredentialCreationOptions, + userId: string, ): PublicKeyCredentialCreationOptions { const user = credentialCreateOptions.user; - user.id = u8arr(b64enc(credentialCreateOptions.user.id as Uint8Array)); + // Because json can't contain raw bytes, the server base64-encodes the User ID + // So to get the base64 encoded byte array, we first need to convert it to a regular + // string, then a byte array, re-encode it and wrap that in an array. + const stringId = decodeURIComponent(escape(window.atob(userId))); + user.id = u8arr(b64enc(u8arr(stringId))); const challenge = u8arr(credentialCreateOptions.challenge.toString()); const transformedCredentialCreateOptions = Object.assign({}, credentialCreateOptions, { @@ -63,12 +74,6 @@ export function transformNewAssertionForServer(newAssertion: PublicKeyCredential }; } -function u8arr(input: string): Uint8Array { - return Uint8Array.from(atob(input.replace(/_/g, "/").replace(/-/g, "+")), (c) => - c.charCodeAt(0), - ); -} - export function transformCredentialRequestOptions( credentialRequestOptions: PublicKeyCredentialRequestOptions, ): PublicKeyCredentialRequestOptions { diff --git a/web/src/interfaces/AdminInterface.ts b/web/src/interfaces/AdminInterface.ts index bfffc130f1..4f977b44fd 100644 --- a/web/src/interfaces/AdminInterface.ts +++ b/web/src/interfaces/AdminInterface.ts @@ -189,43 +189,37 @@ export class AdminInterface extends LitElement { ${t`User interface`} - - ${t`Overview`} - - - ${t`System Tasks`} + + ${t`Dashboards`} + + ${t`Overview`} + + + ${t`Users`} + + + ${t`System Tasks`} + - ${t`Resources`} + ${t`Applications`} ${SLUG_REGEX})$`]} > ${t`Applications`} - ${SLUG_REGEX})$`]} - > - ${t`Sources`} - ${ID_REGEX})$`]} > ${t`Providers`} - - ${t`Tenants`} - - - - ${t`Outposts`} ${t`Outposts`} - ${t`Integrations`} + ${t`Outpost Integrations`} @@ -272,12 +266,9 @@ export class AdminInterface extends LitElement { ${t`Prompts`} - - ${t`Invitations`} - - ${t`Identity & Cryptography`} + ${t`Directory`} ${ID_REGEX})$`]} @@ -287,12 +278,27 @@ export class AdminInterface extends LitElement { ${t`Groups`} - - ${t`Certificates`} + ${SLUG_REGEX})$`]} + > + ${t`Federation & Social login`} ${t`Tokens & App passwords`} + + ${t`Invitations`} + + + + ${t`System`} + + ${t`Tenants`} + + + ${t`Certificates`} + `; } diff --git a/web/src/locales/en.po b/web/src/locales/en.po index 215ed92d7d..7ef86c5317 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -296,6 +296,10 @@ msgstr "Alternatively, if your current device has Duo installed, click on this l msgid "Always require consent" msgstr "Always require consent" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "An example setup can look like this:" +msgstr "An example setup can look like this:" + #: src/pages/stages/prompt/PromptForm.ts msgid "Any HTML can be used." msgstr "Any HTML can be used." @@ -344,6 +348,7 @@ msgstr "Application's display Name." msgid "Application(s)" msgstr "Application(s)" +#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/applications/ApplicationListPage.ts #: src/pages/outposts/OutpostForm.ts @@ -407,8 +412,12 @@ msgid "Assigned to application" msgstr "Assigned to application" #: src/pages/policies/PolicyListPage.ts -msgid "Assigned to {0} objects." -msgstr "Assigned to {0} objects." +msgid "Assigned to {0} object(s)." +msgstr "Assigned to {0} object(s)." + +#: src/pages/policies/PolicyListPage.ts +#~ msgid "Assigned to {0} objects." +#~ msgstr "Assigned to {0} objects." #: src/pages/events/EventInfo.ts msgid "Attempted to log in as {0}" @@ -433,6 +442,10 @@ msgstr "Audience" #~ msgid "Auth Type" #~ msgstr "Auth Type" +#: src/flows/sources/apple/AppleLoginInit.ts +msgid "Authenticating with Apple..." +msgstr "Authenticating with Apple..." + #: src/flows/sources/plex/PlexLoginInit.ts msgid "Authenticating with Plex..." msgstr "Authenticating with Plex..." @@ -445,6 +458,10 @@ msgstr "Authentication" msgid "Authentication Type" msgstr "Authentication Type" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "Authentication URL" +msgstr "Authentication URL" + #: src/pages/sources/oauth/OAuthSourceForm.ts #: src/pages/sources/plex/PlexSourceForm.ts #: src/pages/sources/saml/SAMLSourceForm.ts @@ -760,6 +777,10 @@ msgstr "Check status" msgid "Check the IP of the Kubernetes service, or" msgstr "Check the IP of the Kubernetes service, or" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Check the logs" +msgstr "Check the logs" + #: #~ msgid "Check your Emails for a password reset link." #~ msgstr "Check your Emails for a password reset link." @@ -1200,6 +1221,10 @@ msgstr "Create Token" msgid "Create User" msgstr "Create User" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Create a new application" +msgstr "Create a new application" + #: src/pages/users/ServiceAccountForm.ts msgid "Create group" msgstr "Create group" @@ -1260,6 +1285,10 @@ msgstr "Customisation" msgid "DSA-SHA1" msgstr "DSA-SHA1" +#: src/interfaces/AdminInterface.ts +msgid "Dashboards" +msgstr "Dashboards" + #: src/pages/stages/prompt/PromptForm.ts msgid "Date" msgstr "Date" @@ -1449,6 +1478,10 @@ msgstr "Digits" msgid "Direct querying, always returns the latest data, but slower than cached querying." msgstr "Direct querying, always returns the latest data, but slower than cached querying." +#: src/interfaces/AdminInterface.ts +msgid "Directory" +msgstr "Directory" + #: #: #~ msgid "Disable" @@ -1818,6 +1851,10 @@ msgstr "Expiry date" msgid "Explicit Consent" msgstr "Explicit Consent" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Explore integrations" +msgstr "Explore integrations" + #: src/pages/flows/FlowViewPage.ts msgid "Export" msgstr "Export" @@ -1855,7 +1892,6 @@ msgstr "External Applications which use authentik as Identity-Provider, utilizin msgid "External Host" msgstr "External Host" -#: src/pages/providers/proxy/ProxyProviderForm.ts #: src/pages/providers/proxy/ProxyProviderForm.ts #: src/pages/providers/proxy/ProxyProviderForm.ts msgid "External host" @@ -1866,6 +1902,10 @@ msgstr "External host" msgid "Failed Logins" msgstr "Failed Logins" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Failed Logins per day in the last month" +msgstr "Failed Logins per day in the last month" + #: src/pages/stages/password/PasswordStageForm.ts msgid "Failed attempts before cancel" msgstr "Failed attempts before cancel" @@ -1899,6 +1939,11 @@ msgstr "Failed to update {0}: {1}" msgid "Favicon" msgstr "Favicon" +#: src/interfaces/AdminInterface.ts +#: src/pages/sources/SourcesListPage.ts +msgid "Federation & Social login" +msgstr "Federation & Social login" + #: src/pages/stages/prompt/PromptListPage.ts msgid "Field" msgstr "Field" @@ -1944,6 +1989,10 @@ msgstr "Flow" msgid "Flow Overview" msgstr "Flow Overview" +#: src/pages/events/utils.ts +msgid "Flow execution" +msgstr "Flow execution" + #: src/flows/FlowInspector.ts #: src/flows/FlowInspector.ts msgid "Flow inspector" @@ -2270,8 +2319,8 @@ msgid "Identifier" msgstr "Identifier" #: src/interfaces/AdminInterface.ts -msgid "Identity & Cryptography" -msgstr "Identity & Cryptography" +#~ msgid "Identity & Cryptography" +#~ msgstr "Identity & Cryptography" #: src/pages/outposts/ServiceConnectionDockerForm.ts #: src/pages/outposts/ServiceConnectionKubernetesForm.ts @@ -2344,6 +2393,10 @@ msgstr "Import certificates of external providers or create certificates to sign msgid "In case you can't access any other method." msgstr "In case you can't access any other method." +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com." +msgstr "In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com." + #: src/pages/users/UserListPage.ts msgid "Inactive" msgstr "Inactive" @@ -2366,8 +2419,8 @@ msgid "Integration key" msgstr "Integration key" #: src/interfaces/AdminInterface.ts -msgid "Integrations" -msgstr "Integrations" +#~ msgid "Integrations" +#~ msgstr "Integrations" #: src/pages/tokens/TokenForm.ts #: src/pages/tokens/TokenListPage.ts @@ -2689,6 +2742,10 @@ msgstr "Logins" msgid "Logins over the last 24 hours" msgstr "Logins over the last 24 hours" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Logins per day in the last month" +msgstr "Logins per day in the last month" + #: src/pages/tenants/TenantForm.ts msgid "Logo" msgstr "Logo" @@ -2996,6 +3053,10 @@ msgstr "No Stages bound" msgid "No additional data available." msgstr "No additional data available." +#: src/pages/providers/proxy/ProxyProviderViewPage.ts +msgid "No additional setup is required." +msgstr "No additional setup is required." + #: src/elements/forms/ModalForm.ts msgid "No form found" msgstr "No form found" @@ -3143,6 +3204,10 @@ msgstr "Object field" msgid "Object uniqueness field" msgstr "Object uniqueness field" +#: src/elements/charts/AdminModelPerDay.ts +msgid "Objects created" +msgstr "Objects created" + #: src/pages/stages/consent/ConsentStageForm.ts msgid "Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." msgstr "Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." @@ -3161,6 +3226,10 @@ msgstr "Only fail the policy, don't invalidate user's password." msgid "Only send notification once, for example when sending a webhook into a chat channel." msgstr "Only send notification once, for example when sending a webhook into a chat channel." +#: src/elements/notifications/APIDrawer.ts +msgid "Open API Browser" +msgstr "Open API Browser" + #: #~ msgid "Open application" #~ msgstr "Open application" @@ -3210,8 +3279,8 @@ msgid "Optionally set the 'FriendlyName' value of the Assertion attribute." msgstr "Optionally set the 'FriendlyName' value of the Assertion attribute." #: src/pages/providers/proxy/ProxyProviderForm.ts -msgid "Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." -msgstr "Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." +#~ msgid "Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." +#~ msgstr "Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." #: src/pages/flows/BoundStagesList.ts #: src/pages/flows/StageBindingForm.ts @@ -3239,6 +3308,10 @@ msgstr "Outdated outposts" msgid "Outpost Deployment Info" msgstr "Outpost Deployment Info" +#: src/interfaces/AdminInterface.ts +msgid "Outpost Integrations" +msgstr "Outpost Integrations" + #: #~ msgid "Outpost Service-connection" #~ msgstr "Outpost Service-connection" @@ -3259,7 +3332,6 @@ msgstr "Outpost status" msgid "Outpost(s)" msgstr "Outpost(s)" -#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/outposts/OutpostListPage.ts msgid "Outposts" @@ -3365,7 +3437,6 @@ msgid "Please enter your password" msgstr "Please enter your password" #: src/interfaces/AdminInterface.ts -#: src/pages/admin-overview/AdminOverviewPage.ts #: src/pages/flows/FlowListPage.ts #: src/pages/policies/PolicyListPage.ts msgid "Policies" @@ -3584,6 +3655,10 @@ msgstr "Public key, acquired from https://www.google.com/recaptcha/intro/v3.html msgid "Publisher" msgstr "Publisher" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Quick actions" +msgstr "Quick actions" + #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning, while keeping the flow context." msgstr "RESTART restarts the flow from the beginning, while keeping the flow context." @@ -3761,14 +3836,18 @@ msgid "Reset Password" msgstr "Reset Password" #: src/interfaces/AdminInterface.ts -msgid "Resources" -msgstr "Resources" +#~ msgid "Resources" +#~ msgstr "Resources" #: src/pages/events/EventInfo.ts #: src/pages/property-mappings/PropertyMappingTestForm.ts msgid "Result" msgstr "Result" +#: src/flows/sources/apple/AppleLoginInit.ts +msgid "Retry" +msgstr "Retry" + #: #~ msgid "Retry Task" #~ msgstr "Retry Task" @@ -4109,6 +4188,10 @@ msgstr "Set a custom HTTP-Basic Authentication header based on values from authe msgid "Set custom attributes using YAML or JSON." msgstr "Set custom attributes using YAML or JSON." +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." +msgstr "Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." + #: src/pages/providers/proxy/ProxyProviderViewPage.ts msgid "Setup" msgstr "Setup" @@ -4206,8 +4289,6 @@ msgstr "Source {0}" msgid "Source(s)" msgstr "Source(s)" -#: src/interfaces/AdminInterface.ts -#: src/pages/sources/SourcesListPage.ts #: src/pages/stages/identification/IdentificationStageForm.ts msgid "Sources" msgstr "Sources" @@ -4298,6 +4379,7 @@ msgstr "Stage(s)" #: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts #: src/pages/stages/captcha/CaptchaStageForm.ts #: src/pages/stages/consent/ConsentStageForm.ts #: src/pages/stages/email/EmailStageForm.ts @@ -4734,9 +4816,13 @@ msgstr "Sync status" msgid "Sync users" msgstr "Sync users" +#: src/interfaces/AdminInterface.ts +msgid "System" +msgstr "System" + #: src/pages/admin-overview/AdminOverviewPage.ts -msgid "System Overview" -msgstr "System Overview" +#~ msgid "System Overview" +#~ msgstr "System Overview" #: src/interfaces/AdminInterface.ts #: src/pages/system-tasks/SystemTaskListPage.ts @@ -4845,8 +4931,12 @@ msgid "The external URL you'll access the application at. Include any non-standa msgstr "The external URL you'll access the application at. Include any non-standard port." #: src/pages/providers/proxy/ProxyProviderForm.ts -msgid "The external URL you'll authenticate at. Can be the same domain as authentik." -msgstr "The external URL you'll authenticate at. Can be the same domain as authentik." +#~ msgid "The external URL you'll authenticate at. Can be the same domain as authentik." +#~ msgstr "The external URL you'll authenticate at. Can be the same domain as authentik." + +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "The external URL you'll authenticate at. The authentik core server should be reachable under this URL." +msgstr "The external URL you'll authenticate at. The authentik core server should be reachable under this URL." #: #~ msgid "The following objects use {0}:" @@ -5115,6 +5205,7 @@ msgid "UI settings" msgstr "UI settings" #: src/pages/events/EventInfo.ts +#: src/pages/users/UserListPage.ts msgid "UID" msgstr "UID" @@ -5467,6 +5558,10 @@ msgstr "User interface" msgid "User matching mode" msgstr "User matching mode" +#: src/pages/admin-overview/UserDashboardPage.ts +#~ msgid "User metrics" +#~ msgstr "User metrics" + #: src/pages/sources/ldap/LDAPSourceForm.ts msgid "User object filter" msgstr "User object filter" @@ -5475,10 +5570,30 @@ msgstr "User object filter" msgid "User password writeback" msgstr "User password writeback" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "User statistics" +msgstr "User statistics" + #: src/pages/users/UserListPage.ts msgid "User status" msgstr "User status" +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification" +msgstr "User verification" + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification is preferred if available, but not required." +msgstr "User verification is preferred if available, but not required." + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification must occur." +msgstr "User verification must occur." + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification should not occur." +msgstr "User verification should not occur." + #: src/pages/events/utils.ts msgid "User was written to" msgstr "User was written to" @@ -5529,6 +5644,7 @@ msgstr "Username" msgid "Username: Same as Text input, but checks for and prevents duplicate usernames." msgstr "Username: Same as Text input, but checks for and prevents duplicate usernames." +#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/admin-overview/AdminOverviewPage.ts #: src/pages/users/UserListPage.ts @@ -5539,6 +5655,10 @@ msgstr "Users" msgid "Users added to this group will be superusers." msgstr "Users added to this group will be superusers." +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Users created per day in the last month" +msgstr "Users created per day in the last month" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed." msgstr "Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed." @@ -5651,6 +5771,10 @@ msgstr "Warning: Provider is not used by any Outpost." msgid "Warning: Provider not assigned to any application." msgstr "Warning: Provider not assigned to any application." +#: src/pages/users/UserListPage.ts +msgid "Warning: You're about to delete the user you're logged in as ({0}). Proceed at your own risk." +msgstr "Warning: You're about to delete the user you're logged in as ({0}). Proceed at your own risk." + #: src/pages/outposts/OutpostListPage.ts msgid "Warning: authentik Domain is not configured, authentication will not work." msgstr "Warning: authentik Domain is not configured, authentication will not work." @@ -5679,6 +5803,10 @@ msgstr "Webhook Mapping" msgid "Webhook URL" msgstr "Webhook URL" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Welcome, {name}." +msgstr "Welcome, {name}." + #: src/pages/stages/email/EmailStageForm.ts msgid "When a user returns from the email successfully, their account will be activated." msgstr "When a user returns from the email successfully, their account will be activated." @@ -5782,6 +5910,10 @@ msgstr "You're about to be redirect to the following URL." msgid "You're currently impersonating {0}. Click to stop." msgstr "You're currently impersonating {0}. Click to stop." +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "app1 running on app1.example.com" +msgstr "app1 running on app1.example.com" + #: #~ msgid "authentik Builtin Database" #~ msgstr "authentik Builtin Database" @@ -5790,6 +5922,10 @@ msgstr "You're currently impersonating {0}. Click to stop." #~ msgid "authentik LDAP Backend" #~ msgstr "authentik LDAP Backend" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "authentik running on auth.example.com" +msgstr "authentik running on auth.example.com" + #: src/elements/forms/DeleteForm.ts msgid "connecting object will be deleted" msgstr "connecting object will be deleted" @@ -5858,3 +5994,11 @@ msgstr "{0}, should be {1}" #: src/elements/forms/ConfirmationForm.ts msgid "{0}: {1}" msgstr "{0}: {1}" + +#: src/elements/charts/AdminModelPerDay.ts +msgid "{ago} days ago" +msgstr "{ago} days ago" + +#: src/elements/charts/Chart.ts +msgid "{ago} hours ago" +msgstr "{ago} hours ago" diff --git a/web/src/locales/fr_FR.po b/web/src/locales/fr_FR.po index cb2d9a9c98..7838b5efb7 100644 --- a/web/src/locales/fr_FR.po +++ b/web/src/locales/fr_FR.po @@ -300,6 +300,10 @@ msgstr "Sinon, si Duo est installé sur cet appareil, cliquez sur ce lien :" msgid "Always require consent" msgstr "Toujours exiger l'approbation" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "An example setup can look like this:" +msgstr "" + #: src/pages/stages/prompt/PromptForm.ts msgid "Any HTML can be used." msgstr "" @@ -348,6 +352,7 @@ msgstr "Nom d'affichage de l'application" msgid "Application(s)" msgstr "Application(s)" +#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/applications/ApplicationListPage.ts #: src/pages/outposts/OutpostForm.ts @@ -411,8 +416,12 @@ msgid "Assigned to application" msgstr "Assigné à l'application" #: src/pages/policies/PolicyListPage.ts -msgid "Assigned to {0} objects." -msgstr "Assigné à {0} objets" +msgid "Assigned to {0} object(s)." +msgstr "" + +#: src/pages/policies/PolicyListPage.ts +#~ msgid "Assigned to {0} objects." +#~ msgstr "Assigné à {0} objets" #: src/pages/events/EventInfo.ts msgid "Attempted to log in as {0}" @@ -437,6 +446,10 @@ msgstr "Audience" #~ msgid "Auth Type" #~ msgstr "" +#: src/flows/sources/apple/AppleLoginInit.ts +msgid "Authenticating with Apple..." +msgstr "" + #: src/flows/sources/plex/PlexLoginInit.ts msgid "Authenticating with Plex..." msgstr "Authentification avec Plex..." @@ -449,6 +462,10 @@ msgstr "Authentification" msgid "Authentication Type" msgstr "" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "Authentication URL" +msgstr "" + #: src/pages/sources/oauth/OAuthSourceForm.ts #: src/pages/sources/plex/PlexSourceForm.ts #: src/pages/sources/saml/SAMLSourceForm.ts @@ -761,6 +778,10 @@ msgstr "Vérifier le statut" msgid "Check the IP of the Kubernetes service, or" msgstr "" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Check the logs" +msgstr "" + #: #~ msgid "Check your Emails for a password reset link." #~ msgstr "Vérifiez vos courriels pour un lien de récupération de mot de passe." @@ -1198,6 +1219,10 @@ msgstr "Créer un jeton" msgid "Create User" msgstr "Créer un utilisateu" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Create a new application" +msgstr "" + #: src/pages/users/ServiceAccountForm.ts msgid "Create group" msgstr "Créer un groupe" @@ -1258,6 +1283,10 @@ msgstr "Personalisation" msgid "DSA-SHA1" msgstr "DSA-SHA1" +#: src/interfaces/AdminInterface.ts +msgid "Dashboards" +msgstr "" + #: src/pages/stages/prompt/PromptForm.ts msgid "Date" msgstr "Date" @@ -1439,6 +1468,10 @@ msgstr "Chiffres" msgid "Direct querying, always returns the latest data, but slower than cached querying." msgstr "" +#: src/interfaces/AdminInterface.ts +msgid "Directory" +msgstr "" + #~ msgid "Disable" #~ msgstr "Désactiver" @@ -1804,6 +1837,10 @@ msgstr "Date d'expiration" msgid "Explicit Consent" msgstr "Approbation explicite" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Explore integrations" +msgstr "" + #: src/pages/flows/FlowViewPage.ts msgid "Export" msgstr "Exporter" @@ -1841,7 +1878,6 @@ msgstr "Applications externes qui utilisent authentik comme fournisseur d'identi msgid "External Host" msgstr "Hôte externe" -#: src/pages/providers/proxy/ProxyProviderForm.ts #: src/pages/providers/proxy/ProxyProviderForm.ts #: src/pages/providers/proxy/ProxyProviderForm.ts msgid "External host" @@ -1852,6 +1888,10 @@ msgstr "Hôte externe" msgid "Failed Logins" msgstr "Connexions échouées" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Failed Logins per day in the last month" +msgstr "" + #: src/pages/stages/password/PasswordStageForm.ts msgid "Failed attempts before cancel" msgstr "Échecs avant annulation" @@ -1885,6 +1925,11 @@ msgstr "Impossible de mettre à jour {0} : {1}" msgid "Favicon" msgstr "Favicon" +#: src/interfaces/AdminInterface.ts +#: src/pages/sources/SourcesListPage.ts +msgid "Federation & Social login" +msgstr "" + #: src/pages/stages/prompt/PromptListPage.ts msgid "Field" msgstr "Champ" @@ -1929,6 +1974,10 @@ msgstr "Flux" msgid "Flow Overview" msgstr "Aperçu du flux" +#: src/pages/events/utils.ts +msgid "Flow execution" +msgstr "" + #: src/flows/FlowInspector.ts #: src/flows/FlowInspector.ts msgid "Flow inspector" @@ -2253,8 +2302,8 @@ msgid "Identifier" msgstr "Identifiant" #: src/interfaces/AdminInterface.ts -msgid "Identity & Cryptography" -msgstr "Identité et chiffrement" +#~ msgid "Identity & Cryptography" +#~ msgstr "Identité et chiffrement" #: src/pages/outposts/ServiceConnectionDockerForm.ts #: src/pages/outposts/ServiceConnectionKubernetesForm.ts @@ -2327,6 +2376,10 @@ msgstr "Importer les certificats des fournisseurs externes ou créer des certifi msgid "In case you can't access any other method." msgstr "Au cas où aucune autre méthode ne soit disponible." +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com." +msgstr "" + #: src/pages/users/UserListPage.ts msgid "Inactive" msgstr "Inactif" @@ -2349,8 +2402,8 @@ msgid "Integration key" msgstr "Clé d'intégration" #: src/interfaces/AdminInterface.ts -msgid "Integrations" -msgstr "Intégrations" +#~ msgid "Integrations" +#~ msgstr "Intégrations" #: src/pages/tokens/TokenForm.ts #: src/pages/tokens/TokenListPage.ts @@ -2668,6 +2721,10 @@ msgstr "Connexions" msgid "Logins over the last 24 hours" msgstr "Connexions ces dernières 24 heures" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Logins per day in the last month" +msgstr "" + #: src/pages/tenants/TenantForm.ts msgid "Logo" msgstr "Logo" @@ -2974,6 +3031,10 @@ msgstr "Aucune étape liée" msgid "No additional data available." msgstr "Aucune donnée additionnelle disponible." +#: src/pages/providers/proxy/ProxyProviderViewPage.ts +msgid "No additional setup is required." +msgstr "" + #: src/elements/forms/ModalForm.ts msgid "No form found" msgstr "Aucun formulaire trouvé" @@ -3119,6 +3180,10 @@ msgstr "Champ d'objet" msgid "Object uniqueness field" msgstr "Champ d'unicité de l'objet" +#: src/elements/charts/AdminModelPerDay.ts +msgid "Objects created" +msgstr "" + #: src/pages/stages/consent/ConsentStageForm.ts msgid "Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." msgstr "Durée d'expiration du consentement (Format : hours=1;minutes=2;seconds=3)." @@ -3137,6 +3202,10 @@ msgstr "Faire simplement échouer la politique sans invalider le mot de passe ut msgid "Only send notification once, for example when sending a webhook into a chat channel." msgstr "Envoyer une seule fois la notification, par exemple lors de l'envoi d'un webhook dans un canal de discussion." +#: src/elements/notifications/APIDrawer.ts +msgid "Open API Browser" +msgstr "" + #~ msgid "Open application" #~ msgstr "Ouvrir l'appication" @@ -3185,8 +3254,8 @@ msgid "Optionally set the 'FriendlyName' value of the Assertion attribute." msgstr "Indiquer la valeur \"FriendlyName\" de l'attribut d'assertion (optionnel)" #: src/pages/providers/proxy/ProxyProviderForm.ts -msgid "Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." -msgstr "Indiquer votre domaine parent (optionnel), si vous souhaitez que l'authentification et l'autorisation soient réalisés au niveau du domaine. Si vous exécutez des applications sur app1.domain.tld, app2.domain.tld, indiquez ici \"domain.tld\"." +#~ msgid "Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." +#~ msgstr "Indiquer votre domaine parent (optionnel), si vous souhaitez que l'authentification et l'autorisation soient réalisés au niveau du domaine. Si vous exécutez des applications sur app1.domain.tld, app2.domain.tld, indiquez ici \"domain.tld\"." #: src/pages/flows/BoundStagesList.ts #: src/pages/flows/StageBindingForm.ts @@ -3213,6 +3282,10 @@ msgstr "Avant-postes périmés" msgid "Outpost Deployment Info" msgstr "Info de déploiement de l'avant-poste" +#: src/interfaces/AdminInterface.ts +msgid "Outpost Integrations" +msgstr "" + #~ msgid "Outpost Service-connection" #~ msgstr "Connexion de service de l'avant-poste" @@ -3231,7 +3304,6 @@ msgstr "Statut de l'avant-poste" msgid "Outpost(s)" msgstr "Avant-poste(s)" -#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/outposts/OutpostListPage.ts msgid "Outposts" @@ -3337,7 +3409,6 @@ msgid "Please enter your password" msgstr "Veuillez saisir votre mot de passe" #: src/interfaces/AdminInterface.ts -#: src/pages/admin-overview/AdminOverviewPage.ts #: src/pages/flows/FlowListPage.ts #: src/pages/policies/PolicyListPage.ts msgid "Policies" @@ -3552,6 +3623,10 @@ msgstr "Clé publique, obtenue depuis https://www.google.com/recaptcha/intro/v3. msgid "Publisher" msgstr "Éditeur" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Quick actions" +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning, while keeping the flow context." msgstr "REDÉMARRER redémarre le flux depuis le début, en gardant le contexte du flux." @@ -3732,14 +3807,18 @@ msgid "Reset Password" msgstr "Réinitialiser le mot de passe" #: src/interfaces/AdminInterface.ts -msgid "Resources" -msgstr "Ressources" +#~ msgid "Resources" +#~ msgstr "Ressources" #: src/pages/events/EventInfo.ts #: src/pages/property-mappings/PropertyMappingTestForm.ts msgid "Result" msgstr "Résultat" +#: src/flows/sources/apple/AppleLoginInit.ts +msgid "Retry" +msgstr "" + #~ msgid "Retry Task" #~ msgstr "Réessayer la tâche" @@ -4072,6 +4151,10 @@ msgstr "Définir un en-tête d'authentification HTTP-Basic personnalisé basé s msgid "Set custom attributes using YAML or JSON." msgstr "Définissez des attributs personnalisés via YAML ou JSON." +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." +msgstr "" + #: src/pages/providers/proxy/ProxyProviderViewPage.ts msgid "Setup" msgstr "" @@ -4168,8 +4251,6 @@ msgstr "Source {0}" msgid "Source(s)" msgstr "Source(s)" -#: src/interfaces/AdminInterface.ts -#: src/pages/sources/SourcesListPage.ts #: src/pages/stages/identification/IdentificationStageForm.ts msgid "Sources" msgstr "Sources" @@ -4258,6 +4339,7 @@ msgstr "Étape(s)" #: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts #: src/pages/stages/captcha/CaptchaStageForm.ts #: src/pages/stages/consent/ConsentStageForm.ts #: src/pages/stages/email/EmailStageForm.ts @@ -4689,9 +4771,13 @@ msgstr "Synchroniser les statuts" msgid "Sync users" msgstr "Synchroniser les utilisateurs" +#: src/interfaces/AdminInterface.ts +msgid "System" +msgstr "" + #: src/pages/admin-overview/AdminOverviewPage.ts -msgid "System Overview" -msgstr "Vue d'ensemble du système" +#~ msgid "System Overview" +#~ msgstr "Vue d'ensemble du système" #: src/interfaces/AdminInterface.ts #: src/pages/system-tasks/SystemTaskListPage.ts @@ -4799,8 +4885,12 @@ msgid "The external URL you'll access the application at. Include any non-standa msgstr "L'URL externe par laquelle vous accéderez à l'application. Incluez un port non-standard si besoin." #: src/pages/providers/proxy/ProxyProviderForm.ts -msgid "The external URL you'll authenticate at. Can be the same domain as authentik." -msgstr "L'URL externe sur laquelle vous vous authentifierez. Cela peut être le même domaine qu'authentik." +#~ msgid "The external URL you'll authenticate at. Can be the same domain as authentik." +#~ msgstr "L'URL externe sur laquelle vous vous authentifierez. Cela peut être le même domaine qu'authentik." + +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "The external URL you'll authenticate at. The authentik core server should be reachable under this URL." +msgstr "" #~ msgid "The following objects use {0}:" #~ msgstr "Les objets suivants utilisent {0} :" @@ -5056,6 +5146,7 @@ msgid "UI settings" msgstr "Paramètres d'UI" #: src/pages/events/EventInfo.ts +#: src/pages/users/UserListPage.ts msgid "UID" msgstr "UID" @@ -5405,6 +5496,10 @@ msgstr "Interface utilisateur" msgid "User matching mode" msgstr "Mode de correspondance utilisateur" +#: src/pages/admin-overview/UserDashboardPage.ts +#~ msgid "User metrics" +#~ msgstr "" + #: src/pages/sources/ldap/LDAPSourceForm.ts msgid "User object filter" msgstr "Filtre des objets utilisateur" @@ -5413,10 +5508,30 @@ msgstr "Filtre des objets utilisateur" msgid "User password writeback" msgstr "Réécriture du mot de passe utilisateur" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "User statistics" +msgstr "" + #: src/pages/users/UserListPage.ts msgid "User status" msgstr "Statut utilisateur" +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification" +msgstr "" + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification is preferred if available, but not required." +msgstr "" + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification must occur." +msgstr "" + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification should not occur." +msgstr "" + #: src/pages/events/utils.ts msgid "User was written to" msgstr "L'utilisateur a été écrit vers " @@ -5467,6 +5582,7 @@ msgstr "Nom d'utilisateur" msgid "Username: Same as Text input, but checks for and prevents duplicate usernames." msgstr "Nom d'utilisateur : Identique à la saisie de texte, mais vérifie et empêche les noms d'utilisateur en double." +#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/admin-overview/AdminOverviewPage.ts #: src/pages/users/UserListPage.ts @@ -5477,6 +5593,10 @@ msgstr "Utilisateurs" msgid "Users added to this group will be superusers." msgstr "Les utilisateurs ajoutés à ce groupe seront des super-utilisateurs." +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Users created per day in the last month" +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed." msgstr "Les utilisateurs de ce groupe peuvent effectuer des recherches. Si aucun groupe n'est sélectionné, aucune recherche LDAP n'est autorisée." @@ -5589,6 +5709,10 @@ msgstr "" msgid "Warning: Provider not assigned to any application." msgstr "Avertissement : le fournisseur n'est assigné à aucune application." +#: src/pages/users/UserListPage.ts +msgid "Warning: You're about to delete the user you're logged in as ({0}). Proceed at your own risk." +msgstr "" + #: src/pages/outposts/OutpostListPage.ts msgid "Warning: authentik Domain is not configured, authentication will not work." msgstr "Avertissement : le domaine d'authentik n'est pas configuré, l'authentification ne fonctionnera pas." @@ -5617,6 +5741,10 @@ msgstr "Mapping Webhook" msgid "Webhook URL" msgstr "URL Webhoo" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Welcome, {name}." +msgstr "" + #: src/pages/stages/email/EmailStageForm.ts msgid "When a user returns from the email successfully, their account will be activated." msgstr "Lorsqu'un utilisateur revient de l'e-mail avec succès, son compte sera activé." @@ -5718,12 +5846,20 @@ msgstr "Vous allez être redirigé vers l'URL suivante." msgid "You're currently impersonating {0}. Click to stop." msgstr "Vous êtes en train de vous faire passer pour {0}. Cliquez pour arrêter." +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "app1 running on app1.example.com" +msgstr "" + #~ msgid "authentik Builtin Database" #~ msgstr "Base de données intégrée à authentik" #~ msgid "authentik LDAP Backend" #~ msgstr "Backend LDAP authentik" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "authentik running on auth.example.com" +msgstr "" + #: src/elements/forms/DeleteForm.ts msgid "connecting object will be deleted" msgstr "L'objet connecté sera supprimé" @@ -5792,3 +5928,11 @@ msgstr "{0}, devrait être {1}" #: src/elements/forms/ConfirmationForm.ts msgid "{0}: {1}" msgstr "{0} : {1}" + +#: src/elements/charts/AdminModelPerDay.ts +msgid "{ago} days ago" +msgstr "" + +#: src/elements/charts/Chart.ts +msgid "{ago} hours ago" +msgstr "" diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index 3082044af3..b024d7e92c 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -296,6 +296,10 @@ msgstr "" msgid "Always require consent" msgstr "" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "An example setup can look like this:" +msgstr "" + #: src/pages/stages/prompt/PromptForm.ts msgid "Any HTML can be used." msgstr "" @@ -344,6 +348,7 @@ msgstr "" msgid "Application(s)" msgstr "" +#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/applications/ApplicationListPage.ts #: src/pages/outposts/OutpostForm.ts @@ -403,9 +408,13 @@ msgid "Assigned to application" msgstr "" #: src/pages/policies/PolicyListPage.ts -msgid "Assigned to {0} objects." +msgid "Assigned to {0} object(s)." msgstr "" +#: src/pages/policies/PolicyListPage.ts +#~ msgid "Assigned to {0} objects." +#~ msgstr "" + #: src/pages/events/EventInfo.ts msgid "Attempted to log in as {0}" msgstr "" @@ -429,6 +438,10 @@ msgstr "" #~ msgid "Auth Type" #~ msgstr "" +#: src/flows/sources/apple/AppleLoginInit.ts +msgid "Authenticating with Apple..." +msgstr "" + #: src/flows/sources/plex/PlexLoginInit.ts msgid "Authenticating with Plex..." msgstr "" @@ -441,6 +454,10 @@ msgstr "" msgid "Authentication Type" msgstr "" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "Authentication URL" +msgstr "" + #: src/pages/sources/oauth/OAuthSourceForm.ts #: src/pages/sources/plex/PlexSourceForm.ts #: src/pages/sources/saml/SAMLSourceForm.ts @@ -756,6 +773,10 @@ msgstr "" msgid "Check the IP of the Kubernetes service, or" msgstr "" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Check the logs" +msgstr "" + #: #~ msgid "Check your Emails for a password reset link." #~ msgstr "" @@ -1194,6 +1215,10 @@ msgstr "" msgid "Create User" msgstr "" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Create a new application" +msgstr "" + #: src/pages/users/ServiceAccountForm.ts msgid "Create group" msgstr "" @@ -1254,6 +1279,10 @@ msgstr "" msgid "DSA-SHA1" msgstr "" +#: src/interfaces/AdminInterface.ts +msgid "Dashboards" +msgstr "" + #: src/pages/stages/prompt/PromptForm.ts msgid "Date" msgstr "" @@ -1441,6 +1470,10 @@ msgstr "" msgid "Direct querying, always returns the latest data, but slower than cached querying." msgstr "" +#: src/interfaces/AdminInterface.ts +msgid "Directory" +msgstr "" + #: #: #~ msgid "Disable" @@ -1810,6 +1843,10 @@ msgstr "" msgid "Explicit Consent" msgstr "" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Explore integrations" +msgstr "" + #: src/pages/flows/FlowViewPage.ts msgid "Export" msgstr "" @@ -1847,7 +1884,6 @@ msgstr "" msgid "External Host" msgstr "" -#: src/pages/providers/proxy/ProxyProviderForm.ts #: src/pages/providers/proxy/ProxyProviderForm.ts #: src/pages/providers/proxy/ProxyProviderForm.ts msgid "External host" @@ -1858,6 +1894,10 @@ msgstr "" msgid "Failed Logins" msgstr "" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Failed Logins per day in the last month" +msgstr "" + #: src/pages/stages/password/PasswordStageForm.ts msgid "Failed attempts before cancel" msgstr "" @@ -1891,6 +1931,11 @@ msgstr "" msgid "Favicon" msgstr "" +#: src/interfaces/AdminInterface.ts +#: src/pages/sources/SourcesListPage.ts +msgid "Federation & Social login" +msgstr "" + #: src/pages/stages/prompt/PromptListPage.ts msgid "Field" msgstr "" @@ -1936,6 +1981,10 @@ msgstr "" msgid "Flow Overview" msgstr "" +#: src/pages/events/utils.ts +msgid "Flow execution" +msgstr "" + #: src/flows/FlowInspector.ts #: src/flows/FlowInspector.ts msgid "Flow inspector" @@ -2262,8 +2311,8 @@ msgid "Identifier" msgstr "" #: src/interfaces/AdminInterface.ts -msgid "Identity & Cryptography" -msgstr "" +#~ msgid "Identity & Cryptography" +#~ msgstr "" #: src/pages/outposts/ServiceConnectionDockerForm.ts #: src/pages/outposts/ServiceConnectionKubernetesForm.ts @@ -2336,6 +2385,10 @@ msgstr "" msgid "In case you can't access any other method." msgstr "" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com." +msgstr "" + #: src/pages/users/UserListPage.ts msgid "Inactive" msgstr "" @@ -2358,8 +2411,8 @@ msgid "Integration key" msgstr "" #: src/interfaces/AdminInterface.ts -msgid "Integrations" -msgstr "" +#~ msgid "Integrations" +#~ msgstr "" #: src/pages/tokens/TokenForm.ts #: src/pages/tokens/TokenListPage.ts @@ -2679,6 +2732,10 @@ msgstr "" msgid "Logins over the last 24 hours" msgstr "" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Logins per day in the last month" +msgstr "" + #: src/pages/tenants/TenantForm.ts msgid "Logo" msgstr "" @@ -2986,6 +3043,10 @@ msgstr "" msgid "No additional data available." msgstr "" +#: src/pages/providers/proxy/ProxyProviderViewPage.ts +msgid "No additional setup is required." +msgstr "" + #: src/elements/forms/ModalForm.ts msgid "No form found" msgstr "" @@ -3133,6 +3194,10 @@ msgstr "" msgid "Object uniqueness field" msgstr "" +#: src/elements/charts/AdminModelPerDay.ts +msgid "Objects created" +msgstr "" + #: src/pages/stages/consent/ConsentStageForm.ts msgid "Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." msgstr "" @@ -3151,6 +3216,10 @@ msgstr "" msgid "Only send notification once, for example when sending a webhook into a chat channel." msgstr "" +#: src/elements/notifications/APIDrawer.ts +msgid "Open API Browser" +msgstr "" + #: #~ msgid "Open application" #~ msgstr "" @@ -3200,8 +3269,8 @@ msgid "Optionally set the 'FriendlyName' value of the Assertion attribute." msgstr "" #: src/pages/providers/proxy/ProxyProviderForm.ts -msgid "Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." -msgstr "" +#~ msgid "Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." +#~ msgstr "" #: src/pages/flows/BoundStagesList.ts #: src/pages/flows/StageBindingForm.ts @@ -3229,6 +3298,10 @@ msgstr "" msgid "Outpost Deployment Info" msgstr "" +#: src/interfaces/AdminInterface.ts +msgid "Outpost Integrations" +msgstr "" + #: #~ msgid "Outpost Service-connection" #~ msgstr "" @@ -3249,7 +3322,6 @@ msgstr "" msgid "Outpost(s)" msgstr "" -#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/outposts/OutpostListPage.ts msgid "Outposts" @@ -3355,7 +3427,6 @@ msgid "Please enter your password" msgstr "" #: src/interfaces/AdminInterface.ts -#: src/pages/admin-overview/AdminOverviewPage.ts #: src/pages/flows/FlowListPage.ts #: src/pages/policies/PolicyListPage.ts msgid "Policies" @@ -3574,6 +3645,10 @@ msgstr "" msgid "Publisher" msgstr "" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Quick actions" +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning, while keeping the flow context." msgstr "" @@ -3751,14 +3826,18 @@ msgid "Reset Password" msgstr "" #: src/interfaces/AdminInterface.ts -msgid "Resources" -msgstr "" +#~ msgid "Resources" +#~ msgstr "" #: src/pages/events/EventInfo.ts #: src/pages/property-mappings/PropertyMappingTestForm.ts msgid "Result" msgstr "" +#: src/flows/sources/apple/AppleLoginInit.ts +msgid "Retry" +msgstr "" + #: #~ msgid "Retry Task" #~ msgstr "" @@ -4099,6 +4178,10 @@ msgstr "" msgid "Set custom attributes using YAML or JSON." msgstr "" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'." +msgstr "" + #: src/pages/providers/proxy/ProxyProviderViewPage.ts msgid "Setup" msgstr "" @@ -4196,8 +4279,6 @@ msgstr "" msgid "Source(s)" msgstr "" -#: src/interfaces/AdminInterface.ts -#: src/pages/sources/SourcesListPage.ts #: src/pages/stages/identification/IdentificationStageForm.ts msgid "Sources" msgstr "" @@ -4288,6 +4369,7 @@ msgstr "" #: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts #: src/pages/stages/captcha/CaptchaStageForm.ts #: src/pages/stages/consent/ConsentStageForm.ts #: src/pages/stages/email/EmailStageForm.ts @@ -4724,10 +4806,14 @@ msgstr "" msgid "Sync users" msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts -msgid "System Overview" +#: src/interfaces/AdminInterface.ts +msgid "System" msgstr "" +#: src/pages/admin-overview/AdminOverviewPage.ts +#~ msgid "System Overview" +#~ msgstr "" + #: src/interfaces/AdminInterface.ts #: src/pages/system-tasks/SystemTaskListPage.ts msgid "System Tasks" @@ -4835,7 +4921,11 @@ msgid "The external URL you'll access the application at. Include any non-standa msgstr "" #: src/pages/providers/proxy/ProxyProviderForm.ts -msgid "The external URL you'll authenticate at. Can be the same domain as authentik." +#~ msgid "The external URL you'll authenticate at. Can be the same domain as authentik." +#~ msgstr "" + +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "The external URL you'll authenticate at. The authentik core server should be reachable under this URL." msgstr "" #: @@ -5095,6 +5185,7 @@ msgid "UI settings" msgstr "" #: src/pages/events/EventInfo.ts +#: src/pages/users/UserListPage.ts msgid "UID" msgstr "" @@ -5447,6 +5538,10 @@ msgstr "" msgid "User matching mode" msgstr "" +#: src/pages/admin-overview/UserDashboardPage.ts +#~ msgid "User metrics" +#~ msgstr "" + #: src/pages/sources/ldap/LDAPSourceForm.ts msgid "User object filter" msgstr "" @@ -5455,10 +5550,30 @@ msgstr "" msgid "User password writeback" msgstr "" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "User statistics" +msgstr "" + #: src/pages/users/UserListPage.ts msgid "User status" msgstr "" +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification" +msgstr "" + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification is preferred if available, but not required." +msgstr "" + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification must occur." +msgstr "" + +#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +msgid "User verification should not occur." +msgstr "" + #: src/pages/events/utils.ts msgid "User was written to" msgstr "" @@ -5509,6 +5624,7 @@ msgstr "" msgid "Username: Same as Text input, but checks for and prevents duplicate usernames." msgstr "" +#: src/interfaces/AdminInterface.ts #: src/interfaces/AdminInterface.ts #: src/pages/admin-overview/AdminOverviewPage.ts #: src/pages/users/UserListPage.ts @@ -5519,6 +5635,10 @@ msgstr "" msgid "Users added to this group will be superusers." msgstr "" +#: src/pages/admin-overview/DashboardUserPage.ts +msgid "Users created per day in the last month" +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed." msgstr "" @@ -5631,6 +5751,10 @@ msgstr "" msgid "Warning: Provider not assigned to any application." msgstr "" +#: src/pages/users/UserListPage.ts +msgid "Warning: You're about to delete the user you're logged in as ({0}). Proceed at your own risk." +msgstr "" + #: src/pages/outposts/OutpostListPage.ts msgid "Warning: authentik Domain is not configured, authentication will not work." msgstr "" @@ -5659,6 +5783,10 @@ msgstr "" msgid "Webhook URL" msgstr "" +#: src/pages/admin-overview/AdminOverviewPage.ts +msgid "Welcome, {name}." +msgstr "" + #: src/pages/stages/email/EmailStageForm.ts msgid "When a user returns from the email successfully, their account will be activated." msgstr "" @@ -5760,6 +5888,10 @@ msgstr "" msgid "You're currently impersonating {0}. Click to stop." msgstr "" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "app1 running on app1.example.com" +msgstr "" + #: #~ msgid "authentik Builtin Database" #~ msgstr "" @@ -5768,6 +5900,10 @@ msgstr "" #~ msgid "authentik LDAP Backend" #~ msgstr "" +#: src/pages/providers/proxy/ProxyProviderForm.ts +msgid "authentik running on auth.example.com" +msgstr "" + #: src/elements/forms/DeleteForm.ts msgid "connecting object will be deleted" msgstr "" @@ -5836,3 +5972,11 @@ msgstr "" #: src/elements/forms/ConfirmationForm.ts msgid "{0}: {1}" msgstr "" + +#: src/elements/charts/AdminModelPerDay.ts +msgid "{ago} days ago" +msgstr "" + +#: src/elements/charts/Chart.ts +msgid "{ago} hours ago" +msgstr "" diff --git a/web/src/pages/admin-overview/AdminOverviewPage.ts b/web/src/pages/admin-overview/AdminOverviewPage.ts index 848c4c9125..7e6c76c030 100644 --- a/web/src/pages/admin-overview/AdminOverviewPage.ts +++ b/web/src/pages/admin-overview/AdminOverviewPage.ts @@ -2,15 +2,19 @@ import { t } from "@lingui/macro"; import { CSSResult, LitElement, TemplateResult, css, html } from "lit"; import { customElement } from "lit/decorators.js"; +import { until } from "lit/directives/until.js"; import AKGlobal from "../../authentik.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFList from "@patternfly/patternfly/components/List/list.css"; import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; +import { me } from "../../api/Users"; import "../../elements/PageHeader"; import "../../elements/cards/AggregatePromiseCard"; import "../../elements/charts/AdminLoginsChart"; +import { paramURL } from "../../elements/router/RouterOutlet"; import "./TopApplicationsTable"; import "./cards/AdminStatusCard"; import "./cards/BackupStatusCard"; @@ -31,6 +35,7 @@ export class AdminOverviewPage extends LitElement { PFGrid, PFPage, PFContent, + PFList, AKGlobal, css` .row-divider { @@ -51,11 +56,18 @@ export class AdminOverviewPage extends LitElement { } render(): TemplateResult { - return html` + return html` + + ${until( + me().then((user) => { + let name = user.user.username; + if (user.user.name !== "") { + name = user.user.name; + } + return t`Welcome, ${name}.`; + }), + )} +
@@ -64,11 +76,33 @@ export class AdminOverviewPage extends LitElement { class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-xl pf-m-2-col-on-2xl graph-container" > - +
+ +
+
+
+ + + + +
+
+
+
+ +
+ + + + +
+
+ + + + +
+
+
`; + } +} diff --git a/web/src/pages/admin-overview/charts/LDAPSyncStatusChart.ts b/web/src/pages/admin-overview/charts/LDAPSyncStatusChart.ts index b4341a1713..f8aebf80f6 100644 --- a/web/src/pages/admin-overview/charts/LDAPSyncStatusChart.ts +++ b/web/src/pages/admin-overview/charts/LDAPSyncStatusChart.ts @@ -36,37 +36,41 @@ export class LDAPSyncStatusChart extends AKChart { async apiRequest(): Promise { const api = new SourcesApi(DEFAULT_CONFIG); const sources = await api.sourcesLdapList({}); - let healthy = 0; - let failed = 0; - let unsynced = 0; + const metrics: { [key: string]: number } = { + healthy: 0, + failed: 0, + unsynced: 0, + }; await Promise.all( sources.results.map(async (element) => { + // Each source should have 3 successful tasks, so the worst task overwrites + let sourceKey = "healthy"; try { const health = await api.sourcesLdapSyncStatusList({ slug: element.slug, }); + health.forEach((task) => { if (task.status !== StatusEnum.Successful) { - failed += 1; + sourceKey = "failed"; } const now = new Date().getTime(); const maxDelta = 3600000; // 1 hour if (!health || now - task.taskFinishTimestamp.getTime() > maxDelta) { - unsynced += 1; - } else { - healthy += 1; + sourceKey = "unsynced"; } }); } catch { - unsynced += 1; + sourceKey = "unsynced"; } + metrics[sourceKey] += 1; }), ); this.centerText = sources.pagination.count.toString(); return { - healthy: sources.pagination.count === 0 ? -1 : healthy, - failed, - unsynced, + healthy: sources.pagination.count === 0 ? -1 : metrics.healthy, + failed: metrics.failed, + unsynced: metrics.unsynced, }; } diff --git a/web/src/pages/applications/ApplicationListPage.ts b/web/src/pages/applications/ApplicationListPage.ts index 450ff28a6a..b408ffd54b 100644 --- a/web/src/pages/applications/ApplicationListPage.ts +++ b/web/src/pages/applications/ApplicationListPage.ts @@ -2,6 +2,7 @@ import { t } from "@lingui/macro"; import { CSSResult, TemplateResult, css, html } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css"; @@ -13,6 +14,7 @@ import { uiConfig } from "../../common/config"; import "../../elements/buttons/SpinnerButton"; import "../../elements/forms/DeleteBulkForm"; import "../../elements/forms/ModalForm"; +import { getURLParam } from "../../elements/router/RouteMatch"; import { TableColumn } from "../../elements/table/Table"; import { TablePage } from "../../elements/table/TablePage"; import "./ApplicationForm"; @@ -94,15 +96,24 @@ export class ApplicationListPage extends TablePage { `; } + renderIcon(item: Application): TemplateResult { + if (item?.metaIcon) { + if (item.metaIcon.startsWith("fa://")) { + const icon = item.metaIcon.replaceAll("fa://", ""); + return html``; + } + return html`${t`Application Icon`}`; + } + return html``; + } + row(item: Application): TemplateResult[] { return [ - item.metaIcon - ? html`${t`Application Icon`}` - : html``, + this.renderIcon(item), html`
${item.name}
${item.metaPublisher ? html`${item.metaPublisher}` : html``} @@ -133,7 +144,7 @@ export class ApplicationListPage extends TablePage { renderToolbar(): TemplateResult { return html` - + ${t`Create`} ${t`Create Application`} diff --git a/web/src/pages/events/utils.ts b/web/src/pages/events/utils.ts index 130f3c31a3..7810b94d10 100644 --- a/web/src/pages/events/utils.ts +++ b/web/src/pages/events/utils.ts @@ -31,6 +31,8 @@ export function ActionToLabel(action?: EventActions): string { return t`Impersonation started`; case EventActions.ImpersonationEnded: return t`Impersonation ended`; + case EventActions.FlowExecution: + return t`Flow execution`; case EventActions.PolicyExecution: return t`Policy execution`; case EventActions.PolicyException: diff --git a/web/src/pages/policies/PolicyListPage.ts b/web/src/pages/policies/PolicyListPage.ts index 1b8aee48ab..e84cfc128a 100644 --- a/web/src/pages/policies/PolicyListPage.ts +++ b/web/src/pages/policies/PolicyListPage.ts @@ -75,7 +75,7 @@ export class PolicyListPage extends TablePage {
${item.name}
${(item.boundTo || 0) > 0 ? html` - ${t`Assigned to ${item.boundTo} objects.`} ` + ${t`Assigned to ${item.boundTo} object(s).`} ` : html` ${t`Warning: Policy is not assigned.`}`}
`, diff --git a/web/src/pages/providers/proxy/ProxyProviderForm.ts b/web/src/pages/providers/proxy/ProxyProviderForm.ts index 0218ebe028..bff2c51694 100644 --- a/web/src/pages/providers/proxy/ProxyProviderForm.ts +++ b/web/src/pages/providers/proxy/ProxyProviderForm.ts @@ -7,6 +7,7 @@ import { ifDefined } from "lit/directives/if-defined.js"; import { until } from "lit/directives/until.js"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFList from "@patternfly/patternfly/components/List/list.css"; import PFToggleGroup from "@patternfly/patternfly/components/ToggleGroup/toggle-group.css"; import PFSpacing from "@patternfly/patternfly/utilities/Spacing/spacing.css"; @@ -32,6 +33,7 @@ export class ProxyProviderFormPage extends ModelForm { return super.styles.concat( PFToggleGroup, PFContent, + PFList, PFSpacing, css` .pf-c-toggle-group { @@ -162,7 +164,7 @@ export class ProxyProviderFormPage extends ModelForm { renderSettings(): TemplateResult { switch (this.mode) { case ProxyMode.Proxy: - return html`

+ return html`

${t`This provider will behave like a transparent reverse-proxy, except requests must be authenticated. If your upstream application uses HTTPS, make sure to connect to the outpost using HTTPS as well.`}

{

`; case ProxyMode.ForwardSingle: - return html`

+ return html`

${t`Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you).`}

{

`; case ProxyMode.ForwardDomain: - return html`

+ return html`

${t`Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application.`}

+
+ ${t`An example setup can look like this:`} +
    +
  • ${t`authentik running on auth.example.com`}
  • +
  • ${t`app1 running on app1.example.com`}
  • +
+ ${t`In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com.`} +
@@ -245,10 +255,14 @@ export class ProxyProviderFormPage extends ModelForm { required />

- ${t`The external URL you'll authenticate at. Can be the same domain as authentik.`} + ${t`The external URL you'll authenticate at. The authentik core server should be reachable under this URL.`}

- + { required />

- ${t`Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.`} + ${t`Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.`}

`; } diff --git a/web/src/pages/providers/proxy/ProxyProviderViewPage.ts b/web/src/pages/providers/proxy/ProxyProviderViewPage.ts index 8165419d1a..7192fffa72 100644 --- a/web/src/pages/providers/proxy/ProxyProviderViewPage.ts +++ b/web/src/pages/providers/proxy/ProxyProviderViewPage.ts @@ -92,10 +92,17 @@ export class ProxyProviderViewPage extends LitElement { renderConfigTemplate(tmpl: string): TemplateResult { // See website/docs/providers/proxy/forward_auth.mdx - const final = tmpl - .replaceAll("authentik.company", window.location.hostname) - .replaceAll("outpost.company", window.location.hostname) - .replaceAll("app.company", this.provider?.externalHost || ""); + let final = ""; + if (this.provider?.mode === ProxyMode.ForwardSingle) { + final = tmpl + .replaceAll("authentik.company", window.location.hostname) + .replaceAll("outpost.company", window.location.hostname) + .replaceAll("app.company", this.provider?.externalHost || ""); + } else if (this.provider?.mode == ProxyMode.ForwardDomain) { + final = tmpl + .replaceAll("authentik.company", window.location.hostname) + .replaceAll("outpost.company", this.provider?.externalHost || ""); + } return html`${unsafeHTML(final)}`; } @@ -233,50 +240,56 @@ export class ProxyProviderViewPage extends LitElement {
${t`Setup`}
- -
- ${this.renderConfigTemplate(MDNginxIngress.html)} -
-
- ${this.renderConfigTemplate(MDNginxPM.html)} -
-
- ${this.renderConfigTemplate(MDNginxStandalone.html)} -
-
- ${this.renderConfigTemplate(MDTraefikIngres.html)} -
-
- ${this.renderConfigTemplate(MDTraefikCompose.html)} -
-
- ${this.renderConfigTemplate(MDTraefikStandalone.html)} -
-
+ ${[ProxyMode.ForwardSingle, ProxyMode.ForwardDomain].includes( + this.provider?.mode || ProxyMode.Proxy, + ) + ? html` + +
+ ${this.renderConfigTemplate(MDNginxIngress.html)} +
+
+ ${this.renderConfigTemplate(MDNginxPM.html)} +
+
+ ${this.renderConfigTemplate(MDNginxStandalone.html)} +
+
+ ${this.renderConfigTemplate(MDTraefikIngres.html)} +
+
+ ${this.renderConfigTemplate(MDTraefikCompose.html)} +
+
+ ${this.renderConfigTemplate(MDTraefikStandalone.html)} +
+
+ ` + : html`

${t`No additional setup is required.`}

`}
`; diff --git a/web/src/pages/sources/SourcesListPage.ts b/web/src/pages/sources/SourcesListPage.ts index 0763a27f76..48f9e9b958 100644 --- a/web/src/pages/sources/SourcesListPage.ts +++ b/web/src/pages/sources/SourcesListPage.ts @@ -25,7 +25,7 @@ import "./saml/SAMLSourceForm"; @customElement("ak-source-list") export class SourceListPage extends TablePage { pageTitle(): string { - return t`Sources`; + return t`Federation & Social login`; } pageDescription(): string | undefined { return t`Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves.`; @@ -139,8 +139,7 @@ export class SourceListPage extends TablePage { > `; diff --git a/web/src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts b/web/src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts index 96e52921fe..c1193d5b72 100644 --- a/web/src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +++ b/web/src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts @@ -1,3 +1,5 @@ +import { UserVerificationEnum } from "@goauthentik/api/dist/models/UserVerificationEnum"; + import { t } from "@lingui/macro"; import { TemplateResult, html } from "lit"; @@ -52,6 +54,40 @@ export class AuthenticateWebAuthnStageForm extends ModelForm + + ${t`Stage-specific settings`} +
+ + + +
+
`; } } diff --git a/web/src/pages/users/UserListPage.ts b/web/src/pages/users/UserListPage.ts index 95e5e85f2a..9c484640f1 100644 --- a/web/src/pages/users/UserListPage.ts +++ b/web/src/pages/users/UserListPage.ts @@ -4,12 +4,14 @@ import { CSSResult, TemplateResult, html } from "lit"; import { customElement, property } from "lit/decorators.js"; import { until } from "lit/directives/until.js"; +import PFAlert from "@patternfly/patternfly/components/Alert/alert.css"; import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; import { CoreApi, User } from "@goauthentik/api"; import { AKResponse } from "../../api/Client"; import { DEFAULT_CONFIG, tenant } from "../../api/Config"; +import { me } from "../../api/Users"; import { uiConfig } from "../../common/config"; import { PFColor } from "../../elements/Label"; import "../../elements/buttons/ActionButton"; @@ -51,7 +53,7 @@ export class UserListPage extends TablePage { hideServiceAccounts = getURLParam("hideServiceAccounts", true); static get styles(): CSSResult[] { - return super.styles.concat(PFDescriptionList); + return super.styles.concat(PFDescriptionList, PFAlert); } async apiEndpoint(page: number): Promise> { @@ -79,13 +81,14 @@ export class UserListPage extends TablePage { renderToolbarSelected(): TemplateResult { const disabled = this.selectedElements.length < 1; - return html` { return [ { key: t`Username`, value: item.username }, { key: t`ID`, value: item.pk.toString() }, + { key: t`UID`, value: item.uid }, ]; }} .usedBy=${(item: User) => { @@ -99,6 +102,28 @@ export class UserListPage extends TablePage { }); }} > + ${until( + me().then((user) => { + const shouldShowWarning = this.selectedElements.find((el) => { + return el.pk === user.user.pk || el.pk == user.original?.pk; + }); + if (shouldShowWarning) { + return html` +
+
+
+ +
+

+ ${t`Warning: You're about to delete the user you're logged in as (${shouldShowWarning.username}). Proceed at your own risk.`} +

+
+
+ `; + } + return html``; + }), + )} diff --git a/web/src/routesAdmin.ts b/web/src/routesAdmin.ts index e66ea154f7..99e2250dfb 100644 --- a/web/src/routesAdmin.ts +++ b/web/src/routesAdmin.ts @@ -2,6 +2,7 @@ import { html } from "lit"; import { ID_REGEX, Route, SLUG_REGEX, UUID_REGEX } from "./elements/router/Route"; import "./pages/admin-overview/AdminOverviewPage"; +import "./pages/admin-overview/DashboardUserPage"; import "./pages/applications/ApplicationListPage"; import "./pages/applications/ApplicationViewPage"; import "./pages/crypto/CertificateKeyPairListPage"; @@ -40,6 +41,10 @@ export const ROUTES: Route[] = [ new RegExp("^/administration/overview$"), html``, ), + new Route( + new RegExp("^/administration/dashboard/users$"), + html``, + ), new Route( new RegExp("^/administration/system-tasks$"), html``, diff --git a/website/docs/core/terminology.md b/website/docs/core/terminology.md index 95e6c27a9f..1ed5202f31 100644 --- a/website/docs/core/terminology.md +++ b/website/docs/core/terminology.md @@ -28,7 +28,7 @@ At a base level a policy is a yes/no gate. It will either evaluate to True or Fa See [Policies](./policies/) -### Stages & Stages +### Flows & Stages Flows are an ordered sequence of stages. These flows can be used to define how a user authenticates, enrolls, etc. diff --git a/website/docs/flow/index.md b/website/docs/flow/index.md index d5cad928f5..83a6c4b40f 100644 --- a/website/docs/flow/index.md +++ b/website/docs/flow/index.md @@ -36,16 +36,16 @@ This stage should always contain a [**User Logout**](stages/user_logout.md) stag ### Enrollment -This designates a flow for enrollment. This flow can contain any amount of verification stages, such as [**email**](stages/email/index.md) or [**captcha**](stages/captcha/index.md). At the end, to create the user, you can use the [**user_write**](stages/user_write.md) stage, which either updates the currently staged user, or if none exists, creates a new one. +This designates a flow for enrollment. This flow can contain any amount of verification stages, such as [**email**](stages/email/) or [**captcha**](stages/captcha/). At the end, to create the user, you can use the [**user_write**](stages/user_write.md) stage, which either updates the currently staged user, or if none exists, creates a new one. ### Unenrollment -This designates a flow for unenrollment. This flow can contain any amount of verification stages, such as [**email**](stages/email/index.md) or [**captcha**](stages/captcha/index.md). As a final stage, to delete the account, use the [**user_delete**](stages/user_delete.md) stage. +This designates a flow for unenrollment. This flow can contain any amount of verification stages, such as [**email**](stages/email/) or [**captcha**](stages/captcha/). As a final stage, to delete the account, use the [**user_delete**](stages/user_delete.md) stage. ### Recovery -This designates a flow for recovery. This flow normally contains an [**identification**](stages/identification/index.md) stage to find the user. It can also contain any amount of verification stages, such as [**email**](stages/email/index.md) or [**captcha**](stages/captcha/index.md). -Afterwards, use the [**prompt**](stages/prompt/index.md) stage to ask the user for a new password and the [**user_write**](stages/user_write.md) stage to update the password. +This designates a flow for recovery. This flow normally contains an [**identification**](stages/identification/) stage to find the user. It can also contain any amount of verification stages, such as [**email**](stages/email/) or [**captcha**](stages/captcha/). +Afterwards, use the [**prompt**](stages/prompt/) stage to ask the user for a new password and the [**user_write**](stages/user_write.md) stage to update the password. ### Setup diff --git a/website/docs/flow/stages/authenticator_validate/index.md b/website/docs/flow/stages/authenticator_validate/index.md index 034da1110a..c710fe9409 100644 --- a/website/docs/flow/stages/authenticator_validate/index.md +++ b/website/docs/flow/stages/authenticator_validate/index.md @@ -4,11 +4,11 @@ title: Authenticator Validation Stage This stage validates an already configured Authenticator Device. This device has to be configured using any of the other authenticator stages: -- [Duo authenticator stage](../authenticator_duo/index.md) -- [SMS authenticator stage](../authenticator_sms/index.md). -- [Static authenticator stage](../authenticator_static/index.md). -- [TOTP authenticator stage](../authenticator_totp/index.md) -- [WebAuth authenticator stage](../authenticator_webauthn/index.md). +- [Duo authenticator stage](../authenticator_duo/) +- [SMS authenticator stage](../authenticator_sms/). +- [Static authenticator stage](../authenticator_static/). +- [TOTP authenticator stage](../authenticator_totp/) +- [WebAuth authenticator stage](../authenticator_webauthn/). You can select which type of device classes are allowed. diff --git a/website/docs/flow/stages/invitation/index.md b/website/docs/flow/stages/invitation/index.md index a24bd4eb7b..7080d04a79 100644 --- a/website/docs/flow/stages/invitation/index.md +++ b/website/docs/flow/stages/invitation/index.md @@ -10,4 +10,4 @@ To check if a user has used an invitation within a policy, you can check `reques To use an invitation, use the URL `https://authentik.tld/if/flow/your-enrollment-flow/?itoken=invitation-token`. -You can also prompt the user for an invite by using the [*Prompt stage*](../prompt/index.md) by using a field with a field key of `token`. +You can also prompt the user for an invite by using the [*Prompt stage*](../prompt/) by using a field with a field key of `token`. diff --git a/website/docs/installation/docker-compose.md b/website/docs/installation/docker-compose.md index cf381284e3..0bc4470e36 100644 --- a/website/docs/installation/docker-compose.md +++ b/website/docs/installation/docker-compose.md @@ -31,7 +31,7 @@ echo "AUTHENTIK_ERROR_REPORTING__ENABLED=true" >> .env ## Email configuration (optional, but recommended) -It is also recommended to configure global email credentials. These are used by authentik to notify you about alerts and configuration issues. They can also be used by [Email stages](flow/stages/email/index.md) to send verification/recovery emails. +It is also recommended to configure global email credentials. These are used by authentik to notify you about alerts and configuration issues. They can also be used by [Email stages](../flow/stages/email/) to send verification/recovery emails. Append this block to your `.env` file diff --git a/website/docs/installation/kubernetes.md b/website/docs/installation/kubernetes.md index c2998b8635..225b1d60c6 100644 --- a/website/docs/installation/kubernetes.md +++ b/website/docs/installation/kubernetes.md @@ -46,4 +46,4 @@ helm install authentik authentik/authentik -f values.yaml This installation automatically applies database migrations on startup. After the installation is done, navigate to the `https:///if/flow/initial-setup/`, to set a password for the akadmin user. -It is also recommended to configure global email credentials. These are used by authentik to notify you about alerts, configuration issues. They can also be used by [Email stages](flow/stages/email/index.md) to send verification/recovery emails. +It is also recommended to configure global email credentials. These are used by authentik to notify you about alerts, configuration issues. They can also be used by [Email stages](../flow/stages/email/) to send verification/recovery emails. diff --git a/website/docs/providers/oauth2.md b/website/docs/providers/oauth2.md index cf2dca183d..465669acf5 100644 --- a/website/docs/providers/oauth2.md +++ b/website/docs/providers/oauth2.md @@ -4,7 +4,7 @@ title: OAuth2 Provider This provider supports both generic OAuth2 as well as OpenID Connect -Scopes can be configured using Scope Mappings, a type of [Property Mappings](../property-mappings/index.md#scope-mapping). +Scopes can be configured using Scope Mappings, a type of [Property Mappings](../property-mappings/#scope-mapping). | Endpoint | URL | | -------------------- | -------------------------------------------------------------------- | diff --git a/website/docs/providers/saml.md b/website/docs/providers/saml.md index 99ffb1438f..0d53514507 100644 --- a/website/docs/providers/saml.md +++ b/website/docs/providers/saml.md @@ -2,7 +2,7 @@ title: SAML Provider --- -This provider allows you to integrate enterprise software using the SAML2 Protocol. It supports signed requests and uses [Property Mappings](../property-mappings/index.md#saml-property-mapping) to determine which fields are exposed and what values they return. This makes it possible to expose vendor-specific fields. +This provider allows you to integrate enterprise software using the SAML2 Protocol. It supports signed requests and uses [Property Mappings](../property-mappings/#saml-property-mapping) to determine which fields are exposed and what values they return. This makes it possible to expose vendor-specific fields. Default fields are exposed through auto-generated Property Mappings, which are prefixed with "authentik default". | Endpoint | URL | diff --git a/website/docs/releases/v0.11.md b/website/docs/releases/v0.11.md index 1b13e4d200..0627d9f62d 100644 --- a/website/docs/releases/v0.11.md +++ b/website/docs/releases/v0.11.md @@ -5,7 +5,7 @@ slug: "0.11" This update brings these headline features: -- Add Backup and Restore, currently only externally schedulable, documented [here](../maintenance/backups/index.md) +- Add Backup and Restore, currently only externally schedulable, documented [here](../maintenance/backups/) - New Admin Dashboard with more metrics and Charts Shows successful and failed logins from the last 24 hours, as well as the most used applications diff --git a/website/docs/releases/v2021.1.md b/website/docs/releases/v2021.1.md index 7061f9ba2a..f9ad789414 100644 --- a/website/docs/releases/v2021.1.md +++ b/website/docs/releases/v2021.1.md @@ -8,7 +8,7 @@ slug: "2021.1" - New versioning schema (year.month.release) - Add global email settings - In previous versions, you had to configure email connection details per [Email Stage](../flow/stages/email/index.md). Now, you can (and should) configure global settings. + In previous versions, you had to configure email connection details per [Email Stage](../flow/stages/email/). Now, you can (and should) configure global settings. This is documented under the [docker-compose](../installation/docker-compose.md) and [Kubernetes](../installation/kubernetes.md) sections. diff --git a/website/docs/releases/v2021.12.md b/website/docs/releases/v2021.12.md index a3c23614ab..9854a18959 100644 --- a/website/docs/releases/v2021.12.md +++ b/website/docs/releases/v2021.12.md @@ -103,6 +103,54 @@ This release does not have any headline features, and mostly fixes bugs. - web/elements: close dropdown when refresh event is dispatched - web/user: allow custom font-awesome icons for applications +## Fixed in 2021.12.1-rc4 + +- core: fix error when using invalid key-values in attributes query +- flows: fix error in inspector view +- flows: fix error when trying to print FlowToken objects +- lib: correctly report "faked" IPs to sentry +- outposts: add additional checks for websocket connection +- outposts: cleanup logs for failed binds +- outposts: don't try to create docker client for embedded outpost +- outposts: fix docker controller not stopping containers +- outposts: fix unlabeled transaction +- outposts: handle RuntimeError during websocket connect +- outposts: rewrite re-connect logic without recws +- outposts: set display name for outpost service account +- outposts/ldap: fix searches with mixed casing +- outposts/proxy: use filesystem storage for non-embedded outposts +- policies: don't always clear application cache on post_save +- stagse/authenticator_webauthn: remove pydantic import +- web: fix borders of sidebars in dark mode + +## Fixed in 2021.12.1-rc5 + +- crypto: add additional validation before importing a certificate +- events: add flow_execution event type +- events: fix schema for top_per_user +- flows: fix wrong exception being caught in flow inspector +- outposts: reset backoff after successful connect +- outposts/proxy: fix securecookie: the value is too long again, since it can happen even with filesystem storage +- providers/oauth2: add additional logging to show with token path is taken +- providers/oauth2: use generate_key instead of uuid4 +- sources/ldap: fix incorrect task names being referenced, use source native slug +- sources/oauth: add initial okta type +- sources/oauth: allow oauth types to override their login button challenge +- sources/oauth: implement apple native sign-in using the apple JS SDK +- sources/oauth: strip parts of custom apple client_id +- stages/authenticator_webauthn: make user_verification configurable +- stages/identification: fix miscalculated sleep +- stages/invitation: use GroupMemberSerializer serializer to prevent all of the user's groups and their users from being returned +- web: add link to open API Browser for API Drawer +- web/admin: add dashboard with user creation/login statistics +- web/admin: fix invalid display for LDAP Source sync status +- web/admin: fix rendering for applications on view page +- web/admin: fix rendering of applications with custom icon +- web/admin: improve wording for froward_auth, don't show setup when using proxy mode +- web/admin: show warning when deleting currently logged in user +- web/admin: update overview page +- web/flows: fix error when attempting to enroll new webauthn device + ## Upgrading This release does not introduce any new requirements. diff --git a/website/docs/releases/v2021.2.md b/website/docs/releases/v2021.2.md index 5c6a158ca3..8a7115bf3e 100644 --- a/website/docs/releases/v2021.2.md +++ b/website/docs/releases/v2021.2.md @@ -116,11 +116,11 @@ Due to the switch to managed objects, some default property mappings are changin The change affects the "SAML Name" property, which has been changed from an oid to a Schema URI to aid readability. The integrations affected are: -- [Ansible Tower/AWX](/integrations/services/awx-tower/index) -- [GitLab](/integrations/services/gitlab/index) -- [NextCloud](/integrations/services/nextcloud/index) -- [Rancher](/integrations/services/rancher/index) -- [Sentry](/integrations/services/sentry/index) +- [Ansible Tower/AWX](/integrations/services/awx-tower/) +- [GitLab](/integrations/services/gitlab/) +- [NextCloud](/integrations/services/nextcloud/) +- [Rancher](/integrations/services/rancher/) +- [Sentry](/integrations/services/sentry/) ### docker-compose diff --git a/website/integrations/services/tautulli/index.md b/website/integrations/services/tautulli/index.md index ec26ab525c..4c6f4ec680 100644 --- a/website/integrations/services/tautulli/index.md +++ b/website/integrations/services/tautulli/index.md @@ -50,4 +50,4 @@ In Tautulli, navigate to Settings and enable the "Show Advanced" option. Navigat Save the settings, and restart Tautulli if prompted. -Afterwards, you need to deploy an Outpost in front of Tautulli, as descried [here](../sonarr/index.md) +Afterwards, you need to deploy an Outpost in front of Tautulli, as descried [here](../sonarr/) diff --git a/website/netlify.toml b/website/netlify.toml index 4025e2d4ef..eddb8831d2 100644 --- a/website/netlify.toml +++ b/website/netlify.toml @@ -2,10 +2,34 @@ from = "/discord" to = "https://discord.gg/jg33eMhnj6" +# Migration from docs to separate directory [[redirects]] from = "/docs/integrations/*" to = "/integrations/:splat" +# Docusaurus update removes index +[[redirects]] + from = "/docs/:firstPart/index" + to = "/docs/:firstPart/" + status = 301 + force = true +[[redirects]] + from = "/docs/:firstPart/:secondPart/index" + to = "/docs/:firstPart/:secondPart/" + status = 301 + force = true +[[redirects]] + from = "/integrations/:firstPart/index" + to = "/integrations/:firstPart/" + status = 301 + force = true +[[redirects]] + from = "/integrations/:firstPart/:secondPart/index" + to = "/integrations/:firstPart/:secondPart/" + status = 301 + force = true + +# ?go-get=1 downloads [[redirects]] from = "/*" to = "/.netlify/functions/go-get" @@ -13,6 +37,7 @@ force = true query = {go-get = "1"} +# Container registry [[redirects]] from = "/v2" to = "/.netlify/functions/oci-proxy" diff --git a/website/src/pages/index.jsx b/website/src/pages/index.jsx index b4b61c1c11..8cc7fbe38d 100644 --- a/website/src/pages/index.jsx +++ b/website/src/pages/index.jsx @@ -80,7 +80,7 @@ function Home() { "button button--outline button--secondary button--lg", styles.getStarted )} - to={useBaseUrl("docs/installation/index")} + to={useBaseUrl("docs/installation/")} > Get Started