Compare commits
81 Commits
version/20
...
version/20
| Author | SHA1 | Date | |
|---|---|---|---|
| 31a58e2c25 | |||
| 229715acb2 | |||
| 2a670afd02 | |||
| b69248dd55 | |||
| 5ff5edf769 | |||
| 939889e0ec | |||
| 19ae6585dc | |||
| a81c847392 | |||
| c6ede78fba | |||
| cea1289186 | |||
| c297f28552 | |||
| 35b25bd76e | |||
| 64d7610b13 | |||
| 2c8fcff832 | |||
| 054e76d02a | |||
| 80fa132dd9 | |||
| 4c59c3abef | |||
| 22d319c0e7 | |||
| 89edd77484 | |||
| 04e52d8ba6 | |||
| 9b5e3921cb | |||
| 2bbad64dc3 | |||
| f6026fdb13 | |||
| 49def45ca3 | |||
| a4856969f4 | |||
| 2aa7266688 | |||
| 25817cae6b | |||
| 5383ae2c19 | |||
| c0c246edab | |||
| 831b32c279 | |||
| 70ccc63702 | |||
| de954250e5 | |||
| f268bd4c69 | |||
| 57a48b6350 | |||
| 9aac114115 | |||
| 66e3cbdc46 | |||
| 2d76d23f7b | |||
| 4327b35bc3 | |||
| f7047df40e | |||
| ef77a4b64e | |||
| 5d7d21076f | |||
| ede072889e | |||
| 9cb7e6c606 | |||
| e7d36c095d | |||
| b88eb430c1 | |||
| 641872a33a | |||
| 405c690193 | |||
| 932cf48d2b | |||
| 402819107d | |||
| 41f135126b | |||
| 591a339302 | |||
| 35f2c5d96a | |||
| fe6963c428 | |||
| 19cac4bf43 | |||
| 4ca564490e | |||
| fcb795c273 | |||
| 14c70b3e4a | |||
| ac880c28d7 | |||
| f3c6b9a4f6 | |||
| cba0cf0d76 | |||
| 73b67cf0f0 | |||
| 23a8052cc8 | |||
| 57c49c3865 | |||
| cbea51ae5b | |||
| 8962081d92 | |||
| e743f13f81 | |||
| b20a8b7c17 | |||
| b53c94d76a | |||
| d4419d66c1 | |||
| 79044368d2 | |||
| 426686957d | |||
| 28cb803fd9 | |||
| 85c3a36b62 | |||
| 9ba8a715b1 | |||
| 358750f66e | |||
| b9918529b8 | |||
| a5673b4ec8 | |||
| d9287d0c0e | |||
| d9c2b64116 | |||
| 2b150d3077 | |||
| dec7a9cfb9 |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 2021.6.1-rc6
|
||||
current_version = 2021.6.2
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
|
||||
|
||||
1
.github/stale.yml
vendored
@ -6,6 +6,7 @@ daysUntilClose: 7
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- pr_wanted
|
||||
# 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
|
||||
|
||||
79
.github/workflows/release.yml
vendored
@ -33,22 +33,21 @@ jobs:
|
||||
with:
|
||||
push: ${{ github.event_name == 'release' }}
|
||||
tags: |
|
||||
beryju/authentik:2021.6.1-rc6,
|
||||
beryju/authentik:2021.6.2,
|
||||
beryju/authentik:latest,
|
||||
ghcr.io/goauthentik/server:2021.6.1-rc6,
|
||||
ghcr.io/goauthentik/server:2021.6.2,
|
||||
ghcr.io/goauthentik/server:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
- name: Building Docker Image (stable)
|
||||
uses: docker/build-push-action@v2
|
||||
if: ${{ github.event_name == 'release' && !contains('2021.6.1-rc6', 'rc') }}
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
beryju/authentik:stable,
|
||||
ghcr.io/goauthentik/server:stable
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
if: ${{ github.event_name == 'release' && !contains('2021.6.2', 'rc') }}
|
||||
run: |
|
||||
docker pull beryju/authentik:latest
|
||||
docker tag beryju/authentik:latest beryju/authentik:stable
|
||||
docker push beryju/authentik:stable
|
||||
docker pull ghcr.io/goauthentik/server:latest
|
||||
docker tag ghcr.io/goauthentik/server:latest ghcr.io/goauthentik/server:stable
|
||||
docker push ghcr.io/goauthentik/server:stable
|
||||
build-proxy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -76,22 +75,21 @@ jobs:
|
||||
with:
|
||||
push: ${{ github.event_name == 'release' }}
|
||||
tags: |
|
||||
beryju/authentik-proxy:2021.6.1-rc6,
|
||||
beryju/authentik-proxy:2021.6.2,
|
||||
beryju/authentik-proxy:latest,
|
||||
ghcr.io/goauthentik/proxy:2021.6.1-rc6,
|
||||
ghcr.io/goauthentik/proxy:2021.6.2,
|
||||
ghcr.io/goauthentik/proxy:latest
|
||||
file: outpost/proxy.Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
- name: Building Docker Image (stable)
|
||||
uses: docker/build-push-action@v2
|
||||
if: ${{ github.event_name == 'release' && !contains('2021.6.1-rc6', 'rc') }}
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
beryju/authentik-proxy:stable,
|
||||
ghcr.io/goauthentik/proxy:stable
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
if: ${{ github.event_name == 'release' && !contains('2021.6.2', 'rc') }}
|
||||
run: |
|
||||
docker pull beryju/authentik-proxy:latest
|
||||
docker tag beryju/authentik-proxy:latest beryju/authentik-proxy:stable
|
||||
docker push beryju/authentik-proxy:stable
|
||||
docker pull ghcr.io/goauthentik/proxy:latest
|
||||
docker tag ghcr.io/goauthentik/proxy:latest ghcr.io/goauthentik/proxy:stable
|
||||
docker push ghcr.io/goauthentik/proxy:stable
|
||||
build-ldap:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -119,24 +117,22 @@ jobs:
|
||||
with:
|
||||
push: ${{ github.event_name == 'release' }}
|
||||
tags: |
|
||||
beryju/authentik-ldap:2021.6.1-rc6,
|
||||
beryju/authentik-ldap:2021.6.2,
|
||||
beryju/authentik-ldap:latest,
|
||||
ghcr.io/goauthentik/ldap:2021.6.1-rc6,
|
||||
ghcr.io/goauthentik/ldap:2021.6.2,
|
||||
ghcr.io/goauthentik/ldap:latest
|
||||
file: outpost/ldap.Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
- name: Building Docker Image (stable)
|
||||
uses: docker/build-push-action@v2
|
||||
if: ${{ github.event_name == 'release' && !contains('2021.6.1-rc6', 'rc') }}
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
beryju/authentik-ldap:stable,
|
||||
ghcr.io/goauthentik/ldap:stable
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
if: ${{ github.event_name == 'release' && !contains('2021.6.2', 'rc') }}
|
||||
run: |
|
||||
docker pull beryju/authentik-ldap:latest
|
||||
docker tag beryju/authentik-ldap:latest beryju/authentik-ldap:stable
|
||||
docker push beryju/authentik-ldap:stable
|
||||
docker pull ghcr.io/goauthentik/ldap:latest
|
||||
docker tag ghcr.io/goauthentik/ldap:latest ghcr.io/goauthentik/ldap:stable
|
||||
docker push ghcr.io/goauthentik/ldap:stable
|
||||
test-release:
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
needs:
|
||||
- build-server
|
||||
- build-proxy
|
||||
@ -160,13 +156,26 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v2.1.5
|
||||
with:
|
||||
node-version: 12.x
|
||||
- name: Build web api client and web ui
|
||||
run: |
|
||||
export NODE_ENV=production
|
||||
make gen-web
|
||||
cd web
|
||||
npm i
|
||||
npm run build
|
||||
- name: Create a Sentry.io release
|
||||
uses: getsentry/action-release@v1
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: beryjuorg
|
||||
SENTRY_PROJECT: authentik
|
||||
SENTRY_URL: https://sentry.beryju.org
|
||||
with:
|
||||
version: authentik@2021.6.1-rc6
|
||||
version: authentik@2021.6.2
|
||||
environment: beryjuorg-prod
|
||||
sourcemaps: './web/dist'
|
||||
|
||||
1
Pipfile
@ -46,6 +46,7 @@ webauthn = "*"
|
||||
xmlsec = "*"
|
||||
duo-client = "*"
|
||||
ua-parser = "*"
|
||||
deepmerge = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
||||
|
||||
134
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "4fa1ad681762c867a95410074f31ac5d00119e187e0f38982cd59fdf301cccf5"
|
||||
"sha256": "f90d9fb4713eaf9c5ffe6a3858e64843670f79ab5007e7debf914c1f094c8d63"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@ -122,19 +122,19 @@
|
||||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:6180272094030bda3ee5c242881892cd3d9d19c05cb513945f530e396c7de1e4",
|
||||
"sha256:95d814d16fe55ae55e1e4a3db248596f9647a0c42f4796c6e05be0bfaffb1830"
|
||||
"sha256:2c2f70608934b03f9c08f4cd185de223b5abd18245dd4d4800e1fbc2a2523e31",
|
||||
"sha256:fccfa81cda69bb2317ed97e7149d7d84d19e6ec3bfbe3f721139e7ac0c407c73"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.17.94"
|
||||
"version": "==1.17.98"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:60a382a5b2f7d77b1b575d54fba819097526e3fdd0f3004f4d1142d50af0d642",
|
||||
"sha256:ba8a7951be535e25219a82dea15c30d7bdf0c51e7c1623c3306248493c1616ac"
|
||||
"sha256:b2a49de4ee04b690142c8e7240f0f5758e3f7673dd39cf398efe893bf5e11c3f",
|
||||
"sha256:b955b23fe2fbdbbc8e66f37fe2970de6b5d8169f940b200bcf434751709d38f6"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||
"version": "==1.20.94"
|
||||
"version": "==1.20.98"
|
||||
},
|
||||
"cachetools": {
|
||||
"hashes": [
|
||||
@ -165,11 +165,11 @@
|
||||
},
|
||||
"celery": {
|
||||
"hashes": [
|
||||
"sha256:1329de1edeaf734ef859e630cb42df2c116d53e59d2f46433b13aed196e85620",
|
||||
"sha256:65f061c04578cf189cd7352c192e1a79fdeb370b916bff792bcc769560e81184"
|
||||
"sha256:54436cd97b031bf2e08064223240e2a83d601d9414bcb1b702f94c6c33c29485",
|
||||
"sha256:b5399d76cf70d5cfac3ec993f8796ec1aa90d4cef55972295751f384758a80d7"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.1.0"
|
||||
"version": "==5.1.1"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
@ -324,6 +324,14 @@
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.2"
|
||||
},
|
||||
"deepmerge": {
|
||||
"hashes": [
|
||||
"sha256:87166dbe9ba1a3348a45c9d4ada6778f518d41afc0b85aa017ea3041facc3f9c",
|
||||
"sha256:f6fd7f1293c535fb599e197e750dbe8674503c5d2a89759b3c72a3c46746d4fd"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.3.0"
|
||||
},
|
||||
"defusedxml": {
|
||||
"hashes": [
|
||||
"sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69",
|
||||
@ -426,11 +434,11 @@
|
||||
},
|
||||
"drf-spectacular": {
|
||||
"hashes": [
|
||||
"sha256:146e8c21dc806a20c84c687811c30163970fbf620213ab87280f7403469d80bb",
|
||||
"sha256:8a028d251a6d0b39739ebdec487fd43ee4ecba244d8ffaaac43ff06430728dd8"
|
||||
"sha256:6ffbfde7d96a4a2febd19182cc405217e1e86a50280fc739402291c93d1a32b7",
|
||||
"sha256:77593024bb899f69227abedcf87def7851a11c9978f781aa4b385a10f67a38b7"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.17.1"
|
||||
"version": "==0.17.2"
|
||||
},
|
||||
"duo-client": {
|
||||
"hashes": [
|
||||
@ -465,11 +473,11 @@
|
||||
},
|
||||
"google-auth": {
|
||||
"hashes": [
|
||||
"sha256:154f7889c5d679a6f626f36adb12afbd4dbb0a9a04ec575d989d6ba79c4fd65e",
|
||||
"sha256:6d47c79b5d09fbc7e8355fd9594cc4cf65fdde5d401c63951eaac4baa1ba2ae1"
|
||||
"sha256:b3a67fa9ba5b768861dacf374c2135eb09fa14a0e40c851c3b8ea7abe6fc8fef",
|
||||
"sha256:e34e5f5de5610b202f9b40ebd9f8b27571d5c5537db9afed3a72b2db5a345039"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||
"version": "==1.31.0"
|
||||
"version": "==1.32.0"
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
@ -786,52 +794,46 @@
|
||||
},
|
||||
"prompt-toolkit": {
|
||||
"hashes": [
|
||||
"sha256:bf00f22079f5fadc949f42ae8ff7f05702826a97059ffcc6281036ad40ac6f04",
|
||||
"sha256:e1b4f11b9336a28fa11810bc623c357420f69dfdb6d2dac41ca2c21a55c033bc"
|
||||
"sha256:08360ee3a3148bdb5163621709ee322ec34fc4375099afa4bbf751e9b7b7fa4f",
|
||||
"sha256:7089d8d2938043508aa9420ec18ce0922885304cddae87fb96eebca942299f88"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.1'",
|
||||
"version": "==3.0.18"
|
||||
"version": "==3.0.19"
|
||||
},
|
||||
"psycopg2-binary": {
|
||||
"hashes": [
|
||||
"sha256:0deac2af1a587ae12836aa07970f5cb91964f05a7c6cdb69d8425ff4c15d4e2c",
|
||||
"sha256:0e4dc3d5996760104746e6cfcdb519d9d2cd27c738296525d5867ea695774e67",
|
||||
"sha256:11b9c0ebce097180129e422379b824ae21c8f2a6596b159c7659e2e5a00e1aa0",
|
||||
"sha256:15978a1fbd225583dd8cdaf37e67ccc278b5abecb4caf6b2d6b8e2b948e953f6",
|
||||
"sha256:1fabed9ea2acc4efe4671b92c669a213db744d2af8a9fc5d69a8e9bc14b7a9db",
|
||||
"sha256:2dac98e85565d5688e8ab7bdea5446674a83a3945a8f416ad0110018d1501b94",
|
||||
"sha256:42ec1035841b389e8cc3692277a0bd81cdfe0b65d575a2c8862cec7a80e62e52",
|
||||
"sha256:6422f2ff0919fd720195f64ffd8f924c1395d30f9a495f31e2392c2efafb5056",
|
||||
"sha256:6a32f3a4cb2f6e1a0b15215f448e8ce2da192fd4ff35084d80d5e39da683e79b",
|
||||
"sha256:7312e931b90fe14f925729cde58022f5d034241918a5c4f9797cac62f6b3a9dd",
|
||||
"sha256:7d92a09b788cbb1aec325af5fcba9fed7203897bbd9269d5691bb1e3bce29550",
|
||||
"sha256:833709a5c66ca52f1d21d41865a637223b368c0ee76ea54ca5bad6f2526c7679",
|
||||
"sha256:89705f45ce07b2dfa806ee84439ec67c5d9a0ef20154e0e475e2b2ed392a5b83",
|
||||
"sha256:8cd0fb36c7412996859cb4606a35969dd01f4ea34d9812a141cd920c3b18be77",
|
||||
"sha256:950bc22bb56ee6ff142a2cb9ee980b571dd0912b0334aa3fe0fe3788d860bea2",
|
||||
"sha256:a0c50db33c32594305b0ef9abc0cb7db13de7621d2cadf8392a1d9b3c437ef77",
|
||||
"sha256:a0eb43a07386c3f1f1ebb4dc7aafb13f67188eab896e7397aa1ee95a9c884eb2",
|
||||
"sha256:aaa4213c862f0ef00022751161df35804127b78adf4a2755b9f991a507e425fd",
|
||||
"sha256:ac0c682111fbf404525dfc0f18a8b5f11be52657d4f96e9fcb75daf4f3984859",
|
||||
"sha256:ad20d2eb875aaa1ea6d0f2916949f5c08a19c74d05b16ce6ebf6d24f2c9f75d1",
|
||||
"sha256:b4afc542c0ac0db720cf516dd20c0846f71c248d2b3d21013aa0d4ef9c71ca25",
|
||||
"sha256:b8a3715b3c4e604bcc94c90a825cd7f5635417453b253499664f784fc4da0152",
|
||||
"sha256:ba28584e6bca48c59eecbf7efb1576ca214b47f05194646b081717fa628dfddf",
|
||||
"sha256:ba381aec3a5dc29634f20692349d73f2d21f17653bda1decf0b52b11d694541f",
|
||||
"sha256:bd1be66dde2b82f80afb9459fc618216753f67109b859a361cf7def5c7968729",
|
||||
"sha256:c2507d796fca339c8fb03216364cca68d87e037c1f774977c8fc377627d01c71",
|
||||
"sha256:cec7e622ebc545dbb4564e483dd20e4e404da17ae07e06f3e780b2dacd5cee66",
|
||||
"sha256:d14b140a4439d816e3b1229a4a525df917d6ea22a0771a2a78332273fd9528a4",
|
||||
"sha256:d1b4ab59e02d9008efe10ceabd0b31e79519da6fb67f7d8e8977118832d0f449",
|
||||
"sha256:d5227b229005a696cc67676e24c214740efd90b148de5733419ac9aaba3773da",
|
||||
"sha256:e1f57aa70d3f7cc6947fd88636a481638263ba04a742b4a37dd25c373e41491a",
|
||||
"sha256:e74a55f6bad0e7d3968399deb50f61f4db1926acf4a6d83beaaa7df986f48b1c",
|
||||
"sha256:e82aba2188b9ba309fd8e271702bd0d0fc9148ae3150532bbb474f4590039ffb",
|
||||
"sha256:ee69dad2c7155756ad114c02db06002f4cded41132cc51378e57aad79cc8e4f4",
|
||||
"sha256:f5ab93a2cb2d8338b1674be43b442a7f544a0971da062a5da774ed40587f18f5"
|
||||
"sha256:0b7dae87f0b729922e06f85f667de7bf16455d411971b2043bbd9577af9d1975",
|
||||
"sha256:0f2e04bd2a2ab54fa44ee67fe2d002bb90cee1c0f1cc0ebc3148af7b02034cbd",
|
||||
"sha256:123c3fb684e9abfc47218d3784c7b4c47c8587951ea4dd5bc38b6636ac57f616",
|
||||
"sha256:1473c0215b0613dd938db54a653f68251a45a78b05f6fc21af4326f40e8360a2",
|
||||
"sha256:14db1752acdd2187d99cb2ca0a1a6dfe57fc65c3281e0f20e597aac8d2a5bd90",
|
||||
"sha256:1e3a362790edc0a365385b1ac4cc0acc429a0c0d662d829a50b6ce743ae61b5a",
|
||||
"sha256:1e85b74cbbb3056e3656f1cc4781294df03383127a8114cbc6531e8b8367bf1e",
|
||||
"sha256:20f1ab44d8c352074e2d7ca67dc00843067788791be373e67a0911998787ce7d",
|
||||
"sha256:2f62c207d1740b0bde5c4e949f857b044818f734a3d57f1d0d0edc65050532ed",
|
||||
"sha256:3242b9619de955ab44581a03a64bdd7d5e470cc4183e8fcadd85ab9d3756ce7a",
|
||||
"sha256:35c4310f8febe41f442d3c65066ca93cccefd75013df3d8c736c5b93ec288140",
|
||||
"sha256:4235f9d5ddcab0b8dbd723dca56ea2922b485ea00e1dafacf33b0c7e840b3d32",
|
||||
"sha256:5ced67f1e34e1a450cdb48eb53ca73b60aa0af21c46b9b35ac3e581cf9f00e31",
|
||||
"sha256:7360647ea04db2e7dff1648d1da825c8cf68dc5fbd80b8fb5b3ee9f068dcd21a",
|
||||
"sha256:8c13d72ed6af7fd2c8acbd95661cf9477f94e381fce0792c04981a8283b52917",
|
||||
"sha256:988b47ac70d204aed01589ed342303da7c4d84b56c2f4c4b8b00deda123372bf",
|
||||
"sha256:995fc41ebda5a7a663a254a1dcac52638c3e847f48307b5416ee373da15075d7",
|
||||
"sha256:a36c7eb6152ba5467fb264d73844877be8b0847874d4822b7cf2d3c0cb8cdcb0",
|
||||
"sha256:aed4a9a7e3221b3e252c39d0bf794c438dc5453bc2963e8befe9d4cd324dff72",
|
||||
"sha256:aef9aee84ec78af51107181d02fe8773b100b01c5dfde351184ad9223eab3698",
|
||||
"sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773",
|
||||
"sha256:b4d7679a08fea64573c969f6994a2631908bb2c0e69a7235648642f3d2e39a68",
|
||||
"sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76",
|
||||
"sha256:ca86db5b561b894f9e5f115d6a159fff2a2570a652e07889d8a383b5fae66eb4",
|
||||
"sha256:cfc523edecddaef56f6740d7de1ce24a2fdf94fd5e704091856a201872e37f9f",
|
||||
"sha256:da113b70f6ec40e7d81b43d1b139b9db6a05727ab8be1ee559f3a69854a69d34",
|
||||
"sha256:f6fac64a38f6768e7bc7b035b9e10d8a538a9fadce06b983fb3e6fa55ac5f5ce",
|
||||
"sha256:f8559617b1fcf59a9aedba2c9838b5b6aa211ffedecabca412b92a1ff75aac1a",
|
||||
"sha256:fbb42a541b1093385a2d8c7eec94d26d30437d0e77c1d25dae1dcc46741a385e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.8.6"
|
||||
"version": "==2.9.1"
|
||||
},
|
||||
"pyasn1": {
|
||||
"hashes": [
|
||||
@ -961,10 +963,10 @@
|
||||
},
|
||||
"python-dotenv": {
|
||||
"hashes": [
|
||||
"sha256:00aa34e92d992e9f8383730816359647f358f4a3be1ba45e5a5cefd27ee91544",
|
||||
"sha256:b1ae5e9643d5ed987fc57cc2583021e38db531946518130777734f9589b3141f"
|
||||
"sha256:dd8fe852847f4fbfadabf6183ddd4c824a9651f02d51714fa075c95561959c7d",
|
||||
"sha256:effaac3c1e58d89b3ccb4d04a40dc7ad6e0275fda25fd75ae9d323e2465e202d"
|
||||
],
|
||||
"version": "==0.17.1"
|
||||
"version": "==0.18.0"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
@ -1538,11 +1540,11 @@
|
||||
},
|
||||
"gitpython": {
|
||||
"hashes": [
|
||||
"sha256:29fe82050709760081f588dd50ce83504feddbebdc4da6956d02351552b1c135",
|
||||
"sha256:ee24bdc93dce357630764db659edaf6b8d664d4ff5447ccfeedd2dc5c253f41e"
|
||||
"sha256:b838a895977b45ab6f0cc926a9045c8d1c44e2b653c1fcc39fe91f42c6e8f05b",
|
||||
"sha256:fce760879cd2aebd2991b3542876dc5c4a909b30c9d69dfc488e504a8db37ee8"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==3.1.17"
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.1.18"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
@ -1560,11 +1562,11 @@
|
||||
},
|
||||
"isort": {
|
||||
"hashes": [
|
||||
"sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6",
|
||||
"sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"
|
||||
"sha256:83510593e07e433b77bd5bff0f6f607dbafa06d1a89022616f02d8b699cfcd56",
|
||||
"sha256:8e2c107091cfec7286bc0f68a547d0ba4c094d460b732075b6fba674f1035c0c"
|
||||
],
|
||||
"markers": "python_version >= '3.6' and python_version < '4'",
|
||||
"version": "==5.8.0"
|
||||
"markers": "python_version < '4.0' and python_full_version >= '3.6.1'",
|
||||
"version": "==5.9.1"
|
||||
},
|
||||
"lazy-object-proxy": {
|
||||
"hashes": [
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
"""authentik"""
|
||||
__version__ = "2021.6.1-rc6"
|
||||
__version__ = "2021.6.2"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
@ -3,23 +3,33 @@ from traceback import format_tb
|
||||
from typing import Optional
|
||||
|
||||
from django.http import HttpRequest
|
||||
from guardian.utils import get_anonymous_user
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.core.models import PropertyMapping, User
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.expression.evaluator import BaseEvaluator
|
||||
from authentik.policies.types import PolicyRequest
|
||||
|
||||
|
||||
class PropertyMappingEvaluator(BaseEvaluator):
|
||||
"""Custom Evalautor that adds some different context variables."""
|
||||
|
||||
def set_context(
|
||||
self, user: Optional[User], request: Optional[HttpRequest], **kwargs
|
||||
self,
|
||||
user: Optional[User],
|
||||
request: Optional[HttpRequest],
|
||||
mapping: PropertyMapping,
|
||||
**kwargs,
|
||||
):
|
||||
"""Update context with context from PropertyMapping's evaluate"""
|
||||
req = PolicyRequest(user=get_anonymous_user())
|
||||
req.obj = mapping
|
||||
if user:
|
||||
req.user = user
|
||||
self._context["user"] = user
|
||||
if request:
|
||||
self._context["request"] = request
|
||||
req.http_request = request
|
||||
self._context["request"] = req
|
||||
self._context.update(**kwargs)
|
||||
|
||||
def handle_error(self, exc: Exception, expression_source: str):
|
||||
@ -30,9 +40,8 @@ class PropertyMappingEvaluator(BaseEvaluator):
|
||||
expression=expression_source,
|
||||
message=error_string,
|
||||
)
|
||||
if "user" in self._context:
|
||||
event.set_user(self._context["user"])
|
||||
if "request" in self._context:
|
||||
event.from_http(self._context["request"])
|
||||
req: PolicyRequest = self._context["request"]
|
||||
event.from_http(req.http_request, req.user)
|
||||
return
|
||||
event.save()
|
||||
|
||||
@ -6,6 +6,7 @@ from urllib.parse import urlencode
|
||||
from uuid import uuid4
|
||||
|
||||
import django.db.models.options as options
|
||||
from deepmerge import always_merger
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.contrib.auth.models import UserManager as DjangoUserManager
|
||||
@ -114,8 +115,8 @@ class User(GuardianUserMixin, AbstractUser):
|
||||
including the users attributes"""
|
||||
final_attributes = {}
|
||||
for group in self.ak_groups.all().order_by("name"):
|
||||
final_attributes.update(group.attributes)
|
||||
final_attributes.update(self.attributes)
|
||||
always_merger.merge(final_attributes, group.attributes)
|
||||
always_merger.merge(final_attributes, self.attributes)
|
||||
return final_attributes
|
||||
|
||||
@cached_property
|
||||
@ -142,21 +143,25 @@ class User(GuardianUserMixin, AbstractUser):
|
||||
@property
|
||||
def avatar(self) -> str:
|
||||
"""Get avatar, depending on authentik.avatar setting"""
|
||||
mode = CONFIG.raw.get("authentik").get("avatars")
|
||||
mode: str = CONFIG.y("avatars", "none")
|
||||
if mode == "none":
|
||||
return DEFAULT_AVATAR
|
||||
# gravatar uses md5 for their URLs, so md5 can't be avoided
|
||||
mail_hash = md5(self.email.encode("utf-8")).hexdigest() # nosec
|
||||
if mode == "gravatar":
|
||||
parameters = [
|
||||
("s", "158"),
|
||||
("r", "g"),
|
||||
]
|
||||
# gravatar uses md5 for their URLs, so md5 can't be avoided
|
||||
mail_hash = md5(self.email.encode("utf-8")).hexdigest() # nosec
|
||||
gravatar_url = (
|
||||
f"{GRAVATAR_URL}/avatar/{mail_hash}?{urlencode(parameters, doseq=True)}"
|
||||
)
|
||||
return escape(gravatar_url)
|
||||
raise ValueError(f"Invalid avatar mode {mode}")
|
||||
return mode % {
|
||||
"username": self.username,
|
||||
"mail_hash": mail_hash,
|
||||
"upn": self.attributes.get("upn", ""),
|
||||
}
|
||||
|
||||
class Meta:
|
||||
|
||||
@ -460,7 +465,7 @@ class PropertyMapping(SerializerModel, ManagedModel):
|
||||
from authentik.core.expression import PropertyMappingEvaluator
|
||||
|
||||
evaluator = PropertyMappingEvaluator()
|
||||
evaluator.set_context(user, request, **kwargs)
|
||||
evaluator.set_context(user, request, self, **kwargs)
|
||||
try:
|
||||
return evaluator.evaluate(self.expression)
|
||||
except (ValueError, SyntaxError) as exc:
|
||||
@ -494,8 +499,12 @@ class AuthenticatedSession(ExpiringModel):
|
||||
last_used = models.DateTimeField(auto_now=True)
|
||||
|
||||
@staticmethod
|
||||
def from_request(request: HttpRequest, user: User) -> "AuthenticatedSession":
|
||||
def from_request(
|
||||
request: HttpRequest, user: User
|
||||
) -> Optional["AuthenticatedSession"]:
|
||||
"""Create a new session from a http request"""
|
||||
if not hasattr(request, "session") or not request.session.session_key:
|
||||
return None
|
||||
return AuthenticatedSession(
|
||||
session_key=request.session.session_key,
|
||||
user=user,
|
||||
|
||||
@ -49,7 +49,9 @@ def user_logged_in_session(sender, request: HttpRequest, user: "User", **_):
|
||||
"""Create an AuthenticatedSession from request"""
|
||||
from authentik.core.models import AuthenticatedSession
|
||||
|
||||
AuthenticatedSession.from_request(request, user).save()
|
||||
session = AuthenticatedSession.from_request(request, user)
|
||||
if session:
|
||||
session.save()
|
||||
|
||||
|
||||
@receiver(user_logged_out)
|
||||
|
||||
@ -183,6 +183,8 @@ class SourceFlowManager:
|
||||
# pylint: disable=unused-argument
|
||||
def get_stages_to_append(self, flow: Flow) -> list[Stage]:
|
||||
"""Hook to override stages which are appended to the flow"""
|
||||
if not self.source.enrollment_flow:
|
||||
return []
|
||||
if flow.slug == self.source.enrollment_flow.slug:
|
||||
return [
|
||||
in_memory_stage(PostUserEnrollmentStage),
|
||||
|
||||
@ -11,6 +11,11 @@
|
||||
|
||||
{% block head %}
|
||||
<script src="{% static 'dist/FlowInterface.js' %}?v={{ ak_version }}" type="module"></script>
|
||||
<style>
|
||||
.pf-c-background-image::before {
|
||||
background-image: url("{{ flow.background_url }}");
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
@ -7,6 +7,14 @@
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}?v={{ ak_version }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.pf-c-background-image::before {
|
||||
background-image: url("/static/dist/assets/images/flow_background.jpg");
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="pf-c-background-image">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="pf-c-background-image__filter" width="0" height="0">
|
||||
|
||||
@ -55,11 +55,16 @@ class CertificateKeyPair(CreatedUpdatedModel):
|
||||
def private_key(self) -> Optional[RSAPrivateKey]:
|
||||
"""Get python cryptography PrivateKey instance"""
|
||||
if not self._private_key and self._private_key != "":
|
||||
self._private_key = load_pem_private_key(
|
||||
str.encode("\n".join([x.strip() for x in self.key_data.split("\n")])),
|
||||
password=None,
|
||||
backend=default_backend(),
|
||||
)
|
||||
try:
|
||||
self._private_key = load_pem_private_key(
|
||||
str.encode(
|
||||
"\n".join([x.strip() for x in self.key_data.split("\n")])
|
||||
),
|
||||
password=None,
|
||||
backend=default_backend(),
|
||||
)
|
||||
except ValueError:
|
||||
return None
|
||||
return self._private_key
|
||||
|
||||
@property
|
||||
|
||||
@ -14,6 +14,7 @@ from authentik.events.models import cleanse_dict
|
||||
from authentik.flows.exceptions import EmptyFlowException, FlowNonApplicableException
|
||||
from authentik.flows.markers import ReevaluateMarker, StageMarker
|
||||
from authentik.flows.models import Flow, FlowStageBinding, Stage
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.policies.engine import PolicyEngine
|
||||
from authentik.root.monitoring import UpdatingGauge
|
||||
|
||||
@ -33,6 +34,7 @@ HIST_FLOWS_PLAN_TIME = Histogram(
|
||||
"Duration to build a plan for a flow",
|
||||
["flow_slug"],
|
||||
)
|
||||
CACHE_TIMEOUT = int(CONFIG.y("redis.cache_timeout_flows"))
|
||||
|
||||
|
||||
def cache_key(flow: Flow, user: Optional[User] = None) -> str:
|
||||
@ -157,7 +159,7 @@ class FlowPlanner:
|
||||
"f(plan): building plan",
|
||||
)
|
||||
plan = self._build_plan(user, request, default_context)
|
||||
cache.set(cache_key(self.flow, user), plan)
|
||||
cache.set(cache_key(self.flow, user), plan, CACHE_TIMEOUT)
|
||||
GAUGE_FLOWS_CACHED.update()
|
||||
if not plan.stages and not self.allow_empty_flows:
|
||||
raise EmptyFlowException()
|
||||
|
||||
@ -18,27 +18,11 @@ from authentik.flows.challenge import (
|
||||
)
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.flows.views import FlowExecutorView
|
||||
from authentik.lib.sentry import SentryIgnoredException
|
||||
|
||||
PLAN_CONTEXT_PENDING_USER_IDENTIFIER = "pending_user_identifier"
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
class InvalidChallengeError(SentryIgnoredException):
|
||||
"""Error raised when a challenge from a stage is not valid"""
|
||||
|
||||
def __init__(self, errors, stage_view: View, challenge: Challenge) -> None:
|
||||
super().__init__()
|
||||
self.errors = errors
|
||||
self.stage_view = stage_view
|
||||
self.challenge = challenge
|
||||
|
||||
def __str__(self) -> str:
|
||||
return (
|
||||
f"Invalid challenge from {self.stage_view}: {self.errors}\n{self.challenge}"
|
||||
)
|
||||
|
||||
|
||||
class StageView(View):
|
||||
"""Abstract Stage, inherits TemplateView but can be combined with FormView"""
|
||||
|
||||
|
||||
@ -44,6 +44,7 @@ from authentik.flows.planner import (
|
||||
FlowPlan,
|
||||
FlowPlanner,
|
||||
)
|
||||
from authentik.lib.sentry import SentryIgnoredException
|
||||
from authentik.lib.utils.reflection import all_subclasses, class_to_path
|
||||
from authentik.lib.utils.urls import is_url_absolute, redirect_with_qs
|
||||
from authentik.tenants.models import Tenant
|
||||
@ -93,6 +94,10 @@ def challenge_response_types():
|
||||
return Inner()
|
||||
|
||||
|
||||
class InvalidStageError(SentryIgnoredException):
|
||||
"""Error raised when a challenge from a stage is not valid"""
|
||||
|
||||
|
||||
@method_decorator(xframe_options_sameorigin, name="dispatch")
|
||||
class FlowExecutorView(APIView):
|
||||
"""Stage 1 Flow executor, passing requests to Stage Views"""
|
||||
@ -164,12 +169,19 @@ class FlowExecutorView(APIView):
|
||||
current_stage=self.current_stage,
|
||||
flow_slug=self.flow.slug,
|
||||
)
|
||||
stage_cls = self.current_stage.type
|
||||
try:
|
||||
stage_cls = self.current_stage.type
|
||||
except NotImplementedError as exc:
|
||||
self._logger.debug("Error getting stage type", exc=exc)
|
||||
return self.stage_invalid()
|
||||
self.current_stage_view = stage_cls(self)
|
||||
self.current_stage_view.args = self.args
|
||||
self.current_stage_view.kwargs = self.kwargs
|
||||
self.current_stage_view.request = request
|
||||
return super().dispatch(request)
|
||||
try:
|
||||
return super().dispatch(request)
|
||||
except InvalidStageError as exc:
|
||||
return self.stage_invalid(str(exc))
|
||||
|
||||
@extend_schema(
|
||||
responses={
|
||||
@ -353,8 +365,11 @@ class FlowErrorResponse(TemplateResponse):
|
||||
context = {}
|
||||
context["error"] = self.error
|
||||
if self._request.user and self._request.user.is_authenticated:
|
||||
if self._request.user.is_superuser or self._request.user.attributes.get(
|
||||
USER_ATTRIBUTE_DEBUG, False
|
||||
if (
|
||||
self._request.user.is_superuser
|
||||
or self._request.user.group_attributes().get(
|
||||
USER_ATTRIBUTE_DEBUG, False
|
||||
)
|
||||
):
|
||||
context["tb"] = "".join(format_tb(self.error.__traceback__))
|
||||
return context
|
||||
|
||||
@ -62,7 +62,7 @@ class ConfigLoader:
|
||||
output.update(kwargs)
|
||||
print(dumps(output))
|
||||
|
||||
def update(self, root, updatee):
|
||||
def update(self, root: dict[str, Any], updatee: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Recursively update dictionary"""
|
||||
for key, value in updatee.items():
|
||||
if isinstance(value, Mapping):
|
||||
@ -73,7 +73,7 @@ class ConfigLoader:
|
||||
root[key] = value
|
||||
return root
|
||||
|
||||
def parse_uri(self, value):
|
||||
def parse_uri(self, value: str) -> str:
|
||||
"""Parse string values which start with a URI"""
|
||||
url = urlparse(value)
|
||||
if url.scheme == "env":
|
||||
@ -99,7 +99,10 @@ class ConfigLoader:
|
||||
raise ImproperlyConfigured from exc
|
||||
except PermissionError as exc:
|
||||
self._log(
|
||||
"warning", "Permission denied while reading file", path=path, error=exc
|
||||
"warning",
|
||||
"Permission denied while reading file",
|
||||
path=path,
|
||||
error=str(exc),
|
||||
)
|
||||
|
||||
def update_from_dict(self, update: dict):
|
||||
|
||||
@ -9,6 +9,7 @@ postgresql:
|
||||
web:
|
||||
listen: 0.0.0.0:9000
|
||||
listen_tls: 0.0.0.0:9443
|
||||
load_local_files: false
|
||||
|
||||
redis:
|
||||
host: localhost
|
||||
@ -16,6 +17,10 @@ redis:
|
||||
cache_db: 0
|
||||
message_queue_db: 1
|
||||
ws_db: 2
|
||||
cache_timeout: 300
|
||||
cache_timeout_flows: 300
|
||||
cache_timeout_policies: 300
|
||||
cache_timeout_reputation: 300
|
||||
|
||||
debug: false
|
||||
|
||||
@ -45,12 +50,12 @@ outposts:
|
||||
# %(build_hash)s: Build hash if you're running a beta version
|
||||
docker_image_base: "ghcr.io/goauthentik/%(type)s:%(version)s"
|
||||
|
||||
authentik:
|
||||
avatars: gravatar # gravatar or none
|
||||
geoip: "./GeoLite2-City.mmdb"
|
||||
# Optionally add links to the footer on the login page
|
||||
footer_links:
|
||||
- name: Documentation
|
||||
href: https://goauthentik.io/docs/
|
||||
- name: authentik Website
|
||||
href: https://goauthentik.io/
|
||||
avatars: env://AUTHENTIK_AUTHENTIK__AVATARS?gravatar
|
||||
geoip: "./GeoLite2-City.mmdb"
|
||||
|
||||
# Can't currently be configured via environment variables, only yaml
|
||||
footer_links:
|
||||
- name: Documentation
|
||||
href: https://goauthentik.io/docs/
|
||||
- name: authentik Website
|
||||
href: https://goauthentik.io/
|
||||
|
||||
61
authentik/lib/tests/test_config.py
Normal file
@ -0,0 +1,61 @@
|
||||
"""Test config loader"""
|
||||
from os import chmod, environ, unlink, write
|
||||
from tempfile import mkstemp
|
||||
|
||||
from django.conf import ImproperlyConfigured
|
||||
from django.test import TestCase
|
||||
|
||||
from authentik.lib.config import ENV_PREFIX, ConfigLoader
|
||||
|
||||
|
||||
class TestConfig(TestCase):
|
||||
"""Test config loader"""
|
||||
|
||||
def test_env(self):
|
||||
"""Test simple instance"""
|
||||
config = ConfigLoader()
|
||||
environ[ENV_PREFIX + "_test__test"] = "bar"
|
||||
config.update_from_env()
|
||||
self.assertEqual(config.y("test.test"), "bar")
|
||||
|
||||
def test_patch(self):
|
||||
"""Test patch decorator"""
|
||||
config = ConfigLoader()
|
||||
config.y_set("foo.bar", "bar")
|
||||
self.assertEqual(config.y("foo.bar"), "bar")
|
||||
with config.patch("foo.bar", "baz"):
|
||||
self.assertEqual(config.y("foo.bar"), "baz")
|
||||
self.assertEqual(config.y("foo.bar"), "bar")
|
||||
|
||||
def test_uri_env(self):
|
||||
"""Test URI parsing (environment)"""
|
||||
config = ConfigLoader()
|
||||
environ["foo"] = "bar"
|
||||
self.assertEqual(config.parse_uri("env://foo"), "bar")
|
||||
self.assertEqual(config.parse_uri("env://fo?bar"), "bar")
|
||||
|
||||
def test_uri_file(self):
|
||||
"""Test URI parsing (file load)"""
|
||||
config = ConfigLoader()
|
||||
file, file_name = mkstemp()
|
||||
write(file, "foo".encode())
|
||||
_, file2_name = mkstemp()
|
||||
chmod(file2_name, 0o000) # Remove all permissions so we can't read the file
|
||||
self.assertEqual(config.parse_uri(f"file://{file_name}"), "foo")
|
||||
self.assertEqual(config.parse_uri(f"file://{file2_name}?def"), "def")
|
||||
unlink(file_name)
|
||||
unlink(file2_name)
|
||||
|
||||
def test_file_update(self):
|
||||
"""Test update_from_file"""
|
||||
config = ConfigLoader()
|
||||
file, file_name = mkstemp()
|
||||
write(file, "{".encode())
|
||||
file2, file2_name = mkstemp()
|
||||
write(file2, "{".encode())
|
||||
chmod(file2_name, 0o000) # Remove all permissions so we can't read the file
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
config.update_from_file(file_name)
|
||||
config.update_from_file(file2_name)
|
||||
unlink(file_name)
|
||||
unlink(file2_name)
|
||||
@ -33,7 +33,7 @@ def _get_outpost_override_ip(request: HttpRequest) -> Optional[str]:
|
||||
return None
|
||||
if OUTPOST_REMOTE_IP_HEADER not in request.META:
|
||||
return None
|
||||
if request.user.attributes.get(USER_ATTRIBUTE_CAN_OVERRIDE_IP, False):
|
||||
if request.user.group_attributes().get(USER_ATTRIBUTE_CAN_OVERRIDE_IP, False):
|
||||
return None
|
||||
return request.META[OUTPOST_REMOTE_IP_HEADER]
|
||||
|
||||
|
||||
@ -67,11 +67,6 @@ class OutpostConsumer(AuthJsonConsumer):
|
||||
self.accept()
|
||||
self.outpost = outpost.first()
|
||||
self.last_uid = self.channel_name
|
||||
LOGGER.debug(
|
||||
"added outpost instace to cache",
|
||||
outpost=self.outpost,
|
||||
channel_name=self.channel_name,
|
||||
)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def disconnect(self, close_code):
|
||||
@ -108,6 +103,11 @@ class OutpostConsumer(AuthJsonConsumer):
|
||||
outpost=self.outpost.name,
|
||||
uid=self.last_uid,
|
||||
).inc()
|
||||
LOGGER.debug(
|
||||
"added outpost instace to cache",
|
||||
outpost=self.outpost,
|
||||
instance_uuid=self.last_uid,
|
||||
)
|
||||
self.first_msg = True
|
||||
|
||||
if msg.instruction == WebsocketMessageInstruction.HELLO:
|
||||
|
||||
@ -66,7 +66,7 @@ class DockerController(BaseController):
|
||||
"name": container_name,
|
||||
"detach": True,
|
||||
"ports": {
|
||||
f"{port.port}/{port.protocol.lower()}": port.inner_port or port.port
|
||||
f"{port.inner_port or port.port}/{port.protocol.lower()}": port.port
|
||||
for port in self.deployment_ports
|
||||
},
|
||||
"environment": self._get_env(),
|
||||
|
||||
@ -37,7 +37,9 @@ class AccessDeniedResponse(TemplateResponse):
|
||||
if self._request.user and self._request.user.is_authenticated:
|
||||
if (
|
||||
self._request.user.is_superuser
|
||||
or self._request.user.attributes.get(USER_ATTRIBUTE_DEBUG, False)
|
||||
or self._request.user.group_attributes().get(
|
||||
USER_ATTRIBUTE_DEBUG, False
|
||||
)
|
||||
):
|
||||
context["policy_result"] = self.policy_result
|
||||
return context
|
||||
|
||||
@ -10,6 +10,7 @@ from sentry_sdk.tracing import Span
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.utils.errors import exception_to_string
|
||||
from authentik.policies.exceptions import PolicyException
|
||||
from authentik.policies.models import PolicyBinding
|
||||
@ -18,6 +19,7 @@ from authentik.policies.types import PolicyRequest, PolicyResult
|
||||
LOGGER = get_logger()
|
||||
|
||||
FORK_CTX = get_context("fork")
|
||||
CACHE_TIMEOUT = int(CONFIG.y("redis.cache_timeout_policies"))
|
||||
PROCESS_CLASS = FORK_CTX.Process
|
||||
HIST_POLICIES_EXECUTION_TIME = Histogram(
|
||||
"authentik_policies_execution_time",
|
||||
@ -114,7 +116,7 @@ class PolicyProcess(PROCESS_CLASS):
|
||||
policy_result.source_binding = self.binding
|
||||
if not self.request.debug:
|
||||
key = cache_key(self.binding, self.request)
|
||||
cache.set(key, policy_result)
|
||||
cache.set(key, policy_result, CACHE_TIMEOUT)
|
||||
LOGGER.debug(
|
||||
"P_ENG(proc): finished and cached ",
|
||||
policy=self.binding.policy,
|
||||
|
||||
@ -5,6 +5,7 @@ from django.dispatch import receiver
|
||||
from django.http import HttpRequest
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.utils.http import get_client_ip
|
||||
from authentik.policies.reputation.models import (
|
||||
CACHE_KEY_IP_PREFIX,
|
||||
@ -13,6 +14,7 @@ from authentik.policies.reputation.models import (
|
||||
from authentik.stages.identification.signals import identification_failed
|
||||
|
||||
LOGGER = get_logger()
|
||||
CACHE_TIMEOUT = int(CONFIG.y("redis.cache_timeout_reputation"))
|
||||
|
||||
|
||||
def update_score(request: HttpRequest, username: str, amount: int):
|
||||
@ -20,10 +22,10 @@ def update_score(request: HttpRequest, username: str, amount: int):
|
||||
remote_ip = get_client_ip(request)
|
||||
|
||||
# We only update the cache here, as its faster than writing to the DB
|
||||
cache.get_or_set(CACHE_KEY_IP_PREFIX + remote_ip, 0)
|
||||
cache.get_or_set(CACHE_KEY_IP_PREFIX + remote_ip, 0, CACHE_TIMEOUT)
|
||||
cache.incr(CACHE_KEY_IP_PREFIX + remote_ip, amount)
|
||||
|
||||
cache.get_or_set(CACHE_KEY_USER_PREFIX + username, 0)
|
||||
cache.get_or_set(CACHE_KEY_USER_PREFIX + username, 0, CACHE_TIMEOUT)
|
||||
cache.incr(CACHE_KEY_USER_PREFIX + username, amount)
|
||||
|
||||
LOGGER.debug("Updated score", amount=amount, for_user=username, for_ip=remote_ip)
|
||||
|
||||
@ -105,6 +105,7 @@ class PolicyAccessView(AccessMixin, View):
|
||||
policy_engine = PolicyEngine(
|
||||
self.application, user or self.request.user, self.request
|
||||
)
|
||||
policy_engine.use_cache = False
|
||||
policy_engine.build()
|
||||
result = policy_engine.result
|
||||
LOGGER.debug(
|
||||
|
||||
@ -9,7 +9,7 @@ return {}
|
||||
"""
|
||||
SCOPE_EMAIL_EXPRESSION = """
|
||||
return {
|
||||
"email": user.email,
|
||||
"email": request.user.email,
|
||||
"email_verified": True
|
||||
}
|
||||
"""
|
||||
@ -17,14 +17,14 @@ SCOPE_PROFILE_EXPRESSION = """
|
||||
return {
|
||||
# Because authentik only saves the user's full name, and has no concept of first and last names,
|
||||
# the full name is used as given name.
|
||||
# You can override this behaviour in custom mappings, i.e. `user.name.split(" ")`
|
||||
"name": user.name,
|
||||
"given_name": user.name,
|
||||
# You can override this behaviour in custom mappings, i.e. `request.user.name.split(" ")`
|
||||
"name": request.user.name,
|
||||
"given_name": request.user.name,
|
||||
"family_name": "",
|
||||
"preferred_username": user.username,
|
||||
"nickname": user.username,
|
||||
"preferred_username": request.user.username,
|
||||
"nickname": request.user.username,
|
||||
# groups is not part of the official userinfo schema, but is a quasi-standard
|
||||
"groups": [group.name for group in user.ak_groups.all()],
|
||||
"groups": [group.name for group in request.user.ak_groups.all()],
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ SCOPE_AK_PROXY_EXPRESSION = """
|
||||
# which are used for example for the HTTP-Basic Authentication mapping.
|
||||
return {
|
||||
"ak_proxy": {
|
||||
"user_attributes": user.group_attributes()
|
||||
"user_attributes": request.user.group_attributes()
|
||||
}
|
||||
}"""
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ from authentik.managed.manager import EnsureExists, ObjectManager
|
||||
from authentik.providers.saml.models import SAMLPropertyMapping
|
||||
|
||||
GROUP_EXPRESSION = """
|
||||
for group in user.ak_groups.all():
|
||||
for group in request.user.ak_groups.all():
|
||||
yield group.name
|
||||
"""
|
||||
|
||||
@ -18,7 +18,7 @@ class SAMLProviderManager(ObjectManager):
|
||||
"goauthentik.io/providers/saml/upn",
|
||||
name="authentik default SAML Mapping: UPN",
|
||||
saml_name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn",
|
||||
expression="return user.attributes.get('upn', user.email)",
|
||||
expression="return request.user.attributes.get('upn', request.user.email)",
|
||||
friendly_name="",
|
||||
),
|
||||
EnsureExists(
|
||||
@ -26,7 +26,7 @@ class SAMLProviderManager(ObjectManager):
|
||||
"goauthentik.io/providers/saml/name",
|
||||
name="authentik default SAML Mapping: Name",
|
||||
saml_name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
|
||||
expression="return user.name",
|
||||
expression="return request.user.name",
|
||||
friendly_name="",
|
||||
),
|
||||
EnsureExists(
|
||||
@ -34,7 +34,7 @@ class SAMLProviderManager(ObjectManager):
|
||||
"goauthentik.io/providers/saml/email",
|
||||
name="authentik default SAML Mapping: Email",
|
||||
saml_name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
|
||||
expression="return user.email",
|
||||
expression="return request.user.email",
|
||||
friendly_name="",
|
||||
),
|
||||
EnsureExists(
|
||||
@ -42,7 +42,7 @@ class SAMLProviderManager(ObjectManager):
|
||||
"goauthentik.io/providers/saml/username",
|
||||
name="authentik default SAML Mapping: Username",
|
||||
saml_name="http://schemas.goauthentik.io/2021/02/saml/username",
|
||||
expression="return user.username",
|
||||
expression="return request.user.username",
|
||||
friendly_name="",
|
||||
),
|
||||
EnsureExists(
|
||||
@ -50,7 +50,7 @@ class SAMLProviderManager(ObjectManager):
|
||||
"goauthentik.io/providers/saml/uid",
|
||||
name="authentik default SAML Mapping: User ID",
|
||||
saml_name="http://schemas.goauthentik.io/2021/02/saml/uid",
|
||||
expression="return user.pk",
|
||||
expression="return request.user.pk",
|
||||
friendly_name="",
|
||||
),
|
||||
EnsureExists(
|
||||
@ -68,7 +68,7 @@ class SAMLProviderManager(ObjectManager):
|
||||
saml_name=(
|
||||
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"
|
||||
),
|
||||
expression="return user.username",
|
||||
expression="return request.user.username",
|
||||
friendly_name="",
|
||||
),
|
||||
]
|
||||
|
||||
@ -24,6 +24,7 @@ from authentik.sources.saml.processors.constants import (
|
||||
SAML_NAME_ID_FORMAT_EMAIL,
|
||||
SAML_NAME_ID_FORMAT_PERSISTENT,
|
||||
SAML_NAME_ID_FORMAT_TRANSIENT,
|
||||
SAML_NAME_ID_FORMAT_UNSPECIFIED,
|
||||
SAML_NAME_ID_FORMAT_WINDOWS,
|
||||
SAML_NAME_ID_FORMAT_X509,
|
||||
SIGN_ALGORITHM_TRANSFORM_MAP,
|
||||
@ -165,7 +166,10 @@ class AssertionProcessor:
|
||||
if name_id.attrib["Format"] == SAML_NAME_ID_FORMAT_EMAIL:
|
||||
name_id.text = self.http_request.user.email
|
||||
return name_id
|
||||
if name_id.attrib["Format"] == SAML_NAME_ID_FORMAT_PERSISTENT:
|
||||
if name_id.attrib["Format"] in [
|
||||
SAML_NAME_ID_FORMAT_PERSISTENT,
|
||||
SAML_NAME_ID_FORMAT_UNSPECIFIED,
|
||||
]:
|
||||
name_id.text = persistent
|
||||
return name_id
|
||||
if name_id.attrib["Format"] == SAML_NAME_ID_FORMAT_X509:
|
||||
@ -180,7 +184,7 @@ class AssertionProcessor:
|
||||
return name_id
|
||||
if name_id.attrib["Format"] == SAML_NAME_ID_FORMAT_TRANSIENT:
|
||||
# Use the hash of the user's session, which changes every session
|
||||
session_key: str = self.http_request.user.session.session_key
|
||||
session_key: str = self.http_request.session.session_key
|
||||
name_id.text = sha256(session_key.encode()).hexdigest()
|
||||
return name_id
|
||||
raise UnsupportedNameIDFormat(
|
||||
|
||||
@ -20,10 +20,11 @@ from authentik.sources.saml.processors.constants import (
|
||||
RSA_SHA256,
|
||||
RSA_SHA384,
|
||||
RSA_SHA512,
|
||||
SAML_NAME_ID_FORMAT_EMAIL,
|
||||
SAML_NAME_ID_FORMAT_UNSPECIFIED,
|
||||
)
|
||||
|
||||
LOGGER = get_logger()
|
||||
ERROR_CANNOT_DECODE_REQUEST = "Cannot decode SAML request."
|
||||
ERROR_SIGNATURE_REQUIRED_BUT_ABSENT = (
|
||||
"Verification Certificate configured, but request is not signed."
|
||||
)
|
||||
@ -42,7 +43,7 @@ class AuthNRequest:
|
||||
|
||||
relay_state: Optional[str] = None
|
||||
|
||||
name_id_policy: str = SAML_NAME_ID_FORMAT_EMAIL
|
||||
name_id_policy: str = SAML_NAME_ID_FORMAT_UNSPECIFIED
|
||||
|
||||
|
||||
class AuthNRequestParser:
|
||||
@ -69,16 +70,21 @@ class AuthNRequestParser:
|
||||
auth_n_request = AuthNRequest(id=root.attrib["ID"], relay_state=relay_state)
|
||||
|
||||
# Check if AuthnRequest has a NameID Policy object
|
||||
name_id_policies = root.findall(f"{{{NS_SAML_PROTOCOL}}}:NameIDPolicy")
|
||||
name_id_policies = root.findall(f"{{{NS_SAML_PROTOCOL}}}NameIDPolicy")
|
||||
if len(name_id_policies) > 0:
|
||||
name_id_policy = name_id_policies[0]
|
||||
auth_n_request.name_id_policy = name_id_policy.attrib["Format"]
|
||||
auth_n_request.name_id_policy = name_id_policy.attrib.get(
|
||||
"Format", SAML_NAME_ID_FORMAT_UNSPECIFIED
|
||||
)
|
||||
|
||||
return auth_n_request
|
||||
|
||||
def parse(self, saml_request: str, relay_state: Optional[str]) -> AuthNRequest:
|
||||
"""Validate and parse raw request with enveloped signautre."""
|
||||
decoded_xml = b64decode(saml_request.encode()).decode()
|
||||
try:
|
||||
decoded_xml = b64decode(saml_request.encode()).decode()
|
||||
except UnicodeDecodeError:
|
||||
raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST)
|
||||
|
||||
verifier = self.provider.verification_kp
|
||||
|
||||
@ -121,7 +127,10 @@ class AuthNRequestParser:
|
||||
sig_alg: Optional[str] = None,
|
||||
) -> AuthNRequest:
|
||||
"""Validate and parse raw request with detached signature"""
|
||||
decoded_xml = decode_base64_and_inflate(saml_request)
|
||||
try:
|
||||
decoded_xml = decode_base64_and_inflate(saml_request)
|
||||
except UnicodeDecodeError:
|
||||
raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST)
|
||||
|
||||
verifier = self.provider.verification_kp
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ from authentik.providers.saml.processors.assertion import AssertionProcessor
|
||||
from authentik.providers.saml.processors.request_parser import AuthNRequestParser
|
||||
from authentik.sources.saml.exceptions import MismatchedRequestID
|
||||
from authentik.sources.saml.models import SAMLSource
|
||||
from authentik.sources.saml.processors.constants import SAML_NAME_ID_FORMAT_EMAIL
|
||||
from authentik.sources.saml.processors.constants import SAML_NAME_ID_FORMAT_UNSPECIFIED
|
||||
from authentik.sources.saml.processors.request import (
|
||||
SESSION_REQUEST_ID,
|
||||
RequestProcessor,
|
||||
@ -206,5 +206,5 @@ class TestAuthNRequest(TestCase):
|
||||
REDIRECT_REQUEST, REDIRECT_RELAY_STATE, REDIRECT_SIGNATURE, REDIRECT_SIG_ALG
|
||||
)
|
||||
self.assertEqual(parsed_request.id, "_dcf55fcd27a887e60a7ef9ee6fd3adab")
|
||||
self.assertEqual(parsed_request.name_id_policy, SAML_NAME_ID_FORMAT_EMAIL)
|
||||
self.assertEqual(parsed_request.name_id_policy, SAML_NAME_ID_FORMAT_UNSPECIFIED)
|
||||
self.assertEqual(parsed_request.relay_state, REDIRECT_RELAY_STATE)
|
||||
|
||||
@ -17,6 +17,7 @@ from authentik.providers.saml.models import SAMLBindings, SAMLProvider
|
||||
from authentik.providers.saml.processors.assertion import AssertionProcessor
|
||||
from authentik.providers.saml.processors.request_parser import AuthNRequest
|
||||
from authentik.providers.saml.utils.encoding import deflate_and_base64_encode, nice64
|
||||
from authentik.sources.saml.exceptions import SAMLException
|
||||
|
||||
LOGGER = get_logger()
|
||||
URL_VALIDATOR = URLValidator(schemes=("http", "https"))
|
||||
@ -56,22 +57,30 @@ class SAMLFlowFinalView(ChallengeStageView):
|
||||
provider: SAMLProvider = get_object_or_404(
|
||||
SAMLProvider, pk=application.provider_id
|
||||
)
|
||||
# Log Application Authorization
|
||||
Event.new(
|
||||
EventAction.AUTHORIZE_APPLICATION,
|
||||
authorized_application=application,
|
||||
flow=self.executor.plan.flow_pk,
|
||||
).from_http(self.request)
|
||||
|
||||
if SESSION_KEY_AUTH_N_REQUEST not in self.request.session:
|
||||
return self.executor.stage_invalid()
|
||||
|
||||
auth_n_request: AuthNRequest = self.request.session.pop(
|
||||
SESSION_KEY_AUTH_N_REQUEST
|
||||
)
|
||||
response = AssertionProcessor(
|
||||
provider, request, auth_n_request
|
||||
).build_response()
|
||||
try:
|
||||
response = AssertionProcessor(
|
||||
provider, request, auth_n_request
|
||||
).build_response()
|
||||
except SAMLException as exc:
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
message=f"Failed to process SAML assertion: {str(exc)}",
|
||||
provider=provider,
|
||||
).from_http(self.request)
|
||||
return self.executor.stage_invalid()
|
||||
|
||||
# Log Application Authorization
|
||||
Event.new(
|
||||
EventAction.AUTHORIZE_APPLICATION,
|
||||
authorized_application=application,
|
||||
flow=self.executor.plan.flow_pk,
|
||||
).from_http(self.request)
|
||||
|
||||
if provider.sp_binding == SAMLBindings.POST:
|
||||
form_attrs = {
|
||||
|
||||
@ -44,7 +44,7 @@ class Command(BaseCommand):
|
||||
user=user,
|
||||
intent=TokenIntents.INTENT_RECOVERY,
|
||||
description=f"Recovery Token generated by {getuser()} on {_now}",
|
||||
identifier=f"ak-recovery-{user}",
|
||||
identifier=f"ak-recovery-{user}-{_now}",
|
||||
)
|
||||
self.stdout.write(
|
||||
(
|
||||
|
||||
@ -15,6 +15,7 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
from json import dumps
|
||||
from tempfile import gettempdir
|
||||
from time import time
|
||||
|
||||
import structlog
|
||||
@ -193,6 +194,7 @@ CACHES = {
|
||||
f"redis://:{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:6379"
|
||||
f"/{CONFIG.y('redis.cache_db')}"
|
||||
),
|
||||
"TIMEOUT": int(CONFIG.y("redis.cache_timeout", 300)),
|
||||
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
|
||||
}
|
||||
}
|
||||
@ -341,7 +343,7 @@ DBBACKUP_FILENAME_TEMPLATE = "authentik-backup-{datetime}.sql"
|
||||
DBBACKUP_CONNECTOR_MAPPING = {
|
||||
"django_prometheus.db.backends.postgresql": "dbbackup.db.postgresql.PgDumpConnector",
|
||||
}
|
||||
|
||||
DBBACKUP_TMP_DIR = gettempdir() if DEBUG else "/tmp" # nosec
|
||||
if CONFIG.y("postgresql.s3_backup"):
|
||||
DBBACKUP_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
|
||||
DBBACKUP_STORAGE_OPTIONS = {
|
||||
|
||||
@ -15,6 +15,10 @@ class PytestTestRunner: # pragma: no cover
|
||||
settings.CELERY_TASK_ALWAYS_EAGER = True
|
||||
CONFIG.y_set("authentik.avatars", "none")
|
||||
CONFIG.y_set("authentik.geoip", "tests/GeoLite2-City-Test.mmdb")
|
||||
CONFIG.y_set(
|
||||
"outposts.docker_image_base",
|
||||
"beryju.org/authentik/outpost-%(type)s:gh-master",
|
||||
)
|
||||
|
||||
def run_tests(self, test_labels):
|
||||
"""Run pytest and return the exitcode.
|
||||
|
||||
@ -2,17 +2,21 @@
|
||||
from authentik.lib.sentry import SentryIgnoredException
|
||||
|
||||
|
||||
class MissingSAMLResponse(SentryIgnoredException):
|
||||
class SAMLException(SentryIgnoredException):
|
||||
"""Base SAML Exception"""
|
||||
|
||||
|
||||
class MissingSAMLResponse(SAMLException):
|
||||
"""Exception raised when request does not contain SAML Response."""
|
||||
|
||||
|
||||
class UnsupportedNameIDFormat(SentryIgnoredException):
|
||||
class UnsupportedNameIDFormat(SAMLException):
|
||||
"""Exception raised when SAML Response contains NameID Format not supported."""
|
||||
|
||||
|
||||
class MismatchedRequestID(SentryIgnoredException):
|
||||
class MismatchedRequestID(SAMLException):
|
||||
"""Exception raised when the returned request ID doesn't match the saved ID."""
|
||||
|
||||
|
||||
class InvalidSignature(SentryIgnoredException):
|
||||
class InvalidSignature(SAMLException):
|
||||
"""Signature of XML Object is either missing or invalid"""
|
||||
|
||||
@ -15,6 +15,9 @@ NS_MAP = {
|
||||
|
||||
SAML_NAME_ID_FORMAT_EMAIL = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
||||
SAML_NAME_ID_FORMAT_PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
|
||||
SAML_NAME_ID_FORMAT_UNSPECIFIED = (
|
||||
"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||
)
|
||||
SAML_NAME_ID_FORMAT_X509 = "urn:oasis:names:tc:SAML:2.0:nameid-format:X509SubjectName"
|
||||
SAML_NAME_ID_FORMAT_WINDOWS = (
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:WindowsDomainQualifiedName"
|
||||
|
||||
@ -9,7 +9,7 @@ from rest_framework.permissions import IsAdminUser
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
|
||||
from authentik.api.authorization import OwnerFilter, OwnerPermissions
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
@ -94,7 +94,7 @@ class DuoDeviceViewSet(
|
||||
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
|
||||
|
||||
|
||||
class DuoAdminDeviceViewSet(ReadOnlyModelViewSet):
|
||||
class DuoAdminDeviceViewSet(ModelViewSet):
|
||||
"""Viewset for Duo authenticator devices (for admins)"""
|
||||
|
||||
permission_classes = [IsAdminUser]
|
||||
|
||||
@ -3,6 +3,7 @@ from django.http import HttpRequest, HttpResponse
|
||||
from rest_framework.fields import CharField
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.flows.challenge import (
|
||||
Challenge,
|
||||
ChallengeResponse,
|
||||
@ -11,6 +12,7 @@ from authentik.flows.challenge import (
|
||||
)
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.flows.stage import ChallengeStageView
|
||||
from authentik.flows.views import InvalidStageError
|
||||
from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice
|
||||
|
||||
LOGGER = get_logger()
|
||||
@ -42,7 +44,15 @@ class AuthenticatorDuoStageView(ChallengeStageView):
|
||||
def get_challenge(self, *args, **kwargs) -> Challenge:
|
||||
user = self.get_pending_user()
|
||||
stage: AuthenticatorDuoStage = self.executor.current_stage
|
||||
enroll = stage.client.enroll(user.username)
|
||||
try:
|
||||
enroll = stage.client.enroll(user.username)
|
||||
except RuntimeError as exc:
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
message=f"Failed to enroll user: {str(exc)}",
|
||||
user=user,
|
||||
).from_http(self.request, user)
|
||||
raise InvalidStageError(str(exc)) from exc
|
||||
user_id = enroll["user_id"]
|
||||
self.request.session[SESSION_KEY_DUO_USER_ID] = user_id
|
||||
self.request.session[SESSION_KEY_DUO_ACTIVATION_CODE] = enroll[
|
||||
|
||||
@ -10,7 +10,7 @@ from authentik.flows.challenge import (
|
||||
ChallengeTypes,
|
||||
WithUserInfoChallenge,
|
||||
)
|
||||
from authentik.flows.models import NotConfiguredAction
|
||||
from authentik.flows.models import NotConfiguredAction, Stage
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.flows.stage import ChallengeStageView
|
||||
from authentik.stages.authenticator_validate.challenge import (
|
||||
@ -143,9 +143,12 @@ class AuthenticatorValidateStageView(ChallengeStageView):
|
||||
return self.executor.stage_invalid()
|
||||
if stage.not_configured_action == NotConfiguredAction.CONFIGURE:
|
||||
LOGGER.debug("Authenticator not configured, sending user to configure")
|
||||
# Because the foreign key to stage.configuration_stage points to
|
||||
# a base stage class, we need to do another lookup
|
||||
stage = Stage.objects.get_subclass(pk=stage.configuration_stage.pk)
|
||||
# plan.insert inserts at 1 index, so when stage_ok pops 0,
|
||||
# the configuration stage is next
|
||||
self.executor.plan.insert(stage.configuration_stage)
|
||||
self.executor.plan.insert(stage)
|
||||
return self.executor.stage_ok()
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
||||
@ -4,11 +4,14 @@ from unittest.mock import MagicMock, patch
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.urls.base import reverse
|
||||
from django.utils.encoding import force_str
|
||||
from django_otp.plugins.otp_totp.models import TOTPDevice
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.flows.models import NotConfiguredAction
|
||||
from authentik.flows.challenge import ChallengeTypes
|
||||
from authentik.flows.models import Flow, FlowStageBinding, NotConfiguredAction
|
||||
from authentik.flows.tests.test_planner import dummy_get_response
|
||||
from authentik.providers.oauth2.generators import (
|
||||
generate_client_id,
|
||||
@ -24,7 +27,9 @@ from authentik.stages.authenticator_validate.challenge import (
|
||||
validate_challenge_duo,
|
||||
validate_challenge_webauthn,
|
||||
)
|
||||
from authentik.stages.authenticator_validate.models import AuthenticatorValidateStage
|
||||
from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
|
||||
from authentik.stages.identification.models import IdentificationStage, UserFields
|
||||
|
||||
|
||||
class AuthenticatorValidateStageTests(TestCase):
|
||||
@ -34,6 +39,50 @@ class AuthenticatorValidateStageTests(TestCase):
|
||||
self.user = User.objects.get(username="akadmin")
|
||||
self.request_factory = RequestFactory()
|
||||
|
||||
def test_not_configured_action(self):
|
||||
"""Test not_configured_action"""
|
||||
conf_stage = IdentificationStage.objects.create(
|
||||
name="conf",
|
||||
user_fields=[
|
||||
UserFields.USERNAME,
|
||||
],
|
||||
)
|
||||
stage = AuthenticatorValidateStage.objects.create(
|
||||
name="foo",
|
||||
not_configured_action=NotConfiguredAction.CONFIGURE,
|
||||
configuration_stage=conf_stage,
|
||||
)
|
||||
flow = Flow.objects.create(name="test", slug="test", title="test")
|
||||
FlowStageBinding.objects.create(target=flow, stage=conf_stage, order=0)
|
||||
FlowStageBinding.objects.create(target=flow, stage=stage, order=1)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
{"uid_field": "akadmin"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
follow=True,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
force_str(response.content),
|
||||
{
|
||||
"type": ChallengeTypes.NATIVE.value,
|
||||
"component": "ak-stage-identification",
|
||||
"password_fields": False,
|
||||
"primary_action": "Log in",
|
||||
"flow_info": {
|
||||
"background": flow.background_url,
|
||||
"cancel_url": reverse("authentik_flows:cancel"),
|
||||
"title": flow.title,
|
||||
},
|
||||
"user_fields": ["username"],
|
||||
"sources": [],
|
||||
},
|
||||
)
|
||||
|
||||
def test_stage_validation(self):
|
||||
"""Test serializer validation"""
|
||||
self.client.force_login(self.user)
|
||||
|
||||
@ -175,7 +175,6 @@ class IdentificationStageView(ChallengeStageView):
|
||||
button = asdict(ui_login_button)
|
||||
button["challenge"] = ui_login_button.challenge.data
|
||||
ui_sources.append(button)
|
||||
print(ui_sources)
|
||||
challenge.initial_data["sources"] = ui_sources
|
||||
return challenge
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ class CurrentTenantSerializer(PassiveSerializer):
|
||||
ui_footer_links = ListField(
|
||||
child=FooterLinkSerializer(),
|
||||
read_only=True,
|
||||
default=CONFIG.y("authentik.footer_links"),
|
||||
default=CONFIG.y("footer_links", []),
|
||||
)
|
||||
|
||||
flow_unenrollment = CharField(source="flow_unenrollment.slug", required=False)
|
||||
|
||||
@ -19,7 +19,26 @@ class TestTenants(TestCase):
|
||||
"branding_favicon": "/static/dist/assets/icons/icon.png",
|
||||
"branding_title": "authentik",
|
||||
"matched_domain": "authentik-default",
|
||||
"ui_footer_links": CONFIG.y("authentik.footer_links"),
|
||||
"ui_footer_links": CONFIG.y("footer_links"),
|
||||
},
|
||||
)
|
||||
|
||||
def test_tenant_subdomain(self):
|
||||
"""Test Current tenant API"""
|
||||
Tenant.objects.all().delete()
|
||||
Tenant.objects.create(domain="bar.baz", branding_title="custom")
|
||||
self.assertJSONEqual(
|
||||
force_str(
|
||||
self.client.get(
|
||||
reverse("authentik_api:tenant-current"), HTTP_HOST="foo.bar.baz"
|
||||
).content
|
||||
),
|
||||
{
|
||||
"branding_logo": "/static/dist/assets/icons/icon_left_brand.svg",
|
||||
"branding_favicon": "/static/dist/assets/icons/icon.png",
|
||||
"branding_title": "custom",
|
||||
"matched_domain": "bar.baz",
|
||||
"ui_footer_links": CONFIG.y("footer_links"),
|
||||
},
|
||||
)
|
||||
|
||||
@ -33,6 +52,6 @@ class TestTenants(TestCase):
|
||||
"branding_favicon": "/static/dist/assets/icons/icon.png",
|
||||
"branding_title": "authentik",
|
||||
"matched_domain": "fallback",
|
||||
"ui_footer_links": CONFIG.y("authentik.footer_links"),
|
||||
"ui_footer_links": CONFIG.y("footer_links"),
|
||||
},
|
||||
)
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
"""Tenant utilities"""
|
||||
from typing import Any
|
||||
|
||||
from django.db.models import Q
|
||||
from django.db.models import F, Q
|
||||
from django.db.models import Value as V
|
||||
from django.http.request import HttpRequest
|
||||
|
||||
from authentik import __version__
|
||||
@ -14,8 +15,10 @@ DEFAULT_TENANT = Tenant(domain="fallback")
|
||||
|
||||
def get_tenant_for_request(request: HttpRequest) -> Tenant:
|
||||
"""Get tenant object for current request"""
|
||||
db_tenants = Tenant.objects.filter(
|
||||
Q(domain__iendswith=request.get_host()) | _q_default
|
||||
db_tenants = (
|
||||
Tenant.objects.annotate(host_domain=V(request.get_host()))
|
||||
.filter(Q(host_domain__iendswith=F("domain")) | _q_default)
|
||||
.order_by("default")
|
||||
)
|
||||
if not db_tenants.exists():
|
||||
return DEFAULT_TENANT
|
||||
@ -28,5 +31,5 @@ def context_processor(request: HttpRequest) -> dict[str, Any]:
|
||||
return {
|
||||
"tenant": tenant,
|
||||
"ak_version": __version__,
|
||||
"footer_links": CONFIG.y("authentik.footer_links"),
|
||||
"footer_links": CONFIG.y("footer_links"),
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ stages:
|
||||
inputs:
|
||||
script: |
|
||||
pipenv run python -m scripts.generate_ci_config
|
||||
pipenv run ./manage.py migrate
|
||||
pipenv run python -m lifecycle.migrate
|
||||
- job: migrations_from_previous_release
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
@ -21,7 +21,7 @@ services:
|
||||
networks:
|
||||
- internal
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.1-rc6}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.2}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
@ -38,21 +38,13 @@ services:
|
||||
- geoip:/geoip
|
||||
networks:
|
||||
- internal
|
||||
labels:
|
||||
traefik.enable: 'true'
|
||||
traefik.docker.network: internal
|
||||
traefik.http.routers.app-router.rule: PathPrefix(`/`)
|
||||
traefik.http.routers.app-router.service: app-service
|
||||
traefik.http.routers.app-router.tls: 'true'
|
||||
traefik.http.services.app-service.loadbalancer.healthcheck.path: /-/health/live/
|
||||
traefik.http.services.app-service.loadbalancer.server.port: '9000'
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "0.0.0.0:9000:9000"
|
||||
- "0.0.0.0:9443:9443"
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.1-rc6}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.2}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
networks:
|
||||
|
||||
@ -16,8 +16,9 @@ func DefaultConfig() {
|
||||
G = Config{
|
||||
Debug: false,
|
||||
Web: WebConfig{
|
||||
Listen: "localhost:9000",
|
||||
ListenTLS: "localhost:9443",
|
||||
Listen: "localhost:9000",
|
||||
ListenTLS: "localhost:9443",
|
||||
LoadLocalFiles: false,
|
||||
},
|
||||
Paths: PathsConfig{
|
||||
Media: "./media",
|
||||
|
||||
@ -9,8 +9,9 @@ type Config struct {
|
||||
}
|
||||
|
||||
type WebConfig struct {
|
||||
Listen string `yaml:"listen"`
|
||||
ListenTLS string `yaml:"listen_tls"`
|
||||
Listen string `yaml:"listen"`
|
||||
ListenTLS string `yaml:"listen_tls"`
|
||||
LoadLocalFiles bool `yaml:"load_local_files"`
|
||||
}
|
||||
|
||||
type PathsConfig struct {
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
package constants
|
||||
|
||||
const VERSION = "2021.6.1-rc6"
|
||||
const VERSION = "2021.6.2"
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
|
||||
func (ws *WebServer) configureStatic() {
|
||||
statRouter := ws.lh.NewRoute().Subrouter()
|
||||
if config.G.Debug {
|
||||
if config.G.Debug || config.G.Web.LoadLocalFiles {
|
||||
ws.log.Debug("Using local static files")
|
||||
ws.lh.PathPrefix("/static/dist").Handler(http.StripPrefix("/static/dist", http.FileServer(http.Dir("./web/dist"))))
|
||||
ws.lh.PathPrefix("/static/authentik").Handler(http.StripPrefix("/static/authentik", http.FileServer(http.Dir("./web/authentik"))))
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
all: clean
|
||||
|
||||
run:
|
||||
go run -v .
|
||||
|
||||
clean:
|
||||
go mod tidy
|
||||
go clean .
|
||||
|
||||
|
||||
@ -446,15 +446,17 @@ func (p *OAuthProxy) addHeadersForProxying(rw http.ResponseWriter, req *http.Req
|
||||
username = session.Email
|
||||
}
|
||||
authVal := b64.StdEncoding.EncodeToString([]byte(username + ":" + password))
|
||||
p.logger.WithField("username", username).Trace("setting http basic auth")
|
||||
req.Header["Authorization"] = []string{fmt.Sprintf("Basic %s", authVal)}
|
||||
}
|
||||
// Check if user has additional headers set that we should sent
|
||||
if additionalHeaders, ok := userAttributes["additionalHeaders"].(map[string]string); ok {
|
||||
if additionalHeaders, ok := userAttributes["additionalHeaders"].(map[string]interface{}); ok {
|
||||
p.logger.WithField("headers", additionalHeaders).Trace("setting additional headers")
|
||||
if additionalHeaders == nil {
|
||||
return
|
||||
}
|
||||
for key, value := range additionalHeaders {
|
||||
req.Header.Set(key, value)
|
||||
req.Header.Set(key, toString(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package proxy
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var xForwardedHost = http.CanonicalHeaderKey("X-Forwarded-Host")
|
||||
@ -18,3 +19,16 @@ func getHost(req *http.Request) string {
|
||||
}
|
||||
return hostOnly
|
||||
}
|
||||
|
||||
// toString Generic to string function, currently supports actual strings and integers
|
||||
func toString(in interface{}) string {
|
||||
switch v := in.(type) {
|
||||
case string:
|
||||
return v
|
||||
case *string:
|
||||
return *v
|
||||
case int:
|
||||
return strconv.Itoa(v)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
const VERSION = "2021.6.1-rc6"
|
||||
const VERSION = "2021.6.2"
|
||||
|
||||
func BUILD() string {
|
||||
build := os.Getenv("GIT_BUILD_HASH")
|
||||
|
||||
154
schema.yml
@ -1,7 +1,7 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: authentik
|
||||
version: 2021.6.1-rc5
|
||||
version: 2021.6.1
|
||||
description: Making authentication simple.
|
||||
contact:
|
||||
email: hello@beryju.org
|
||||
@ -236,6 +236,37 @@ paths:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
post:
|
||||
operationId: authenticators_admin_duo_create
|
||||
description: Viewset for Duo authenticator devices (for admins)
|
||||
tags:
|
||||
- authenticators
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDeviceRequest'
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDeviceRequest'
|
||||
multipart/form-data:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDeviceRequest'
|
||||
required: true
|
||||
security:
|
||||
- authentik: []
|
||||
- cookieAuth: []
|
||||
responses:
|
||||
'201':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDevice'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/api/v2beta/authenticators/admin/duo/{id}/:
|
||||
get:
|
||||
operationId: authenticators_admin_duo_retrieve
|
||||
@ -263,6 +294,103 @@ paths:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
put:
|
||||
operationId: authenticators_admin_duo_update
|
||||
description: Viewset for Duo authenticator devices (for admins)
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this Duo Device.
|
||||
required: true
|
||||
tags:
|
||||
- authenticators
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDeviceRequest'
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDeviceRequest'
|
||||
multipart/form-data:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDeviceRequest'
|
||||
required: true
|
||||
security:
|
||||
- authentik: []
|
||||
- cookieAuth: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDevice'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
patch:
|
||||
operationId: authenticators_admin_duo_partial_update
|
||||
description: Viewset for Duo authenticator devices (for admins)
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this Duo Device.
|
||||
required: true
|
||||
tags:
|
||||
- authenticators
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PatchedDuoDeviceRequest'
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PatchedDuoDeviceRequest'
|
||||
multipart/form-data:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PatchedDuoDeviceRequest'
|
||||
security:
|
||||
- authentik: []
|
||||
- cookieAuth: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DuoDevice'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
delete:
|
||||
operationId: authenticators_admin_duo_destroy
|
||||
description: Viewset for Duo authenticator devices (for admins)
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this Duo Device.
|
||||
required: true
|
||||
tags:
|
||||
- authenticators
|
||||
security:
|
||||
- authentik: []
|
||||
- cookieAuth: []
|
||||
responses:
|
||||
'204':
|
||||
description: No response body
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/api/v2beta/authenticators/admin/static/:
|
||||
get:
|
||||
operationId: authenticators_admin_static_list
|
||||
@ -18412,27 +18540,6 @@ components:
|
||||
required:
|
||||
- certificate_data
|
||||
- name
|
||||
ChallT:
|
||||
type: object
|
||||
description: |-
|
||||
Challenge that gets sent to the client based on which stage
|
||||
is currently active
|
||||
properties:
|
||||
type:
|
||||
$ref: '#/components/schemas/ChallengeChoices'
|
||||
flow_info:
|
||||
$ref: '#/components/schemas/ContextualFlowInfo'
|
||||
component:
|
||||
type: string
|
||||
default: ''
|
||||
response_errors:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ErrorDetail'
|
||||
required:
|
||||
- type
|
||||
ChallengeChoices:
|
||||
enum:
|
||||
- native
|
||||
@ -18449,7 +18556,6 @@ components:
|
||||
- $ref: '#/components/schemas/AuthenticatorWebAuthnChallenge'
|
||||
- $ref: '#/components/schemas/AutosubmitChallenge'
|
||||
- $ref: '#/components/schemas/CaptchaChallenge'
|
||||
- $ref: '#/components/schemas/ChallT'
|
||||
- $ref: '#/components/schemas/ConsentChallenge'
|
||||
- $ref: '#/components/schemas/DummyChallenge'
|
||||
- $ref: '#/components/schemas/EmailChallenge'
|
||||
@ -18470,8 +18576,6 @@ components:
|
||||
ak-stage-authenticator-webauthn: '#/components/schemas/AuthenticatorWebAuthnChallenge'
|
||||
ak-stage-autosubmit: '#/components/schemas/AutosubmitChallenge'
|
||||
ak-stage-captcha: '#/components/schemas/CaptchaChallenge'
|
||||
? ''
|
||||
: '#/components/schemas/ChallT'
|
||||
ak-stage-consent: '#/components/schemas/ConsentChallenge'
|
||||
ak-stage-dummy: '#/components/schemas/DummyChallenge'
|
||||
ak-stage-email: '#/components/schemas/EmailChallenge'
|
||||
|
||||
@ -21,7 +21,13 @@ from authentik.outposts.models import (
|
||||
)
|
||||
from authentik.outposts.tasks import outpost_local_connection
|
||||
from authentik.providers.proxy.models import ProxyProvider
|
||||
from tests.e2e.utils import SeleniumTestCase, apply_migration, object_manager, retry
|
||||
from tests.e2e.utils import (
|
||||
USER,
|
||||
SeleniumTestCase,
|
||||
apply_migration,
|
||||
object_manager,
|
||||
retry,
|
||||
)
|
||||
|
||||
|
||||
@skipUnless(platform.startswith("linux"), "requires local docker")
|
||||
@ -47,7 +53,7 @@ class TestProviderProxy(SeleniumTestCase):
|
||||
"""Start proxy container based on outpost created"""
|
||||
client: DockerClient = from_env()
|
||||
container = client.containers.run(
|
||||
image=f"ghcr.io/goauthentik/proxy:{__version__}",
|
||||
image="beryju.org/authentik/outpost-proxy:gh-master",
|
||||
detach=True,
|
||||
network_mode="host",
|
||||
auto_remove=True,
|
||||
@ -67,6 +73,11 @@ class TestProviderProxy(SeleniumTestCase):
|
||||
@object_manager
|
||||
def test_proxy_simple(self):
|
||||
"""Test simple outpost setup with single provider"""
|
||||
# set additionalHeaders to test later
|
||||
user = USER()
|
||||
user.attributes["additionalHeaders"] = {"X-Foo": "bar"}
|
||||
user.save()
|
||||
|
||||
proxy: ProxyProvider = ProxyProvider.objects.create(
|
||||
name="proxy_provider",
|
||||
authorization_flow=Flow.objects.get(
|
||||
@ -106,6 +117,7 @@ class TestProviderProxy(SeleniumTestCase):
|
||||
|
||||
full_body_text = self.driver.find_element(By.CSS_SELECTOR, "pre").text
|
||||
self.assertIn("X-Forwarded-Preferred-Username: akadmin", full_body_text)
|
||||
self.assertIn("X-Foo: bar", full_body_text)
|
||||
|
||||
|
||||
@skipUnless(platform.startswith("linux"), "requires local docker")
|
||||
|
||||
@ -104,5 +104,5 @@ class OutpostDockerTests(TestCase):
|
||||
self.assertEqual(compose["version"], "3.5")
|
||||
self.assertEqual(
|
||||
compose["services"]["authentik_proxy"]["image"],
|
||||
f"ghcr.io/goauthentik/proxy:{__version__}",
|
||||
"beryju.org/authentik/outpost-proxy:gh-master",
|
||||
)
|
||||
|
||||
@ -104,5 +104,5 @@ class TestProxyDocker(TestCase):
|
||||
self.assertEqual(compose["version"], "3.5")
|
||||
self.assertEqual(
|
||||
compose["services"]["authentik_proxy"]["image"],
|
||||
f"ghcr.io/goauthentik/proxy:{__version__}",
|
||||
"beryju.org/authentik/outpost-proxy:gh-master",
|
||||
)
|
||||
|
||||
510
web/package-lock.json
generated
@ -12,11 +12,11 @@
|
||||
"@babel/core": "^7.14.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.14.5",
|
||||
"@babel/plugin-transform-runtime": "^7.14.5",
|
||||
"@babel/preset-env": "^7.14.5",
|
||||
"@babel/preset-env": "^7.14.7",
|
||||
"@babel/preset-typescript": "^7.14.5",
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"@lingui/cli": "^3.10.2",
|
||||
"@lingui/core": "^3.10.3",
|
||||
"@lingui/core": "^3.10.4",
|
||||
"@lingui/macro": "^3.10.2",
|
||||
"@patternfly/patternfly": "^4.108.2",
|
||||
"@polymer/iron-form": "^3.0.1",
|
||||
@ -24,22 +24,22 @@
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"@rollup/plugin-typescript": "^8.2.1",
|
||||
"@sentry/browser": "^6.7.0",
|
||||
"@sentry/tracing": "^6.7.0",
|
||||
"@sentry/browser": "^6.7.2",
|
||||
"@sentry/tracing": "^6.7.2",
|
||||
"@types/chart.js": "^2.9.32",
|
||||
"@types/codemirror": "5.60.0",
|
||||
"@types/grecaptcha": "^3.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.27.0",
|
||||
"@typescript-eslint/parser": "^4.27.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
||||
"@typescript-eslint/parser": "^4.28.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.5.0",
|
||||
"authentik-api": "file:api",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^3.3.2",
|
||||
"chartjs-adapter-moment": "^1.0.0",
|
||||
"codemirror": "^5.61.1",
|
||||
"codemirror": "^5.62.0",
|
||||
"construct-style-sheets-polyfill": "^2.4.16",
|
||||
"eslint": "^7.28.0",
|
||||
"eslint": "^7.29.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.2",
|
||||
"eslint-plugin-lit": "^1.5.1",
|
||||
@ -48,7 +48,7 @@
|
||||
"lit-html": "^1.4.1",
|
||||
"moment": "^2.29.1",
|
||||
"rapidoc": "^9.0.0",
|
||||
"rollup": "^2.51.2",
|
||||
"rollup": "^2.52.2",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-cssimport": "^1.0.2",
|
||||
@ -58,7 +58,7 @@
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"ts-lit-plugin": "^1.2.1",
|
||||
"tslib": "^2.3.0",
|
||||
"typescript": "^4.3.2",
|
||||
"typescript": "^4.3.4",
|
||||
"webcomponent-qr-code": "^1.0.5",
|
||||
"yaml": "^1.10.2"
|
||||
}
|
||||
@ -102,9 +102,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.5.tgz",
|
||||
"integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz",
|
||||
"integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
@ -532,9 +532,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-proposal-async-generator-functions": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.5.tgz",
|
||||
"integrity": "sha512-tbD/CG3l43FIXxmu4a7RBe4zH7MLJ+S/lFowPFO7HetS2hyOZ/0nnnznegDuzFzfkyQYTxqdTH/hKmuBngaDAA==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz",
|
||||
"integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.14.5",
|
||||
"@babel/helper-remap-async-to-generator": "^7.14.5",
|
||||
@ -685,11 +685,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-proposal-object-rest-spread": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.5.tgz",
|
||||
"integrity": "sha512-VzMyY6PWNPPT3pxc5hi9LloKNr4SSrVCg7Yr6aZpW4Ym07r7KqSU/QXYwjXLVxqwSv0t/XSXkFoKBPUkZ8vb2A==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz",
|
||||
"integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.14.5",
|
||||
"@babel/compat-data": "^7.14.7",
|
||||
"@babel/helper-compilation-targets": "^7.14.5",
|
||||
"@babel/helper-plugin-utils": "^7.14.5",
|
||||
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
|
||||
@ -1077,9 +1077,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-destructuring": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.5.tgz",
|
||||
"integrity": "sha512-wU9tYisEbRMxqDezKUqC9GleLycCRoUsai9ddlsq54r8QRLaeEhc+d+9DqCG+kV9W2GgQjTZESPTpn5bAFMDww==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz",
|
||||
"integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.14.5"
|
||||
},
|
||||
@ -1258,9 +1258,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.5.tgz",
|
||||
"integrity": "sha512-+Xe5+6MWFo311U8SchgeX5c1+lJM+eZDBZgD+tvXu9VVQPXwwVzeManMMjYX6xw2HczngfOSZjoFYKwdeB/Jvw==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz",
|
||||
"integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-create-regexp-features-plugin": "^7.14.5"
|
||||
},
|
||||
@ -1398,9 +1398,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-spread": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.5.tgz",
|
||||
"integrity": "sha512-/3iqoQdiWergnShZYl0xACb4ADeYCJ7X/RgmwtXshn6cIvautRPAFzhd58frQlokLO6Jb4/3JXvmm6WNTPtiTw==",
|
||||
"version": "7.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz",
|
||||
"integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.14.5",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.14.5"
|
||||
@ -1500,16 +1500,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.5.tgz",
|
||||
"integrity": "sha512-ci6TsS0bjrdPpWGnQ+m4f+JSSzDKlckqKIJJt9UZ/+g7Zz9k0N8lYU8IeLg/01o2h8LyNZDMLGgRLDTxpudLsA==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.7.tgz",
|
||||
"integrity": "sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA==",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.14.5",
|
||||
"@babel/compat-data": "^7.14.7",
|
||||
"@babel/helper-compilation-targets": "^7.14.5",
|
||||
"@babel/helper-plugin-utils": "^7.14.5",
|
||||
"@babel/helper-validator-option": "^7.14.5",
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5",
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.14.5",
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.14.7",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-class-static-block": "^7.14.5",
|
||||
"@babel/plugin-proposal-dynamic-import": "^7.14.5",
|
||||
@ -1518,7 +1518,7 @@
|
||||
"@babel/plugin-proposal-logical-assignment-operators": "^7.14.5",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
||||
"@babel/plugin-proposal-numeric-separator": "^7.14.5",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.14.5",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.14.7",
|
||||
"@babel/plugin-proposal-optional-catch-binding": "^7.14.5",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
|
||||
"@babel/plugin-proposal-private-methods": "^7.14.5",
|
||||
@ -1544,7 +1544,7 @@
|
||||
"@babel/plugin-transform-block-scoping": "^7.14.5",
|
||||
"@babel/plugin-transform-classes": "^7.14.5",
|
||||
"@babel/plugin-transform-computed-properties": "^7.14.5",
|
||||
"@babel/plugin-transform-destructuring": "^7.14.5",
|
||||
"@babel/plugin-transform-destructuring": "^7.14.7",
|
||||
"@babel/plugin-transform-dotall-regex": "^7.14.5",
|
||||
"@babel/plugin-transform-duplicate-keys": "^7.14.5",
|
||||
"@babel/plugin-transform-exponentiation-operator": "^7.14.5",
|
||||
@ -1556,7 +1556,7 @@
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.14.5",
|
||||
"@babel/plugin-transform-modules-systemjs": "^7.14.5",
|
||||
"@babel/plugin-transform-modules-umd": "^7.14.5",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.14.5",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7",
|
||||
"@babel/plugin-transform-new-target": "^7.14.5",
|
||||
"@babel/plugin-transform-object-super": "^7.14.5",
|
||||
"@babel/plugin-transform-parameters": "^7.14.5",
|
||||
@ -1564,7 +1564,7 @@
|
||||
"@babel/plugin-transform-regenerator": "^7.14.5",
|
||||
"@babel/plugin-transform-reserved-words": "^7.14.5",
|
||||
"@babel/plugin-transform-shorthand-properties": "^7.14.5",
|
||||
"@babel/plugin-transform-spread": "^7.14.5",
|
||||
"@babel/plugin-transform-spread": "^7.14.6",
|
||||
"@babel/plugin-transform-sticky-regex": "^7.14.5",
|
||||
"@babel/plugin-transform-template-literals": "^7.14.5",
|
||||
"@babel/plugin-transform-typeof-symbol": "^7.14.5",
|
||||
@ -1575,7 +1575,7 @@
|
||||
"babel-plugin-polyfill-corejs2": "^0.2.2",
|
||||
"babel-plugin-polyfill-corejs3": "^0.2.2",
|
||||
"babel-plugin-polyfill-regenerator": "^0.2.2",
|
||||
"core-js-compat": "^3.14.0",
|
||||
"core-js-compat": "^3.15.0",
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -2047,9 +2047,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lingui/core": {
|
||||
"version": "3.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.10.3.tgz",
|
||||
"integrity": "sha512-BiuWi5xPpQa27oIWWnkOYNx4qTMdMeu7vp5y1AGPYQ/4SO0rHfAtOxXtvRU/ktVwht/lIgx5Ygq5J3F+XLvOQA==",
|
||||
"version": "3.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.10.4.tgz",
|
||||
"integrity": "sha512-V9QKQ9PFMTPrGGz2PaeKHZcxFikQZzJbptyQbVFJdXaKhdE2RH6HhdK1PIziDHqp6ZWPthVIfVLURT3ku8eu5w==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"make-plural": "^6.2.2",
|
||||
@ -2314,13 +2314,13 @@
|
||||
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg=="
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.7.0.tgz",
|
||||
"integrity": "sha512-sZvy2fxHjHXPdlaz8Ax02BeUbdILRv6a4i9FvMHvgSBeDiAVRIS+ihBhJAqziNOqwwXYThCSPKcCYGyTTncrVw==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.7.2.tgz",
|
||||
"integrity": "sha512-Lv0Ne1QcesyGAhVcQDfQa3hDPR/MhPSDTMg3xFi+LxqztchVc4w/ynzR0wCZFb8KIHpTj5SpJHfxpDhXYMtS9g==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"@sentry/core": "6.7.2",
|
||||
"@sentry/types": "6.7.2",
|
||||
"@sentry/utils": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2333,14 +2333,14 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.7.0.tgz",
|
||||
"integrity": "sha512-1TzDQIsS71a+6T1o3+NPyIgsTc37wdGh7cKZ8DRQ4bsML7MAkBV/LJeTVbXa0S9xha1v9v/oPindnHX5vBLJbg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.7.2.tgz",
|
||||
"integrity": "sha512-NTZqwN5nR94yrXmSfekoPs1mIFuKvf8esdIW/DadwSKWAdLJwQTJY9xK/8PQv+SEzd7wiitPAx+mCw2By1xiNQ==",
|
||||
"dependencies": {
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/minimal": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"@sentry/hub": "6.7.2",
|
||||
"@sentry/minimal": "6.7.2",
|
||||
"@sentry/types": "6.7.2",
|
||||
"@sentry/utils": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2353,12 +2353,12 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/hub": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.7.0.tgz",
|
||||
"integrity": "sha512-8e1IF6v8OIjuZVsolBAFoHhY0fEolsWwmZzm9k5N1wXWRbu4gpLHnCtDw47u2O9CFYr+b//bNXjmsA+DTckPkw==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.7.2.tgz",
|
||||
"integrity": "sha512-05qVW6ymChJsXag4+fYCQokW3AcABIgcqrVYZUBf6GMU/Gbz5SJqpV7y1+njwWvnPZydMncP9LaDVpMKbE7UYQ==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"@sentry/types": "6.7.2",
|
||||
"@sentry/utils": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2371,12 +2371,12 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/minimal": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.7.0.tgz",
|
||||
"integrity": "sha512-q0SX2t1+6c8TSe8nI4+EsWc8+kSsKiGhoGo2tN2OTk4EXKCYEsEEDqB9iu7md5StmtmrO3UnRiYwT7JV8QGOeg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.7.2.tgz",
|
||||
"integrity": "sha512-jkpwFv2GFHoVl5vnK+9/Q+Ea8eVdbJ3hn3/Dqq9MOLFnVK7ED6MhdHKLT79puGSFj+85OuhM5m2Q44mIhyS5mw==",
|
||||
"dependencies": {
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/hub": "6.7.2",
|
||||
"@sentry/types": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2389,14 +2389,14 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/tracing": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.7.0.tgz",
|
||||
"integrity": "sha512-5joTxxDB4v2J1B3CIGDj4AJKJpeGztqExQMkCrwwWgBsZ+fFfctRSCyiwYo50TU93Zt/rt0rDjj8QF4o8ZH09A==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.7.2.tgz",
|
||||
"integrity": "sha512-juKlI7FICKONWJFJxDxerj0A+8mNRhmtrdR+OXFqOkqSAy/QXlSFZcA/j//O19k2CfwK1BrvoMcQ/4gnffUOVg==",
|
||||
"dependencies": {
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/minimal": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"@sentry/hub": "6.7.2",
|
||||
"@sentry/minimal": "6.7.2",
|
||||
"@sentry/types": "6.7.2",
|
||||
"@sentry/utils": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2409,19 +2409,19 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.7.0.tgz",
|
||||
"integrity": "sha512-5pKv0yJEOnkjy3J3eiGaM1CD2+p3rXkctJa8loZH7QgY7mJgUTKpozO3YymUmGjblthlrbuhH+5wUIBnVF60Bg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.7.2.tgz",
|
||||
"integrity": "sha512-h21Go/PfstUN+ZV6SbwRSZVg9GXRJWdLfHoO5PSVb3TVEMckuxk8tAE57/u+UZDwX8wu+Xyon2TgsKpiWKxqUg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.7.0.tgz",
|
||||
"integrity": "sha512-K6s9svqOF4TT4AwvlDdiV9ZSGStSnf64s8KH1DNqwu5EZULvXvg0kbqgi6ZJTDHcchbnwHm7hLMNfuw95Aqi4Q==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.7.2.tgz",
|
||||
"integrity": "sha512-9COL7aaBbe61Hp5BlArtXZ1o/cxli1NGONLPrVT4fMyeQFmLonhUiy77NdsW19XnvhvaA+2IoV5dg3dnFiF/og==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/types": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2579,15 +2579,14 @@
|
||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.27.0.tgz",
|
||||
"integrity": "sha512-DsLqxeUfLVNp3AO7PC3JyaddmEHTtI9qTSAs+RB6ja27QvIM0TA8Cizn1qcS6vOu+WDLFJzkwkgweiyFhssDdQ==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz",
|
||||
"integrity": "sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/experimental-utils": "4.27.0",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/experimental-utils": "4.28.0",
|
||||
"@typescript-eslint/scope-manager": "4.28.0",
|
||||
"debug": "^4.3.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
"regexpp": "^3.1.0",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
@ -2610,14 +2609,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/experimental-utils": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.27.0.tgz",
|
||||
"integrity": "sha512-n5NlbnmzT2MXlyT+Y0Jf0gsmAQzCnQSWXKy4RGSXVStjDvS5we9IWbh7qRVKdGcxT0WYlgcCYUK/HRg7xFhvjQ==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz",
|
||||
"integrity": "sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ==",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.7",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/typescript-estree": "4.27.0",
|
||||
"@typescript-eslint/scope-manager": "4.28.0",
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"@typescript-eslint/typescript-estree": "4.28.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
@ -2650,13 +2649,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.27.0.tgz",
|
||||
"integrity": "sha512-XpbxL+M+gClmJcJ5kHnUpBGmlGdgNvy6cehgR6ufyxkEJMGP25tZKCaKyC0W/JVpuhU3VU1RBn7SYUPKSMqQvQ==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.0.tgz",
|
||||
"integrity": "sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/typescript-estree": "4.27.0",
|
||||
"@typescript-eslint/scope-manager": "4.28.0",
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"@typescript-eslint/typescript-estree": "4.28.0",
|
||||
"debug": "^4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -2676,12 +2675,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.27.0.tgz",
|
||||
"integrity": "sha512-DY73jK6SEH6UDdzc6maF19AHQJBFVRf6fgAXHPXCGEmpqD4vYgPEzqpFz1lf/daSbOcMpPPj9tyXXDPW2XReAw==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz",
|
||||
"integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/visitor-keys": "4.27.0"
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"@typescript-eslint/visitor-keys": "4.28.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
@ -2692,9 +2691,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.27.0.tgz",
|
||||
"integrity": "sha512-I4ps3SCPFCKclRcvnsVA/7sWzh7naaM/b4pBO2hVxnM3wrU51Lveybdw5WoIktU/V4KfXrTt94V9b065b/0+wA==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz",
|
||||
"integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==",
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
},
|
||||
@ -2704,12 +2703,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.27.0.tgz",
|
||||
"integrity": "sha512-KH03GUsUj41sRLLEy2JHstnezgpS5VNhrJouRdmh6yNdQ+yl8w5LrSwBkExM+jWwCJa7Ct2c8yl8NdtNRyQO6g==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz",
|
||||
"integrity": "sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/visitor-keys": "4.27.0",
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"@typescript-eslint/visitor-keys": "4.28.0",
|
||||
"debug": "^4.3.1",
|
||||
"globby": "^11.0.3",
|
||||
"is-glob": "^4.0.1",
|
||||
@ -2730,9 +2729,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/globby": {
|
||||
"version": "11.0.3",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz",
|
||||
"integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==",
|
||||
"version": "11.0.4",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
|
||||
"integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
|
||||
"dependencies": {
|
||||
"array-union": "^2.1.0",
|
||||
"dir-glob": "^3.0.1",
|
||||
@ -2749,11 +2748,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.27.0.tgz",
|
||||
"integrity": "sha512-es0GRYNZp0ieckZ938cEANfEhsfHrzuLrePukLKtY3/KPXcq1Xd555Mno9/GOgXhKzn0QfkDLVgqWO3dGY80bg==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz",
|
||||
"integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -3476,9 +3475,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror": {
|
||||
"version": "5.61.1",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.61.1.tgz",
|
||||
"integrity": "sha512-+D1NZjAucuzE93vJGbAaXzvoBHwp9nJZWWWF9utjv25+5AZUiah6CIlfb4ikG4MoDsFsCG8niiJH5++OO2LgIQ=="
|
||||
"version": "5.62.0",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.62.0.tgz",
|
||||
"integrity": "sha512-Xnl3304iCc8nyVZuRkzDVVwc794uc9QNX0UcPGeNic1fbzkSrO4l4GVXho9tRNKBgPYZXgocUqXyfIv3BILhCQ=="
|
||||
},
|
||||
"node_modules/collection-visit": {
|
||||
"version": "1.0.0",
|
||||
@ -3579,9 +3578,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/core-js-compat": {
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.14.0.tgz",
|
||||
"integrity": "sha512-R4NS2eupxtiJU+VwgkF9WTpnSfZW4pogwKHd8bclWU2sp93Pr5S1uYJI84cMOubJRou7bcfL0vmwtLslWN5p3A==",
|
||||
"version": "3.15.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.0.tgz",
|
||||
"integrity": "sha512-8X6lWsG+s7IfOKzV93a7fRYfWRZobOfjw5V5rrq43Vh/W+V6qYxl7Akalsvgab4PFT/4L/pjQbdBUEM36NXKrw==",
|
||||
"dependencies": {
|
||||
"browserslist": "^4.16.6",
|
||||
"semver": "7.0.0"
|
||||
@ -3862,9 +3861,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "7.28.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz",
|
||||
"integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.29.0.tgz",
|
||||
"integrity": "sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "7.12.11",
|
||||
"@eslint/eslintrc": "^0.4.2",
|
||||
@ -6771,9 +6770,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "2.51.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.2.tgz",
|
||||
"integrity": "sha512-ReV2eGEadA7hmXSzjxdDKs10neqH2QURf2RxJ6ayAlq93ugy6qIvXMmbc5cWMGCDh1h5T4thuWO1e2VNbMq8FA==",
|
||||
"version": "2.52.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.2.tgz",
|
||||
"integrity": "sha512-4RlFC3k2BIHlUsJ9mGd8OO+9Lm2eDF5P7+6DNQOp5sx+7N/1tFM01kELfbxlMX3MxT6owvLB1ln4S3QvvQlbUA==",
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
@ -6781,7 +6780,7 @@
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.1"
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-commonjs": {
|
||||
@ -7605,9 +7604,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
|
||||
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==",
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz",
|
||||
"integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@ -8066,9 +8065,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/compat-data": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.5.tgz",
|
||||
"integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w=="
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz",
|
||||
"integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw=="
|
||||
},
|
||||
"@babel/core": {
|
||||
"version": "7.14.6",
|
||||
@ -8380,9 +8379,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/plugin-proposal-async-generator-functions": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.5.tgz",
|
||||
"integrity": "sha512-tbD/CG3l43FIXxmu4a7RBe4zH7MLJ+S/lFowPFO7HetS2hyOZ/0nnnznegDuzFzfkyQYTxqdTH/hKmuBngaDAA==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz",
|
||||
"integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==",
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.14.5",
|
||||
"@babel/helper-remap-async-to-generator": "^7.14.5",
|
||||
@ -8473,11 +8472,11 @@
|
||||
}
|
||||
},
|
||||
"@babel/plugin-proposal-object-rest-spread": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.5.tgz",
|
||||
"integrity": "sha512-VzMyY6PWNPPT3pxc5hi9LloKNr4SSrVCg7Yr6aZpW4Ym07r7KqSU/QXYwjXLVxqwSv0t/XSXkFoKBPUkZ8vb2A==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz",
|
||||
"integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==",
|
||||
"requires": {
|
||||
"@babel/compat-data": "^7.14.5",
|
||||
"@babel/compat-data": "^7.14.7",
|
||||
"@babel/helper-compilation-targets": "^7.14.5",
|
||||
"@babel/helper-plugin-utils": "^7.14.5",
|
||||
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
|
||||
@ -8732,9 +8731,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-destructuring": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.5.tgz",
|
||||
"integrity": "sha512-wU9tYisEbRMxqDezKUqC9GleLycCRoUsai9ddlsq54r8QRLaeEhc+d+9DqCG+kV9W2GgQjTZESPTpn5bAFMDww==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz",
|
||||
"integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==",
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.14.5"
|
||||
}
|
||||
@ -8841,9 +8840,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.5.tgz",
|
||||
"integrity": "sha512-+Xe5+6MWFo311U8SchgeX5c1+lJM+eZDBZgD+tvXu9VVQPXwwVzeManMMjYX6xw2HczngfOSZjoFYKwdeB/Jvw==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz",
|
||||
"integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==",
|
||||
"requires": {
|
||||
"@babel/helper-create-regexp-features-plugin": "^7.14.5"
|
||||
}
|
||||
@ -8926,9 +8925,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-spread": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.5.tgz",
|
||||
"integrity": "sha512-/3iqoQdiWergnShZYl0xACb4ADeYCJ7X/RgmwtXshn6cIvautRPAFzhd58frQlokLO6Jb4/3JXvmm6WNTPtiTw==",
|
||||
"version": "7.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz",
|
||||
"integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==",
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.14.5",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.14.5"
|
||||
@ -8986,16 +8985,16 @@
|
||||
}
|
||||
},
|
||||
"@babel/preset-env": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.5.tgz",
|
||||
"integrity": "sha512-ci6TsS0bjrdPpWGnQ+m4f+JSSzDKlckqKIJJt9UZ/+g7Zz9k0N8lYU8IeLg/01o2h8LyNZDMLGgRLDTxpudLsA==",
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.7.tgz",
|
||||
"integrity": "sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA==",
|
||||
"requires": {
|
||||
"@babel/compat-data": "^7.14.5",
|
||||
"@babel/compat-data": "^7.14.7",
|
||||
"@babel/helper-compilation-targets": "^7.14.5",
|
||||
"@babel/helper-plugin-utils": "^7.14.5",
|
||||
"@babel/helper-validator-option": "^7.14.5",
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5",
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.14.5",
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.14.7",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-class-static-block": "^7.14.5",
|
||||
"@babel/plugin-proposal-dynamic-import": "^7.14.5",
|
||||
@ -9004,7 +9003,7 @@
|
||||
"@babel/plugin-proposal-logical-assignment-operators": "^7.14.5",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
||||
"@babel/plugin-proposal-numeric-separator": "^7.14.5",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.14.5",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.14.7",
|
||||
"@babel/plugin-proposal-optional-catch-binding": "^7.14.5",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
|
||||
"@babel/plugin-proposal-private-methods": "^7.14.5",
|
||||
@ -9030,7 +9029,7 @@
|
||||
"@babel/plugin-transform-block-scoping": "^7.14.5",
|
||||
"@babel/plugin-transform-classes": "^7.14.5",
|
||||
"@babel/plugin-transform-computed-properties": "^7.14.5",
|
||||
"@babel/plugin-transform-destructuring": "^7.14.5",
|
||||
"@babel/plugin-transform-destructuring": "^7.14.7",
|
||||
"@babel/plugin-transform-dotall-regex": "^7.14.5",
|
||||
"@babel/plugin-transform-duplicate-keys": "^7.14.5",
|
||||
"@babel/plugin-transform-exponentiation-operator": "^7.14.5",
|
||||
@ -9042,7 +9041,7 @@
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.14.5",
|
||||
"@babel/plugin-transform-modules-systemjs": "^7.14.5",
|
||||
"@babel/plugin-transform-modules-umd": "^7.14.5",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.14.5",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7",
|
||||
"@babel/plugin-transform-new-target": "^7.14.5",
|
||||
"@babel/plugin-transform-object-super": "^7.14.5",
|
||||
"@babel/plugin-transform-parameters": "^7.14.5",
|
||||
@ -9050,7 +9049,7 @@
|
||||
"@babel/plugin-transform-regenerator": "^7.14.5",
|
||||
"@babel/plugin-transform-reserved-words": "^7.14.5",
|
||||
"@babel/plugin-transform-shorthand-properties": "^7.14.5",
|
||||
"@babel/plugin-transform-spread": "^7.14.5",
|
||||
"@babel/plugin-transform-spread": "^7.14.6",
|
||||
"@babel/plugin-transform-sticky-regex": "^7.14.5",
|
||||
"@babel/plugin-transform-template-literals": "^7.14.5",
|
||||
"@babel/plugin-transform-typeof-symbol": "^7.14.5",
|
||||
@ -9061,7 +9060,7 @@
|
||||
"babel-plugin-polyfill-corejs2": "^0.2.2",
|
||||
"babel-plugin-polyfill-corejs3": "^0.2.2",
|
||||
"babel-plugin-polyfill-regenerator": "^0.2.2",
|
||||
"core-js-compat": "^3.14.0",
|
||||
"core-js-compat": "^3.15.0",
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9431,9 +9430,9 @@
|
||||
}
|
||||
},
|
||||
"@lingui/core": {
|
||||
"version": "3.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.10.3.tgz",
|
||||
"integrity": "sha512-BiuWi5xPpQa27oIWWnkOYNx4qTMdMeu7vp5y1AGPYQ/4SO0rHfAtOxXtvRU/ktVwht/lIgx5Ygq5J3F+XLvOQA==",
|
||||
"version": "3.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.10.4.tgz",
|
||||
"integrity": "sha512-V9QKQ9PFMTPrGGz2PaeKHZcxFikQZzJbptyQbVFJdXaKhdE2RH6HhdK1PIziDHqp6ZWPthVIfVLURT3ku8eu5w==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"make-plural": "^6.2.2",
|
||||
@ -9670,13 +9669,13 @@
|
||||
}
|
||||
},
|
||||
"@sentry/browser": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.7.0.tgz",
|
||||
"integrity": "sha512-sZvy2fxHjHXPdlaz8Ax02BeUbdILRv6a4i9FvMHvgSBeDiAVRIS+ihBhJAqziNOqwwXYThCSPKcCYGyTTncrVw==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.7.2.tgz",
|
||||
"integrity": "sha512-Lv0Ne1QcesyGAhVcQDfQa3hDPR/MhPSDTMg3xFi+LxqztchVc4w/ynzR0wCZFb8KIHpTj5SpJHfxpDhXYMtS9g==",
|
||||
"requires": {
|
||||
"@sentry/core": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"@sentry/core": "6.7.2",
|
||||
"@sentry/types": "6.7.2",
|
||||
"@sentry/utils": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9688,14 +9687,14 @@
|
||||
}
|
||||
},
|
||||
"@sentry/core": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.7.0.tgz",
|
||||
"integrity": "sha512-1TzDQIsS71a+6T1o3+NPyIgsTc37wdGh7cKZ8DRQ4bsML7MAkBV/LJeTVbXa0S9xha1v9v/oPindnHX5vBLJbg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.7.2.tgz",
|
||||
"integrity": "sha512-NTZqwN5nR94yrXmSfekoPs1mIFuKvf8esdIW/DadwSKWAdLJwQTJY9xK/8PQv+SEzd7wiitPAx+mCw2By1xiNQ==",
|
||||
"requires": {
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/minimal": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"@sentry/hub": "6.7.2",
|
||||
"@sentry/minimal": "6.7.2",
|
||||
"@sentry/types": "6.7.2",
|
||||
"@sentry/utils": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9707,12 +9706,12 @@
|
||||
}
|
||||
},
|
||||
"@sentry/hub": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.7.0.tgz",
|
||||
"integrity": "sha512-8e1IF6v8OIjuZVsolBAFoHhY0fEolsWwmZzm9k5N1wXWRbu4gpLHnCtDw47u2O9CFYr+b//bNXjmsA+DTckPkw==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.7.2.tgz",
|
||||
"integrity": "sha512-05qVW6ymChJsXag4+fYCQokW3AcABIgcqrVYZUBf6GMU/Gbz5SJqpV7y1+njwWvnPZydMncP9LaDVpMKbE7UYQ==",
|
||||
"requires": {
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"@sentry/types": "6.7.2",
|
||||
"@sentry/utils": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9724,12 +9723,12 @@
|
||||
}
|
||||
},
|
||||
"@sentry/minimal": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.7.0.tgz",
|
||||
"integrity": "sha512-q0SX2t1+6c8TSe8nI4+EsWc8+kSsKiGhoGo2tN2OTk4EXKCYEsEEDqB9iu7md5StmtmrO3UnRiYwT7JV8QGOeg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.7.2.tgz",
|
||||
"integrity": "sha512-jkpwFv2GFHoVl5vnK+9/Q+Ea8eVdbJ3hn3/Dqq9MOLFnVK7ED6MhdHKLT79puGSFj+85OuhM5m2Q44mIhyS5mw==",
|
||||
"requires": {
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/hub": "6.7.2",
|
||||
"@sentry/types": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9741,14 +9740,14 @@
|
||||
}
|
||||
},
|
||||
"@sentry/tracing": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.7.0.tgz",
|
||||
"integrity": "sha512-5joTxxDB4v2J1B3CIGDj4AJKJpeGztqExQMkCrwwWgBsZ+fFfctRSCyiwYo50TU93Zt/rt0rDjj8QF4o8ZH09A==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.7.2.tgz",
|
||||
"integrity": "sha512-juKlI7FICKONWJFJxDxerj0A+8mNRhmtrdR+OXFqOkqSAy/QXlSFZcA/j//O19k2CfwK1BrvoMcQ/4gnffUOVg==",
|
||||
"requires": {
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/minimal": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"@sentry/hub": "6.7.2",
|
||||
"@sentry/minimal": "6.7.2",
|
||||
"@sentry/types": "6.7.2",
|
||||
"@sentry/utils": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9760,16 +9759,16 @@
|
||||
}
|
||||
},
|
||||
"@sentry/types": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.7.0.tgz",
|
||||
"integrity": "sha512-5pKv0yJEOnkjy3J3eiGaM1CD2+p3rXkctJa8loZH7QgY7mJgUTKpozO3YymUmGjblthlrbuhH+5wUIBnVF60Bg=="
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.7.2.tgz",
|
||||
"integrity": "sha512-h21Go/PfstUN+ZV6SbwRSZVg9GXRJWdLfHoO5PSVb3TVEMckuxk8tAE57/u+UZDwX8wu+Xyon2TgsKpiWKxqUg=="
|
||||
},
|
||||
"@sentry/utils": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.7.0.tgz",
|
||||
"integrity": "sha512-K6s9svqOF4TT4AwvlDdiV9ZSGStSnf64s8KH1DNqwu5EZULvXvg0kbqgi6ZJTDHcchbnwHm7hLMNfuw95Aqi4Q==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.7.2.tgz",
|
||||
"integrity": "sha512-9COL7aaBbe61Hp5BlArtXZ1o/cxli1NGONLPrVT4fMyeQFmLonhUiy77NdsW19XnvhvaA+2IoV5dg3dnFiF/og==",
|
||||
"requires": {
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/types": "6.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9926,29 +9925,28 @@
|
||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.27.0.tgz",
|
||||
"integrity": "sha512-DsLqxeUfLVNp3AO7PC3JyaddmEHTtI9qTSAs+RB6ja27QvIM0TA8Cizn1qcS6vOu+WDLFJzkwkgweiyFhssDdQ==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz",
|
||||
"integrity": "sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ==",
|
||||
"requires": {
|
||||
"@typescript-eslint/experimental-utils": "4.27.0",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/experimental-utils": "4.28.0",
|
||||
"@typescript-eslint/scope-manager": "4.28.0",
|
||||
"debug": "^4.3.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
"regexpp": "^3.1.0",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.27.0.tgz",
|
||||
"integrity": "sha512-n5NlbnmzT2MXlyT+Y0Jf0gsmAQzCnQSWXKy4RGSXVStjDvS5we9IWbh7qRVKdGcxT0WYlgcCYUK/HRg7xFhvjQ==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz",
|
||||
"integrity": "sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ==",
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.7",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/typescript-estree": "4.27.0",
|
||||
"@typescript-eslint/scope-manager": "4.28.0",
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"@typescript-eslint/typescript-estree": "4.28.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
@ -9964,37 +9962,37 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.27.0.tgz",
|
||||
"integrity": "sha512-XpbxL+M+gClmJcJ5kHnUpBGmlGdgNvy6cehgR6ufyxkEJMGP25tZKCaKyC0W/JVpuhU3VU1RBn7SYUPKSMqQvQ==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.0.tgz",
|
||||
"integrity": "sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==",
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/typescript-estree": "4.27.0",
|
||||
"@typescript-eslint/scope-manager": "4.28.0",
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"@typescript-eslint/typescript-estree": "4.28.0",
|
||||
"debug": "^4.3.1"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.27.0.tgz",
|
||||
"integrity": "sha512-DY73jK6SEH6UDdzc6maF19AHQJBFVRf6fgAXHPXCGEmpqD4vYgPEzqpFz1lf/daSbOcMpPPj9tyXXDPW2XReAw==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz",
|
||||
"integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==",
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/visitor-keys": "4.27.0"
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"@typescript-eslint/visitor-keys": "4.28.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.27.0.tgz",
|
||||
"integrity": "sha512-I4ps3SCPFCKclRcvnsVA/7sWzh7naaM/b4pBO2hVxnM3wrU51Lveybdw5WoIktU/V4KfXrTt94V9b065b/0+wA=="
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz",
|
||||
"integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA=="
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.27.0.tgz",
|
||||
"integrity": "sha512-KH03GUsUj41sRLLEy2JHstnezgpS5VNhrJouRdmh6yNdQ+yl8w5LrSwBkExM+jWwCJa7Ct2c8yl8NdtNRyQO6g==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz",
|
||||
"integrity": "sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==",
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/visitor-keys": "4.27.0",
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"@typescript-eslint/visitor-keys": "4.28.0",
|
||||
"debug": "^4.3.1",
|
||||
"globby": "^11.0.3",
|
||||
"is-glob": "^4.0.1",
|
||||
@ -10003,9 +10001,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"globby": {
|
||||
"version": "11.0.3",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz",
|
||||
"integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==",
|
||||
"version": "11.0.4",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
|
||||
"integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
|
||||
"requires": {
|
||||
"array-union": "^2.1.0",
|
||||
"dir-glob": "^3.0.1",
|
||||
@ -10018,11 +10016,11 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.27.0.tgz",
|
||||
"integrity": "sha512-es0GRYNZp0ieckZ938cEANfEhsfHrzuLrePukLKtY3/KPXcq1Xd555Mno9/GOgXhKzn0QfkDLVgqWO3dGY80bg==",
|
||||
"version": "4.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz",
|
||||
"integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==",
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/types": "4.28.0",
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
}
|
||||
},
|
||||
@ -10591,9 +10589,9 @@
|
||||
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
|
||||
},
|
||||
"codemirror": {
|
||||
"version": "5.61.1",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.61.1.tgz",
|
||||
"integrity": "sha512-+D1NZjAucuzE93vJGbAaXzvoBHwp9nJZWWWF9utjv25+5AZUiah6CIlfb4ikG4MoDsFsCG8niiJH5++OO2LgIQ=="
|
||||
"version": "5.62.0",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.62.0.tgz",
|
||||
"integrity": "sha512-Xnl3304iCc8nyVZuRkzDVVwc794uc9QNX0UcPGeNic1fbzkSrO4l4GVXho9tRNKBgPYZXgocUqXyfIv3BILhCQ=="
|
||||
},
|
||||
"collection-visit": {
|
||||
"version": "1.0.0",
|
||||
@ -10681,9 +10679,9 @@
|
||||
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.14.0.tgz",
|
||||
"integrity": "sha512-R4NS2eupxtiJU+VwgkF9WTpnSfZW4pogwKHd8bclWU2sp93Pr5S1uYJI84cMOubJRou7bcfL0vmwtLslWN5p3A==",
|
||||
"version": "3.15.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.0.tgz",
|
||||
"integrity": "sha512-8X6lWsG+s7IfOKzV93a7fRYfWRZobOfjw5V5rrq43Vh/W+V6qYxl7Akalsvgab4PFT/4L/pjQbdBUEM36NXKrw==",
|
||||
"requires": {
|
||||
"browserslist": "^4.16.6",
|
||||
"semver": "7.0.0"
|
||||
@ -10901,9 +10899,9 @@
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"eslint": {
|
||||
"version": "7.28.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz",
|
||||
"integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.29.0.tgz",
|
||||
"integrity": "sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "7.12.11",
|
||||
"@eslint/eslintrc": "^0.4.2",
|
||||
@ -13202,11 +13200,11 @@
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.51.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.2.tgz",
|
||||
"integrity": "sha512-ReV2eGEadA7hmXSzjxdDKs10neqH2QURf2RxJ6ayAlq93ugy6qIvXMmbc5cWMGCDh1h5T4thuWO1e2VNbMq8FA==",
|
||||
"version": "2.52.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.2.tgz",
|
||||
"integrity": "sha512-4RlFC3k2BIHlUsJ9mGd8OO+9Lm2eDF5P7+6DNQOp5sx+7N/1tFM01kELfbxlMX3MxT6owvLB1ln4S3QvvQlbUA==",
|
||||
"requires": {
|
||||
"fsevents": "~2.3.1"
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"rollup-plugin-commonjs": {
|
||||
@ -13898,9 +13896,9 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
|
||||
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw=="
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz",
|
||||
"integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew=="
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.13.0",
|
||||
|
||||
@ -41,11 +41,11 @@
|
||||
"@babel/core": "^7.14.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.14.5",
|
||||
"@babel/plugin-transform-runtime": "^7.14.5",
|
||||
"@babel/preset-env": "^7.14.5",
|
||||
"@babel/preset-env": "^7.14.7",
|
||||
"@babel/preset-typescript": "^7.14.5",
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"@lingui/cli": "^3.10.2",
|
||||
"@lingui/core": "^3.10.3",
|
||||
"@lingui/core": "^3.10.4",
|
||||
"@lingui/macro": "^3.10.2",
|
||||
"@patternfly/patternfly": "^4.108.2",
|
||||
"@polymer/iron-form": "^3.0.1",
|
||||
@ -53,22 +53,22 @@
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"@rollup/plugin-typescript": "^8.2.1",
|
||||
"@sentry/browser": "^6.7.0",
|
||||
"@sentry/tracing": "^6.7.0",
|
||||
"@sentry/browser": "^6.7.2",
|
||||
"@sentry/tracing": "^6.7.2",
|
||||
"@types/chart.js": "^2.9.32",
|
||||
"@types/codemirror": "5.60.0",
|
||||
"@types/grecaptcha": "^3.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.27.0",
|
||||
"@typescript-eslint/parser": "^4.27.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
||||
"@typescript-eslint/parser": "^4.28.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.5.0",
|
||||
"authentik-api": "file:api",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^3.3.2",
|
||||
"chartjs-adapter-moment": "^1.0.0",
|
||||
"codemirror": "^5.61.1",
|
||||
"codemirror": "^5.62.0",
|
||||
"construct-style-sheets-polyfill": "^2.4.16",
|
||||
"eslint": "^7.28.0",
|
||||
"eslint": "^7.29.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.2",
|
||||
"eslint-plugin-lit": "^1.5.1",
|
||||
@ -77,7 +77,7 @@
|
||||
"lit-html": "^1.4.1",
|
||||
"moment": "^2.29.1",
|
||||
"rapidoc": "^9.0.0",
|
||||
"rollup": "^2.51.2",
|
||||
"rollup": "^2.52.2",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-cssimport": "^1.0.2",
|
||||
@ -87,7 +87,7 @@
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"ts-lit-plugin": "^1.2.1",
|
||||
"tslib": "^2.3.0",
|
||||
"typescript": "^4.3.2",
|
||||
"typescript": "^4.3.4",
|
||||
"webcomponent-qr-code": "^1.0.5",
|
||||
"yaml": "^1.10.2"
|
||||
},
|
||||
|
||||
@ -68,7 +68,7 @@ html > form > input {
|
||||
|
||||
/* ensure background on non-flow pages match */
|
||||
.pf-c-background-image::before {
|
||||
background-image: var(--ak-flow-background, url("/static/dist/assets/images/flow_background.jpg"));
|
||||
background-image: var(--ak-flow-background);
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
|
||||
export const ERROR_CLASS = "pf-m-danger";
|
||||
export const PROGRESS_CLASS = "pf-m-in-progress";
|
||||
export const CURRENT_CLASS = "pf-m-current";
|
||||
export const VERSION = "2021.6.1-rc6";
|
||||
export const VERSION = "2021.6.2";
|
||||
export const PAGE_SIZE = 20;
|
||||
export const EVENT_REFRESH = "ak-refresh";
|
||||
export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";
|
||||
|
||||
@ -54,7 +54,9 @@ export class ModalButton extends LitElement {
|
||||
|
||||
resetForms(): void {
|
||||
this.querySelectorAll<HTMLFormElement>("[slot=form]").forEach(form => {
|
||||
form?.resetForm();
|
||||
if ("resetForm" in form) {
|
||||
form?.resetForm();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,9 @@ export abstract class TableModal<T> extends Table<T> {
|
||||
|
||||
resetForms(): void {
|
||||
this.querySelectorAll<HTMLFormElement>("[slot=form]").forEach(form => {
|
||||
form?.resetForm();
|
||||
if ("resetForm" in form) {
|
||||
form?.resetForm();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -67,6 +67,27 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||
${t`Stage-specific settings`}
|
||||
</span>
|
||||
<div slot="body" class="pf-c-form">
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Device classes`}
|
||||
?required=${true}
|
||||
name="deviceClasses">
|
||||
<select name="users" class="pf-c-form-control" multiple>
|
||||
<option value=${DeviceClassesEnum.Static} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Static)}>
|
||||
${t`Static Tokens`}
|
||||
</option>
|
||||
<option value=${DeviceClassesEnum.Totp} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Totp)}>
|
||||
${t`TOTP Authenticators`}
|
||||
</option>
|
||||
<option value=${DeviceClassesEnum.Webauthn} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Webauthn)}>
|
||||
${t`WebAuthn Authenticators`}
|
||||
</option>
|
||||
<option value=${DeviceClassesEnum.Duo} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Duo)}>
|
||||
${t`Duo Authenticators`}
|
||||
</option>
|
||||
</select>
|
||||
<p class="pf-c-form__helper-text">${t`Device classes which can be used to authenticate.`}</p>
|
||||
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Not configured action`}
|
||||
?required=${true}
|
||||
@ -90,27 +111,6 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||
</option>
|
||||
</select>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Device classes`}
|
||||
?required=${true}
|
||||
name="deviceClasses">
|
||||
<select name="users" class="pf-c-form-control" multiple>
|
||||
<option value=${DeviceClassesEnum.Static} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Static)}>
|
||||
${t`Static Tokens`}
|
||||
</option>
|
||||
<option value=${DeviceClassesEnum.Totp} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Totp)}>
|
||||
${t`TOTP Authenticators`}
|
||||
</option>
|
||||
<option value=${DeviceClassesEnum.Webauthn} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Webauthn)}>
|
||||
${t`WebAuthn Authenticators`}
|
||||
</option>
|
||||
<option value=${DeviceClassesEnum.Duo} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Duo)}>
|
||||
${t`Duo Authenticators`}
|
||||
</option>
|
||||
</select>
|
||||
<p class="pf-c-form__helper-text">${t`Device classes which can be used to authenticate.`}</p>
|
||||
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
${this.showConfigurationStage ? html`
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Configuration stage`}
|
||||
|
||||
@ -49,7 +49,7 @@ export class TenantForm extends ModelForm<Tenant, string> {
|
||||
<input type="text" value="${first(this.instance?.domain, window.location.host)}" class="pf-c-form-control" required>
|
||||
<p class="pf-c-form__helper-text">${t`Matching is done based on domain suffix, so if you enter domain.tld, foo.domain.tld will still match.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal name="default">
|
||||
<ak-form-element-horizontal name="_default">
|
||||
<div class="pf-c-check">
|
||||
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?._default, false)}>
|
||||
<label class="pf-c-check__label">
|
||||
|
||||
72
website/developer-docs/flow-executor.md
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
title: Flow executor
|
||||
---
|
||||
|
||||
A big focus of authentik is the flows system, which allows you to combine and build complex conditional processes using stages and policies. Normally, these flows are executed in the browser using the authentik inbuilt flow executor (/if/flows).
|
||||
|
||||
However, any flow can be executed via an API from anywhere, in fact that is what the Web flow executor does. This means, you can, with a few requests, execute flows from anywhere, and integrate authentik even better.
|
||||
|
||||
:::info
|
||||
Because the flow executor stores its state in the HTTP Session, so you need to ensure cookies between flow executor requests are persisted.
|
||||
:::
|
||||
|
||||
The main endpoint for flow execution is `/api/v2beta/flows/executor/:slug`.
|
||||
|
||||
This endpoint accepts a query parameter called `query`, in which the flow executor sends the full Query-string.
|
||||
|
||||
To initiate a new flow, execute a GET request.
|
||||
|
||||
## `GET /api/v2beta/flows/executor/test-flow/`
|
||||
|
||||
Below is the response, for example for an Identification stage.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "native", // Stage type, can be "native", "shell" or "redirect"
|
||||
"flow_info": {
|
||||
// Related flow information, mostly used for UI and surrounding elements
|
||||
"title": "Welcome to authentik",
|
||||
"background": "/static/dist/assets/images/flow_background.jpg",
|
||||
"cancel_url": "/flows/-/cancel/"
|
||||
},
|
||||
// Main component to distinguish which stage is currently active
|
||||
"component": "ak-stage-identification",
|
||||
|
||||
// Stage-specific fields
|
||||
"user_fields": [
|
||||
"username",
|
||||
"email"
|
||||
],
|
||||
"password_fields": false,
|
||||
"primary_action": "Log in",
|
||||
"sources": []
|
||||
}
|
||||
```
|
||||
|
||||
To respond to this challenge, send a response:
|
||||
|
||||
## `POST /api/v2beta/flows/executor/test-flow/`
|
||||
|
||||
With this body
|
||||
|
||||
```json
|
||||
{
|
||||
// Component is required to determine how to parse the response
|
||||
"component": "ak-stage-identification",
|
||||
|
||||
// Stage-specific fields
|
||||
"uid_field": "jens"
|
||||
}
|
||||
```
|
||||
|
||||
Depending on the flow, you'll either get a 200 Response with another challenge, or a 302 redirect, which should be followed.
|
||||
|
||||
Depending also on the stage, a response might take longer to be returned (especially with the Duo Authenticator validation).
|
||||
|
||||
To see the data layout for every stage possible, see the [API Browser](https://goauthentik.io/api/#get-/api/v2beta/flows/executor/-flow_slug-/)
|
||||
|
||||
## Result
|
||||
|
||||
If a stage with the component `ak-stage-access-denied` is returned, the flow has been denied.
|
||||
|
||||
If a stage with the component `xak-flow-redirect` is returned, the flow has been executed successfully.
|
||||
50
website/developer-docs/frontend-only-dev-environment.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Frontend-only development environment
|
||||
---
|
||||
|
||||
If you want to only make changes on the UI, you don't need a backend running from source. You can user the docker-compose install with a few customizations.
|
||||
|
||||
1. Clone the git repo from https://github.com/goauthentik/authentik
|
||||
2. In the cloned repository, follow the docker-compose installation instructions [here](../../docs/installation/docker-compose)
|
||||
3. Add the following entry to your `.env` file:
|
||||
|
||||
```
|
||||
AUTHENTIK_IMAGE=beryju.org/authentik/server
|
||||
AUTHENTIK_TAG=gh-next
|
||||
AUTHENTIK_OUTPOSTS__DOCKER_IMAGE_BASE=beryju.org/authentik/outpost-%(type)s:gh-next
|
||||
```
|
||||
|
||||
This will cause authentik to use the beta images.
|
||||
|
||||
4. Create a `local.env.yml` file to tell authentik to use local files instead of the bundled ones:
|
||||
|
||||
```yaml
|
||||
log_level: debug
|
||||
web:
|
||||
load_local_files: true
|
||||
```
|
||||
|
||||
5. Add this volume mapping to your compose file
|
||||
|
||||
```yaml
|
||||
version: '3.2'
|
||||
|
||||
services:
|
||||
# [...]
|
||||
server:
|
||||
# [...]
|
||||
volumes:
|
||||
- ./web:/web
|
||||
- ./local.env.yml:/local.env.yml
|
||||
```
|
||||
|
||||
This makes the local web files and the config file available to the authentik server.
|
||||
|
||||
6. Run `docker-compose up -d` to apply those changes to your containers.
|
||||
7. Run `make gen-web` in the project root directory to generate the API Client used by the web interfaces
|
||||
8. `cd web`
|
||||
9. Run `npm i` and then `npm run watch` to start the build process.
|
||||
|
||||
You can now access authentik on http://localhost:9000 (or https://localhost:9443).
|
||||
|
||||
You might also want to complete the initial setup under `/if/flow/initial-setup/`.
|
||||
@ -1,6 +1,5 @@
|
||||
---
|
||||
title: Getting started
|
||||
slug: /
|
||||
title: Full development environment
|
||||
---
|
||||
|
||||
## Backend
|
||||
7
website/developer-docs/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Developer documentation
|
||||
slug: /
|
||||
---
|
||||
|
||||
Welcome to the authentik developer documentation. authentik is fully open source and can be found here: https://github.com/goauthentik/authentik
|
||||
|
||||
@ -29,6 +29,10 @@ All of these variables can be set to values, but you can also use a URI-like for
|
||||
- `AUTHENTIK_REDIS__CACHE_DB`: Database for caching, defaults to 0
|
||||
- `AUTHENTIK_REDIS__MESSAGE_QUEUE_DB`: Database for the message queue, defaults to 1
|
||||
- `AUTHENTIK_REDIS__WS_DB`: Database for websocket connections, defaults to 2
|
||||
- `AUTHENTIK_REDIS__CACHE_TIMEOUT`: Timeout for cached data until it expires in seconds, defaults to 300
|
||||
- `AUTHENTIK_REDIS__CACHE_TIMEOUT_FLOWS`: Timeout for cached flow plans until they expire in seconds, defaults to 300
|
||||
- `AUTHENTIK_REDIS__CACHE_TIMEOUT_POLICIES`: Timeout for cached polices until they expire in seconds, defaults to 300
|
||||
- `AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION`: Timeout for cached reputation until they expire in seconds, defaults to 300
|
||||
|
||||
## authentik Settings
|
||||
|
||||
@ -100,16 +104,16 @@ Defaults to `info`.
|
||||
|
||||
Placeholder for outpost docker images. Default: `ghcr.io/goauthentik/%(type)s:%(version)s`.
|
||||
|
||||
### AUTHENTIK_AUTHENTIK
|
||||
### AUTHENTIK_AVATARS
|
||||
|
||||
- `AUTHENTIK_AUTHENTIK__AVATARS`
|
||||
Configure how authentik should show avatars for users. Following values can be set:
|
||||
|
||||
Controls which avatars are shown. Defaults to `gravatar`. Can be set to `none` to disable avatars.
|
||||
- `none`: Disables per-user avatars and just shows a 1x1 pixel transparent picture
|
||||
- `gravatar`: Uses gravatar with the user's email address
|
||||
- Any URL: If you want to use images hosted on another server, you can set any URL.
|
||||
|
||||
- `AUTHENTIK_AUTHENTIK__BRANDING__TITLE`
|
||||
Additionally, these placeholders can be used:
|
||||
|
||||
Branding title used throughout the UI. Defaults to `authentik`.
|
||||
|
||||
- `AUTHENTIK_AUTHENTIK__BRANDING__LOGO`
|
||||
|
||||
Logo shown in the sidebar and flow executions. Defaults to `/static/dist/assets/icons/icon_left_brand.svg`
|
||||
- `%(username)s`: The user's username
|
||||
- `%(mail_hash)s`: The email address, md5 hashed
|
||||
- `%(upn)s`: The user's UPN, if set (otherwise an empty string)
|
||||
|
||||
@ -12,11 +12,11 @@ This installation method is for test-setups and small-scale productive setups.
|
||||
|
||||
## Preparation
|
||||
|
||||
Download the latest `docker-compose.yml` from [here](https://raw.githubusercontent.com/goauthentik/authentik/version/2021.6.1-rc6/docker-compose.yml). Place it in a directory of your choice.
|
||||
Download the latest `docker-compose.yml` from [here](https://raw.githubusercontent.com/goauthentik/authentik/version/2021.6.2/docker-compose.yml). Place it in a directory of your choice.
|
||||
|
||||
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
|
||||
|
||||
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.6.1-rc6 >> .env`
|
||||
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.6.2 >> .env`
|
||||
|
||||
If this is a fresh authentik install run the following commands to generate a password:
|
||||
|
||||
@ -74,7 +74,6 @@ Afterwards, run these commands to finish
|
||||
```shell
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
docker-compose run --rm server migrate
|
||||
```
|
||||
|
||||
The compose file statically references the latest version available at the time of downloading, which can be overridden with the `SERVER_TAG` environment variable.
|
||||
|
||||
@ -55,13 +55,19 @@ Under Attribute mapping, set these values:
|
||||
- Attribute to map the email address to.: `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`
|
||||
- Attribute to map the users groups to.: `http://schemas.xmlsoap.org/claims/Group`
|
||||
|
||||
:::note
|
||||
If Nextcloud is behind a reverse proxy you may need to force Nextcloud to use HTTPS.
|
||||
To do this you will need to add the line `'overwriteprotocol' => 'https'` to `config.php` in the Nextcloud `config\config.php` file
|
||||
See https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html#overwrite-parameters for additional information
|
||||
:::
|
||||
|
||||
## Group Quotas
|
||||
|
||||
Create a group for each different level of quota you want users to have. Set a custom attribute, for example called `nextcloud_quota`, to the quota you want, for example `15 GB`.
|
||||
|
||||
Afterwards, create a custom SAML Property Mapping with the name `SAML NextCloud Quota`.
|
||||
Set the *SAML Name* to `nextcloud_quota`.
|
||||
Set the *Expression* to `return user.group_attributes.get("nextcloud_quota", "1 GB")`, where `1 GB` is the default value for users that don't belong to another group (or have another value set).
|
||||
Set the *Expression* to `return user.group_attributes().get("nextcloud_quota", "1 GB")`, where `1 GB` is the default value for users that don't belong to another group (or have another value set).
|
||||
|
||||
## Admin Group
|
||||
|
||||
|
||||
80
website/docs/integrations/services/wekan/index.mdx
Normal file
@ -0,0 +1,80 @@
|
||||
---
|
||||
title: Wekan
|
||||
---
|
||||
|
||||
## What is Wekan
|
||||
|
||||
From https://github.com/wekan/wekan/wiki
|
||||
|
||||
:::note
|
||||
Wekan is an open-source kanban board which allows a card-based task and to-do management.
|
||||
:::
|
||||
|
||||
## Preparation
|
||||
|
||||
The following placeholders will be used:
|
||||
|
||||
- `wekan.company` is the FQDN of the wekan install.
|
||||
- `authentik.company` is the FQDN of the authentik install.
|
||||
|
||||
Create an application in authentik. Create an OAuth2/OpenID provider with the following parameters:
|
||||
|
||||
- Client Type: `Confidential`
|
||||
- JWT Algorithm: `RS256`
|
||||
- Scopes: OpenID, Email and Profile
|
||||
- RSA Key: Select any available key
|
||||
- Redirect URIs: `https://wekan.company/_oauth/oidc`
|
||||
|
||||
Note the Client ID and Client Secret values. Create an application, using the provider you've created above. Note the slug of the application you've created.
|
||||
|
||||
## Wekan
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
<Tabs
|
||||
defaultValue="docker"
|
||||
values={[
|
||||
{label: 'Docker', value: 'docker'},
|
||||
{label: 'Standalone', value: 'standalone'},
|
||||
]}>
|
||||
<TabItem value="docker">
|
||||
If your Wekan is running in docker, add the following environment variables for Authentik
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
OAUTH2_ENABLED=true
|
||||
OAUTH2_LOGIN_STYLE=redirect
|
||||
OAUTH2_CLIENT_ID=<Client ID from above>
|
||||
OAUTH2_SERVER_URL=https://authentik.company
|
||||
OAUTH2_AUTH_ENDPOINT=/application/o/authorize/
|
||||
OAUTH2_USERINFO_ENDPOINT=/application/o/userinfo/
|
||||
OAUTH2_TOKEN_ENDPOINT=/application/o/token/
|
||||
OAUTH2_SECRET=<Client Secret from above>
|
||||
OAUTH2_ID_MAP=preferred_username
|
||||
OAUTH2_USERNAME_MAP=preferred_username
|
||||
OAUTH2_FULLNAME_MAP=given_name
|
||||
OAUTH2_EMAIL_MAP=email
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="standalone">
|
||||
|
||||
edit `.env` and add the following:
|
||||
|
||||
```ini
|
||||
# Authentik OAUTH Config
|
||||
OAUTH2_ENABLED='true'
|
||||
OAUTH2_LOGIN_STYLE='redirect'
|
||||
OAUTH2_CLIENT_ID='<Client ID from above>'
|
||||
OAUTH2_SERVER_URL='https://authentik.company'
|
||||
OAUTH2_AUTH_ENDPOINT='/application/o/authorize/'
|
||||
OAUTH2_USERINFO_ENDPOINT='/application/o/userinfo/'
|
||||
OAUTH2_TOKEN_ENDPOINT='/application/o/token/'
|
||||
OAUTH2_SECRET='<Client Secret from above>'
|
||||
OAUTH2_ID_MAP='preferred_username'
|
||||
OAUTH2_USERNAME_MAP='preferred_username'
|
||||
OAUTH2_FULLNAME_MAP='given_name'
|
||||
OAUTH2_EMAIL_MAP='email'
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
BIN
website/docs/integrations/sources/discord/discord1.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
website/docs/integrations/sources/discord/discord2.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
website/docs/integrations/sources/discord/discord3.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
website/docs/integrations/sources/discord/discord4.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
website/docs/integrations/sources/discord/discord5.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
54
website/docs/integrations/sources/discord/index.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Discord
|
||||
---
|
||||
|
||||
Allows users to authenticate using their Discord credentials
|
||||
|
||||
## Preparation
|
||||
|
||||
The following placeholders will be used:
|
||||
|
||||
- `authentik.company` is the FQDN of the authentik install.
|
||||
|
||||
|
||||
## Discord
|
||||
|
||||
1. Create an application in the Discord Developer Portal (This is Free) https://discord.com/developers/applications
|
||||
|
||||

|
||||
|
||||
2. Name the Application
|
||||
|
||||

|
||||
|
||||
3. Select **OAuth2** from the left Menu
|
||||
|
||||
4. Copy the **Client ID** and _save it for later_
|
||||
|
||||
5. **Click to Reveal** the Client Secret and _save it for later_
|
||||
|
||||
6. Click **Add Redirect** and add https://authentik.company/source/oauth/callback/discord
|
||||
|
||||
Here is an example of a completed OAuth2 screen for Discord.
|
||||
|
||||

|
||||
|
||||
## Authentik
|
||||
|
||||
8. Under _Resources -> Sources_ Click **Create Discord OAuth Source**
|
||||
|
||||
9. **Name:** Choose a name (For the example I used Discord)
|
||||
10. **Slug:** discord (You can choose a different slug, if you do you will need to update the Discord redirect URLand point it to the correct slug.)
|
||||
11. **Consumer Key:** Client ID from step 4
|
||||
12. **Consumer Secret:** Client Secret from step 5
|
||||
13. **Provider type:** Discord
|
||||
|
||||
Here is an exmple of a complete Authentik Discord OAuth Source
|
||||
|
||||

|
||||
|
||||
Save, and you now have Discord as a source.
|
||||
|
||||
:::note
|
||||
For more details on how-to have the new source display on the Login Page see the Sources page
|
||||
:::
|
||||
BIN
website/docs/integrations/sources/github/githubdeveloper1.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 28 KiB |
BIN
website/docs/integrations/sources/github/githubexample2.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
60
website/docs/integrations/sources/github/index.md
Normal file
@ -0,0 +1,60 @@
|
||||
---
|
||||
title: Github
|
||||
---
|
||||
|
||||
Allows users to authenticate using their Github credentials
|
||||
|
||||
## Preparation
|
||||
|
||||
The following placeholders will be used:
|
||||
|
||||
- `authentik.company` is the FQDN of the authentik install.
|
||||
- `www.my.company` Homepage URL for your site
|
||||
|
||||
## Github
|
||||
|
||||
1. Create an OAuth app under Developer Settings https://github.com/settings/developers by clicking on the **Register a neww application**
|
||||
|
||||

|
||||
|
||||
2. **Application Name:** Choose a name users will recognize ie: Authentik
|
||||
3. **Homepage URL**:: www.my.company
|
||||
4. **Authorization callback URL**: https://authentik.company/source/oauth/callback/github
|
||||
5. Click **Register Application**
|
||||
|
||||
Example screenshot
|
||||
|
||||

|
||||
|
||||
6. Copy the **Client ID** and _save it for later_
|
||||
7. Click **Generate a new client secret** and _save it for later_ You will not be able to see the secret again, so be sure to copy it now.
|
||||
|
||||
## Authentik
|
||||
|
||||
8. Under _Resources -> Sources_ Click **Create Github OAuth Source**
|
||||
|
||||
9. **Name**: Choose a name (For the example I use Github)
|
||||
10. **Slug**: github (If you choose a different slug the URLs will need to be updated to reflect the change)
|
||||
11. **Consumer Key:** Client ID from step 6
|
||||
12. **Consumer Secret:** Client Secret from step 7
|
||||
13. **Provider Type:** Github
|
||||
|
||||
Expand URL settings:
|
||||
|
||||
:::note
|
||||
As of June 20 2021 these URLS are correct. Here is the Github reference URL https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps
|
||||
:::
|
||||
|
||||
14. **Authorization URL:** `https://github.com/login/oauth/authorize`
|
||||
15. **Access token URL:** `https://github.com/login/oauth/access_token`
|
||||
16. **Profile URL:** `https://api.github.com/user`
|
||||
|
||||
Here is an exmple of a complete Authentik Github OAuth Source
|
||||
|
||||

|
||||
|
||||
Save, and you now have Github as a source.
|
||||
|
||||
:::note
|
||||
For more details on how-to have the new source display on the Login Page see the Sources page
|
||||
:::
|
||||
BIN
website/docs/integrations/sources/google/authentiksource.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
website/docs/integrations/sources/google/googledeveloper1.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
website/docs/integrations/sources/google/googledeveloper2.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
website/docs/integrations/sources/google/googledeveloper3.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
website/docs/integrations/sources/google/googledeveloper4.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
website/docs/integrations/sources/google/googledeveloper5.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
website/docs/integrations/sources/google/googledeveloper6.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
83
website/docs/integrations/sources/google/index.md
Normal file
@ -0,0 +1,83 @@
|
||||
---
|
||||
title: Google
|
||||
---
|
||||
|
||||
Allows users to authenticate using their Google credentials
|
||||
|
||||
## Preparation
|
||||
|
||||
The following placeholders will be used:
|
||||
|
||||
- `authentik.company` is the FQDN of the authentik install.
|
||||
|
||||
## Google
|
||||
|
||||
You will need to create a new project, and OAuth credentials in the Google Developer console. The developer console can be overwhelming at first.
|
||||
|
||||
1. Visit https://console.developers.google.com/ to create a new project
|
||||
2. Create a New project.
|
||||
|
||||

|
||||
|
||||
3. **Project Name**: Choose a name
|
||||
4. **Organization**: Leave as defaut if unsure
|
||||
5. **Location**: Leave as default if unsure
|
||||
|
||||

|
||||
|
||||
6. Click **Create**
|
||||
7. Choose your project from the drop down at the top
|
||||
8. Click the **Credentials** menu item on the left. It looks like a key.
|
||||
|
||||

|
||||
|
||||
9. Click on **Configure Consent Screen**
|
||||
|
||||

|
||||
|
||||
|
||||
10. **User Type:** If you do not have a Google Workspace (GSuite) account choose _External_. If you do have a Google Workspace (Gsuite) account and want to limit acces to only users inside of your organization choose _Internal_
|
||||
|
||||
_I'm only going to list the mandatory/important fields to complete._
|
||||
|
||||
11. **App Name:** Choose an Application
|
||||
12. **User Support Email:** Must have a value
|
||||
13. **Authorized Domains:** authentik.company
|
||||
14. **Developer Contact Info:** Must have a value
|
||||
15. Click **Save and Continue**
|
||||
16. If you have special scopes configured for google, enter them on this screen. If not click **Save and Continue**
|
||||
17. If you want to create Test Users enter them here, if not click **Save and Continue**
|
||||
18. From the _Summary Page_ click on the **Credentials* link on the left. Same link as step 8
|
||||
19. Click **Create Credentials** on the top of the screen
|
||||
20. Choose **OAuth Client ID**
|
||||
|
||||

|
||||
|
||||
21. **Application Type:** Web Application
|
||||
22. **Name:** Choose a name
|
||||
23. **Authorized redirect URIs:** `https://authenik.company/source/oauth/callback/google/`
|
||||
|
||||

|
||||
|
||||
24. Click **Create**
|
||||
25. Copy and store _Your Client ID_ and _Your Client Secret_ for later
|
||||
|
||||
## Authentik
|
||||
|
||||
26. Under _Resources -> Sources_ Click **Create Google OAuth Source**
|
||||
|
||||
27. **Name**: Choose a name (For the example I use Google)
|
||||
28. **Slug**: google (If you choose a different slug the URLs will need to be updated to reflect the change)
|
||||
29. **Consumer Key:** Your Client ID from step 25
|
||||
30. **Consumer Secret:** Your Client Secret from step 25
|
||||
31. **Provider Type:** Google
|
||||
|
||||
Here is an exmple of a complete Authentik Google OAuth Source
|
||||
|
||||

|
||||
|
||||
Save, and you now have Google as a source.
|
||||
|
||||
:::note
|
||||
For more details on how-to have the new source display on the Login Page see the Sources page
|
||||
:::
|
||||
14
website/docs/integrations/sources/index.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Sources
|
||||
---
|
||||
|
||||
Sources allow you to connect authentik to an existing user directory. They can also be used for social logins, using external providers such as Facebook, Twitter, etc.
|
||||
|
||||
### Add Sources to Default Login Page
|
||||
|
||||
To have sources show on the default login screen you will need to add them. This is assuming you have not created or renamed the default stages and flows.
|
||||
1. Access the **Flows** section
|
||||
2. Click on **default-authentication-flow**
|
||||
3. Click the **Stage Bindings** tab
|
||||
4. Chose **Edit Stage** for the _default-authentication-identification_ stage
|
||||
5. Under **Sources** you should see the addtional sources you have configured. Click all applicable sources to have them displayed on the Login Page
|
||||
@ -1,26 +1,9 @@
|
||||
---
|
||||
title: Sources
|
||||
title: LDAP
|
||||
---
|
||||
|
||||
Sources allow you to connect authentik to an existing user directory. They can also be used for social logins, using external providers such as Facebook, Twitter, etc.
|
||||
|
||||
## Generic OAuth Source
|
||||
|
||||
**All Integration-specific Sources are documented in the Integrations Section**
|
||||
|
||||
This source allows users to enroll themselves with an external OAuth-based Identity Provider. The generic provider expects the endpoint to return OpenID-Connect compatible information. Vendor-specific implementations have their own OAuth Source.
|
||||
|
||||
- Policies: Allow/Forbid users from linking their accounts with this provider.
|
||||
- Request Token URL: This field is used for OAuth v1 implementations and will be provided by the provider.
|
||||
- Authorization URL: This value will be provided by the provider.
|
||||
- Access Token URL: This value will be provided by the provider.
|
||||
- Profile URL: This URL is called by authentik to retrieve user information upon successful authentication.
|
||||
- Consumer key/Consumer secret: These values will be provided by the provider.
|
||||
|
||||
## SAML Source
|
||||
|
||||
This source allows authentik to act as a SAML Service Provider. Just like the SAML Provider, it supports signed requests. Vendor-specific documentation can be found in the Integrations Section.
|
||||
|
||||
## LDAP Source
|
||||
|
||||
This source allows you to import users and groups from an LDAP Server.
|
||||
18
website/docs/integrations/sources/oauth/index.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Generic OAuth Source
|
||||
---
|
||||
|
||||
## Generic OAuth Source
|
||||
|
||||
:::note
|
||||
All Integration-specific Sources are documented in the Integrations Section
|
||||
:::
|
||||
|
||||
This source allows users to enroll themselves with an external OAuth-based Identity Provider. The generic provider expects the endpoint to return OpenID-Connect compatible information. Vendor-specific implementations have their own OAuth Source.
|
||||
|
||||
- Policies: Allow/Forbid users from linking their accounts with this provider.
|
||||
- Request Token URL: This field is used for OAuth v1 implementations and will be provided by the provider.
|
||||
- Authorization URL: This value will be provided by the provider.
|
||||
- Access Token URL: This value will be provided by the provider.
|
||||
- Profile URL: This URL is called by authentik to retrieve user information upon successful authentication.
|
||||
- Consumer key/Consumer secret: These values will be provided by the provider.
|
||||
21
website/docs/integrations/sources/plex/index.md
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Plex
|
||||
---
|
||||
|
||||
Allows users to authenticate using their Plex credentials
|
||||
|
||||
## Preparation
|
||||
|
||||
None
|
||||
|
||||
## Authentik -> Sources
|
||||
|
||||
Add _Plex_ as a _source_
|
||||
|
||||
- Name: Choose a name
|
||||
- Slug: Set a slug
|
||||
- Client ID: Set a unique Client Id or leave the generated ID
|
||||
- Press _Load Servers_ to login to plex and pick the authorized Plex Servers for "allowed users"
|
||||
- Decide if *anyone* with a plex account can authenticate or only friends you share with
|
||||
|
||||
Save, and you now have Plex as a source.
|
||||
7
website/docs/integrations/sources/saml/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: SAML
|
||||
---
|
||||
|
||||
## SAML Source
|
||||
|
||||
This source allows authentik to act as a SAML Service Provider. Just like the SAML Provider, it supports signed requests. Vendor-specific documentation can be found in the Integrations Section.
|
||||
@ -11,7 +11,7 @@ version: "3.5"
|
||||
|
||||
services:
|
||||
authentik_proxy:
|
||||
image: ghcr.io/goauthentik/proxy:2021.6.1-rc6
|
||||
image: ghcr.io/goauthentik/proxy:2021.6.2
|
||||
ports:
|
||||
- 4180:4180
|
||||
- 4443:4443
|
||||
@ -21,7 +21,7 @@ services:
|
||||
AUTHENTIK_TOKEN: token-generated-by-authentik
|
||||
# Or, for the LDAP Outpost
|
||||
authentik_proxy:
|
||||
image: ghcr.io/goauthentik/ldap:2021.6.1-rc6
|
||||
image: ghcr.io/goauthentik/ldap:2021.6.2
|
||||
ports:
|
||||
- 389:3389
|
||||
environment:
|
||||
|
||||