Compare commits
70 Commits
version/20
...
version/20
Author | SHA1 | Date | |
---|---|---|---|
e0f48a30b7 | |||
973f14d911 | |||
e8978adc1b | |||
3ca8d9c968 | |||
42636142fa | |||
57c459348f | |||
493b34cf0d | |||
f0493f418b | |||
d45a292652 | |||
b21ea360db | |||
6816f8b851 | |||
de714f0390 | |||
800df332b5 | |||
16c194d2dc | |||
53100a72fe | |||
ec4c3f44cb | |||
f10bd432b3 | |||
4de927ba5b | |||
74e578c2bf | |||
e584fd1344 | |||
0e02925a3d | |||
5b837c3ccc | |||
2580371f94 | |||
4e9be85353 | |||
79508e1965 | |||
3a88dde545 | |||
31fc4d1cb9 | |||
09cd8f8f63 | |||
d824b09365 | |||
cabbd18880 | |||
c9dda17c68 | |||
bb8559ee18 | |||
5ae32e525c | |||
0832145a01 | |||
4167276c8f | |||
afb84c7bc5 | |||
82b2c7e3f0 | |||
fc8004db2b | |||
ddfc943bba | |||
8c0c12292e | |||
803490d98b | |||
16835ab478 | |||
572b8d87b5 | |||
31d2ea65fd | |||
f4ac2f50e2 | |||
969a3f0ddd | |||
4e18f47f28 | |||
f10286edf8 | |||
d789dcc28f | |||
715a71427e | |||
84c21d16cf | |||
2e4e17adb7 | |||
00cbaaf672 | |||
74e4e8f6aa | |||
d78fda990a | |||
10d949f7a9 | |||
6661af032d | |||
fb5e4a3af8 | |||
1dfad83a34 | |||
70025c648c | |||
676b77aa7c | |||
e35e096266 | |||
7af12d4fec | |||
8d6db0fabf | |||
8ddcf99bf7 | |||
e25f6aea8c | |||
b1a9eda1d3 | |||
2c15ab9995 | |||
b3c51e426d | |||
71578af47f |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 2021.6.1-rc2
|
||||
current_version = 2021.6.1-rc6
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
|
||||
|
@ -1,5 +1,4 @@
|
||||
env
|
||||
helm
|
||||
static
|
||||
htmlcov
|
||||
*.env.yml
|
||||
|
44
.github/workflows/release.yml
vendored
44
.github/workflows/release.yml
vendored
@ -33,12 +33,22 @@ jobs:
|
||||
with:
|
||||
push: ${{ github.event_name == 'release' }}
|
||||
tags: |
|
||||
beryju/authentik:2021.6.1-rc2,
|
||||
beryju/authentik:2021.6.1-rc6,
|
||||
beryju/authentik:latest,
|
||||
ghcr.io/goauthentik/server:2021.6.1-rc2,
|
||||
ghcr.io/goauthentik/server:2021.6.1-rc6,
|
||||
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: .
|
||||
build-proxy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -66,12 +76,22 @@ jobs:
|
||||
with:
|
||||
push: ${{ github.event_name == 'release' }}
|
||||
tags: |
|
||||
beryju/authentik-proxy:2021.6.1-rc2,
|
||||
beryju/authentik-proxy:2021.6.1-rc6,
|
||||
beryju/authentik-proxy:latest,
|
||||
ghcr.io/goauthentik/proxy:2021.6.1-rc2,
|
||||
ghcr.io/goauthentik/proxy:2021.6.1-rc6,
|
||||
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: .
|
||||
build-ldap:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -99,12 +119,22 @@ jobs:
|
||||
with:
|
||||
push: ${{ github.event_name == 'release' }}
|
||||
tags: |
|
||||
beryju/authentik-ldap:2021.6.1-rc2,
|
||||
beryju/authentik-ldap:2021.6.1-rc6,
|
||||
beryju/authentik-ldap:latest,
|
||||
ghcr.io/goauthentik/ldap:2021.6.1-rc2,
|
||||
ghcr.io/goauthentik/ldap:2021.6.1-rc6,
|
||||
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: .
|
||||
test-release:
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
needs:
|
||||
@ -138,5 +168,5 @@ jobs:
|
||||
SENTRY_PROJECT: authentik
|
||||
SENTRY_URL: https://sentry.beryju.org
|
||||
with:
|
||||
version: authentik@2021.6.1-rc2
|
||||
version: authentik@2021.6.1-rc6
|
||||
environment: beryjuorg-prod
|
||||
|
4
.github/workflows/tag.yml
vendored
4
.github/workflows/tag.yml
vendored
@ -20,11 +20,11 @@ jobs:
|
||||
docker-compose pull -q
|
||||
docker build \
|
||||
--no-cache \
|
||||
-t beryju/authentik:latest \
|
||||
-t ghcr.io/goauthentik/server:latest \
|
||||
-f Dockerfile .
|
||||
docker-compose up --no-start
|
||||
docker-compose start postgresql redis
|
||||
docker-compose run -u root --entrypoint /bin/bash server -c "apt-get update && apt-get install -y --no-install-recommends git && pip install --no-cache -r requirements-dev.txt && ./manage.py test authentik"
|
||||
docker-compose run -u root server test
|
||||
- name: Extract version number
|
||||
id: get_version
|
||||
uses: actions/github-script@v4.0.2
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -193,10 +193,6 @@ pip-selfcheck.json
|
||||
local.env.yml
|
||||
.vscode/
|
||||
|
||||
### Helm ###
|
||||
# Chart dependencies
|
||||
**/charts/*.tgz
|
||||
|
||||
# Selenium Screenshots
|
||||
selenium_screenshots/
|
||||
backups/
|
||||
|
111
Pipfile.lock
generated
111
Pipfile.lock
generated
@ -56,6 +56,7 @@
|
||||
"sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a",
|
||||
"sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.7.4.post0"
|
||||
},
|
||||
"aioredis": {
|
||||
@ -70,6 +71,7 @@
|
||||
"sha256:03e16e94f2b34c31f8bf1206d8ddd3ccaa4c315f7f6a1879b7b1210d229568c2",
|
||||
"sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==5.0.6"
|
||||
},
|
||||
"asgiref": {
|
||||
@ -77,6 +79,7 @@
|
||||
"sha256:92906c611ce6c967347bbfea733f13d6313901d54dcca88195eaeb52b2a8e8ee",
|
||||
"sha256:d1216dfbdfb63826470995d31caed36225dcaf34f182e0fa257a4dd9e86f1b78"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.3.4"
|
||||
},
|
||||
"async-timeout": {
|
||||
@ -84,6 +87,7 @@
|
||||
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
|
||||
"sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
|
||||
],
|
||||
"markers": "python_full_version >= '3.5.3'",
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"attrs": {
|
||||
@ -91,6 +95,7 @@
|
||||
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
|
||||
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==21.2.0"
|
||||
},
|
||||
"autobahn": {
|
||||
@ -98,6 +103,7 @@
|
||||
"sha256:9195df8af03b0ff29ccd4b7f5abbde957ee90273465942205f9a1bad6c3f07ac",
|
||||
"sha256:e126c1f583e872fb59e79d36977cfa1f2d0a8a79f90ae31f406faae7664b8e03"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==21.3.1"
|
||||
},
|
||||
"automat": {
|
||||
@ -116,23 +122,26 @@
|
||||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:4cfab400cd9ca9b27b7dffb43f5675525ea5d36c81223d64d15542fdb16cdf7e",
|
||||
"sha256:b0808a58c54c595b6cc6271cbc14a09bb89f0951ca9e8b105d1e94bef3ed24a0"
|
||||
"sha256:6180272094030bda3ee5c242881892cd3d9d19c05cb513945f530e396c7de1e4",
|
||||
"sha256:95d814d16fe55ae55e1e4a3db248596f9647a0c42f4796c6e05be0bfaffb1830"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.17.91"
|
||||
"version": "==1.17.94"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:462e75419e6537efb2709b7eb5b8c7ade007d30209416f0476bd7c51a2ddc78d"
|
||||
"sha256:60a382a5b2f7d77b1b575d54fba819097526e3fdd0f3004f4d1142d50af0d642",
|
||||
"sha256:ba8a7951be535e25219a82dea15c30d7bdf0c51e7c1623c3306248493c1616ac"
|
||||
],
|
||||
"version": "==1.20.91"
|
||||
"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"
|
||||
},
|
||||
"cachetools": {
|
||||
"hashes": [
|
||||
"sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001",
|
||||
"sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff"
|
||||
],
|
||||
"markers": "python_version ~= '3.5'",
|
||||
"version": "==4.2.2"
|
||||
},
|
||||
"cbor2": {
|
||||
@ -151,6 +160,7 @@
|
||||
"sha256:ce6219986385778b1ab7f9b542f160bb4d3558f52975e914a27b774e47016fb7",
|
||||
"sha256:d562b2773e14ee1d65ea5b85351a83a64d4f3fd011bc2b4c70a6e813e78203ce"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==5.4.0"
|
||||
},
|
||||
"celery": {
|
||||
@ -243,6 +253,7 @@
|
||||
"sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
|
||||
"sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==4.0.0"
|
||||
},
|
||||
"click": {
|
||||
@ -250,6 +261,7 @@
|
||||
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
|
||||
"sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==7.1.2"
|
||||
},
|
||||
"click-didyoumean": {
|
||||
@ -309,6 +321,7 @@
|
||||
"sha256:76ffae916ba3aa66b46996c14fa713e46004788167a4873d647544e750e0e99f",
|
||||
"sha256:a9af943c79717bc52fe64a3c236ae5d3adccc8b5be19c881b442d2c3db233393"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.2"
|
||||
},
|
||||
"defusedxml": {
|
||||
@ -413,11 +426,11 @@
|
||||
},
|
||||
"drf-spectacular": {
|
||||
"hashes": [
|
||||
"sha256:4d35e890b8139e1c056588c5529a2f2066615635482563f0840b96d3b879d7d2",
|
||||
"sha256:f552476dfde647963c21615249672e7f4f9ece3788036b5ee5c6cc5ad50748ab"
|
||||
"sha256:146e8c21dc806a20c84c687811c30163970fbf620213ab87280f7403469d80bb",
|
||||
"sha256:8a028d251a6d0b39739ebdec487fd43ee4ecba244d8ffaaac43ff06430728dd8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.17.0"
|
||||
"version": "==0.17.1"
|
||||
},
|
||||
"duo-client": {
|
||||
"hashes": [
|
||||
@ -439,6 +452,7 @@
|
||||
"hashes": [
|
||||
"sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==0.18.2"
|
||||
},
|
||||
"geoip2": {
|
||||
@ -451,10 +465,11 @@
|
||||
},
|
||||
"google-auth": {
|
||||
"hashes": [
|
||||
"sha256:9b235dbc876e49454cbedc52ae0abd540ef705ebccdf4fbe93553bb13f26b1a4",
|
||||
"sha256:eb017521276a75492282c6ca4b718f26de112ed3bcbeaeeb02c1b82de425f909"
|
||||
"sha256:154f7889c5d679a6f626f36adb12afbd4dbb0a9a04ec575d989d6ba79c4fd65e",
|
||||
"sha256:6d47c79b5d09fbc7e8355fd9594cc4cf65fdde5d401c63951eaac4baa1ba2ae1"
|
||||
],
|
||||
"version": "==1.30.2"
|
||||
"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"
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
@ -469,6 +484,7 @@
|
||||
"sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6",
|
||||
"sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.12.0"
|
||||
},
|
||||
"hiredis": {
|
||||
@ -515,6 +531,7 @@
|
||||
"sha256:f52010e0a44e3d8530437e7da38d11fb822acfb0d5b12e9cd5ba655509937ca0",
|
||||
"sha256:f8196f739092a78e4f6b1b2172679ed3343c39c61a3e9d722ce6fcf1dac2824a"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.0.0"
|
||||
},
|
||||
"httptools": {
|
||||
@ -563,6 +580,7 @@
|
||||
"sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417",
|
||||
"sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==0.5.1"
|
||||
},
|
||||
"jmespath": {
|
||||
@ -570,6 +588,7 @@
|
||||
"sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9",
|
||||
"sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==0.10.0"
|
||||
},
|
||||
"jsonschema": {
|
||||
@ -584,6 +603,7 @@
|
||||
"sha256:01481d99f4606f6939cdc9b637264ed353ee9e3e4f62cfb582324142c41a572d",
|
||||
"sha256:e2dedd8a86c9077c350555153825a31e456a0dc20c15d5751f00137ec9c75f0a"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==5.1.0"
|
||||
},
|
||||
"kubernetes": {
|
||||
@ -597,6 +617,9 @@
|
||||
"ldap3": {
|
||||
"hashes": [
|
||||
"sha256:18c3ee656a6775b9b0d60f7c6c5b094d878d1d90fc03d56731039f0a4b546a91",
|
||||
"sha256:4139c91f0eef9782df7b77c8cbc6243086affcb6a8a249b768a9658438e5da59",
|
||||
"sha256:8c949edbad2be8a03e719ba48bd6779f327ec156929562814b3e84ab56889c8c",
|
||||
"sha256:afc6fc0d01f02af82cd7bfabd3bbfd5dc96a6ae91e97db0a2dab8a0f1b436056",
|
||||
"sha256:c1df41d89459be6f304e0ceec4b00fdea533dbbcd83c802b1272dcdb94620b57"
|
||||
],
|
||||
"index": "pypi",
|
||||
@ -658,6 +681,7 @@
|
||||
"hashes": [
|
||||
"sha256:47e86a084dd814fac88c99ea34ba3278a74bc9de5a25f4b815b608798747c7dc"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.0.3"
|
||||
},
|
||||
"msgpack": {
|
||||
@ -733,6 +757,7 @@
|
||||
"sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281",
|
||||
"sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==5.1.0"
|
||||
},
|
||||
"oauthlib": {
|
||||
@ -740,6 +765,7 @@
|
||||
"sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc",
|
||||
"sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.1.1"
|
||||
},
|
||||
"packaging": {
|
||||
@ -755,6 +781,7 @@
|
||||
"sha256:3a8baade6cb80bcfe43297e33e7623f3118d660d41387593758e2fb1ea173a86",
|
||||
"sha256:b014bc76815eb1399da8ce5fc84b7717a3e63652b0c0f8804092c9363acab1b2"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==0.11.0"
|
||||
},
|
||||
"prompt-toolkit": {
|
||||
@ -762,6 +789,7 @@
|
||||
"sha256:bf00f22079f5fadc949f42ae8ff7f05702826a97059ffcc6281036ad40ac6f04",
|
||||
"sha256:e1b4f11b9336a28fa11810bc623c357420f69dfdb6d2dac41ca2c21a55c033bc"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.1'",
|
||||
"version": "==3.0.18"
|
||||
},
|
||||
"psycopg2-binary": {
|
||||
@ -807,15 +835,37 @@
|
||||
},
|
||||
"pyasn1": {
|
||||
"hashes": [
|
||||
"sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
|
||||
"sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576",
|
||||
"sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf",
|
||||
"sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7",
|
||||
"sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
|
||||
"sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"
|
||||
"sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00",
|
||||
"sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8",
|
||||
"sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86",
|
||||
"sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12",
|
||||
"sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776",
|
||||
"sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
|
||||
"sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2",
|
||||
"sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"
|
||||
],
|
||||
"version": "==0.4.8"
|
||||
},
|
||||
"pyasn1-modules": {
|
||||
"hashes": [
|
||||
"sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8",
|
||||
"sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199",
|
||||
"sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811",
|
||||
"sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed",
|
||||
"sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4",
|
||||
"sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e",
|
||||
"sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"
|
||||
"sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74",
|
||||
"sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb",
|
||||
"sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45",
|
||||
"sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd",
|
||||
"sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0",
|
||||
"sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d",
|
||||
"sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"
|
||||
],
|
||||
"version": "==0.2.8"
|
||||
},
|
||||
@ -824,6 +874,7 @@
|
||||
"sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
|
||||
"sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.20"
|
||||
},
|
||||
"pycryptodome": {
|
||||
@ -867,6 +918,7 @@
|
||||
"sha256:412e00137858f04bde0729913874a48485665f2d36fe9ee449f26be864af9316",
|
||||
"sha256:7ead136e03655af85069b6f47b23eb7c3e5c221aa9f022a4fbb499f5b7308f29"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==2.0.2"
|
||||
},
|
||||
"pyjwt": {
|
||||
@ -889,12 +941,14 @@
|
||||
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
|
||||
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.4.7"
|
||||
},
|
||||
"pyrsistent": {
|
||||
"hashes": [
|
||||
"sha256:2e636185d9eb976a18a8a8e96efce62f2905fea90041958d8cc2a189756ebf3e"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==0.17.3"
|
||||
},
|
||||
"python-dateutil": {
|
||||
@ -902,6 +956,7 @@
|
||||
"sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
|
||||
"sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.8.1"
|
||||
},
|
||||
"python-dotenv": {
|
||||
@ -958,6 +1013,7 @@
|
||||
"sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2",
|
||||
"sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==3.5.3"
|
||||
},
|
||||
"requests": {
|
||||
@ -965,12 +1021,14 @@
|
||||
"sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
|
||||
"sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==2.25.1"
|
||||
},
|
||||
"requests-oauthlib": {
|
||||
"hashes": [
|
||||
"sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d",
|
||||
"sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"
|
||||
"sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a",
|
||||
"sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.3.0"
|
||||
@ -1011,6 +1069,7 @@
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"sqlparse": {
|
||||
@ -1018,6 +1077,7 @@
|
||||
"sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0",
|
||||
"sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==0.4.1"
|
||||
},
|
||||
"structlog": {
|
||||
@ -1073,6 +1133,7 @@
|
||||
"sha256:7d6f89745680233f1c4db9ddb748df5e88d2a7a37962be174c0fd04c8dba1dc8",
|
||||
"sha256:c16b55f9a67b2419cfdf8846576e2ec9ba94fe6978a83080c352a80db31c93fb"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==21.2.1"
|
||||
},
|
||||
"typing-extensions": {
|
||||
@ -1096,6 +1157,7 @@
|
||||
"sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f",
|
||||
"sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"urllib3": {
|
||||
@ -1140,6 +1202,7 @@
|
||||
"sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30",
|
||||
"sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==5.0.0"
|
||||
},
|
||||
"watchgod": {
|
||||
@ -1169,6 +1232,7 @@
|
||||
"sha256:b68e4959d704768fa20e35c9d508c8dc2bbc041fd8d267c0d7345cffe2824568",
|
||||
"sha256:e5c333bfa9fa739538b652b6f8c8fc2559f1d364243c8a689d7c0e1d41c2e611"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"websockets": {
|
||||
@ -1266,6 +1330,7 @@
|
||||
"sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a",
|
||||
"sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.6.3"
|
||||
},
|
||||
"zope.interface": {
|
||||
@ -1322,6 +1387,7 @@
|
||||
"sha256:f44e517131a98f7a76696a7b21b164bcb85291cee106a23beccce454e1f433a4",
|
||||
"sha256:f7ee479e96f7ee350db1cf24afa5685a5899e2b34992fb99e1f7c1b0b758d263"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==5.4.0"
|
||||
}
|
||||
},
|
||||
@ -1338,6 +1404,7 @@
|
||||
"sha256:4db03ab5fc3340cf619dbc25e42c2cc3755154ce6009469766d7143d1fc2ee4e",
|
||||
"sha256:8a398dfce302c13f14bab13e2b14fe385d32b73f4e4853b9bdfb64598baa1975"
|
||||
],
|
||||
"markers": "python_version ~= '3.6'",
|
||||
"version": "==2.5.6"
|
||||
},
|
||||
"attrs": {
|
||||
@ -1345,6 +1412,7 @@
|
||||
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
|
||||
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==21.2.0"
|
||||
},
|
||||
"bandit": {
|
||||
@ -1383,6 +1451,7 @@
|
||||
"sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
|
||||
"sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==4.0.0"
|
||||
},
|
||||
"click": {
|
||||
@ -1390,6 +1459,7 @@
|
||||
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
|
||||
"sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==7.1.2"
|
||||
},
|
||||
"colorama": {
|
||||
@ -1463,6 +1533,7 @@
|
||||
"sha256:6c4cc71933456991da20917998acbe6cf4fb41eeaab7d6d67fbc05ecd4c865b0",
|
||||
"sha256:96bf5c08b157a666fec41129e6d327235284cca4c81e92109260f353ba138005"
|
||||
],
|
||||
"markers": "python_version >= '3.4'",
|
||||
"version": "==4.0.7"
|
||||
},
|
||||
"gitpython": {
|
||||
@ -1470,6 +1541,7 @@
|
||||
"sha256:29fe82050709760081f588dd50ce83504feddbebdc4da6956d02351552b1c135",
|
||||
"sha256:ee24bdc93dce357630764db659edaf6b8d664d4ff5447ccfeedd2dc5c253f41e"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==3.1.17"
|
||||
},
|
||||
"idna": {
|
||||
@ -1491,6 +1563,7 @@
|
||||
"sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6",
|
||||
"sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"
|
||||
],
|
||||
"markers": "python_version >= '3.6' and python_version < '4'",
|
||||
"version": "==5.8.0"
|
||||
},
|
||||
"lazy-object-proxy": {
|
||||
@ -1518,6 +1591,7 @@
|
||||
"sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93",
|
||||
"sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||
"version": "==1.6.0"
|
||||
},
|
||||
"mccabe": {
|
||||
@ -1554,6 +1628,7 @@
|
||||
"sha256:42df03e7797b796625b1029c0400279c7c34fd7df24a7d7818a1abb5b38710dd",
|
||||
"sha256:c68c661ac5cc81058ac94247278eeda6d2e6aecb3e227b0387c30d277e7ef8d4"
|
||||
],
|
||||
"markers": "python_version >= '2.6'",
|
||||
"version": "==5.6.0"
|
||||
},
|
||||
"pluggy": {
|
||||
@ -1561,6 +1636,7 @@
|
||||
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
|
||||
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==0.13.1"
|
||||
},
|
||||
"py": {
|
||||
@ -1568,6 +1644,7 @@
|
||||
"sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3",
|
||||
"sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.10.0"
|
||||
},
|
||||
"pylint": {
|
||||
@ -1598,6 +1675,7 @@
|
||||
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
|
||||
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.4.7"
|
||||
},
|
||||
"pytest": {
|
||||
@ -1702,6 +1780,7 @@
|
||||
"sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
|
||||
"sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==2.25.1"
|
||||
},
|
||||
"requests-mock": {
|
||||
@ -1725,6 +1804,7 @@
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"smmap": {
|
||||
@ -1732,6 +1812,7 @@
|
||||
"sha256:7e65386bd122d45405ddf795637b7f7d2b532e7e401d46bbe3fb49b9986d5182",
|
||||
"sha256:a9a7479e4c572e2e775c404dcd3080c8dc49f39918c2cf74913d30c4c478e3c2"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==4.0.0"
|
||||
},
|
||||
"stevedore": {
|
||||
@ -1739,6 +1820,7 @@
|
||||
"sha256:3a5bbd0652bf552748871eaa73a4a8dc2899786bc497a2aa1fcb4dcdb0debeee",
|
||||
"sha256:50d7b78fbaf0d04cd62411188fa7eedcb03eb7f4c4b37005615ceebe582aa82a"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.3.0"
|
||||
},
|
||||
"toml": {
|
||||
@ -1746,6 +1828,7 @@
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==0.10.2"
|
||||
},
|
||||
"urllib3": {
|
||||
|
@ -21,7 +21,7 @@ authentik is an open-source Identity Provider focused on flexibility and versati
|
||||
|
||||
For small/test setups it is recommended to use docker-compose, see the [documentation](https://goauthentik.io/docs/installation/docker-compose/)
|
||||
|
||||
For bigger setups, there is a Helm Chart in the `helm/` directory. This is documented [here](https://goauthentik.io/docs/installation/kubernetes/)
|
||||
For bigger setups, there is a Helm Chart [here])(https://github.com/goauthentik/helm). This is documented [here](https://goauthentik.io/docs/installation/kubernetes/)
|
||||
|
||||
## Screenshots
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
"""authentik"""
|
||||
__version__ = "2021.6.1-rc2"
|
||||
__version__ = "2021.6.1-rc6"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
@ -10,3 +10,25 @@ class AuthentikAPIConfig(AppConfig):
|
||||
label = "authentik_api"
|
||||
mountpoint = "api/"
|
||||
verbose_name = "authentik API"
|
||||
|
||||
def ready(self) -> None:
|
||||
from drf_spectacular.extensions import OpenApiAuthenticationExtension
|
||||
|
||||
from authentik.api.authentication import TokenAuthentication
|
||||
|
||||
# Class is defined here as it needs to be created early enough that drf-spectacular will
|
||||
# find it, but also won't cause any import issues
|
||||
# pylint: disable=unused-variable
|
||||
class TokenSchema(OpenApiAuthenticationExtension):
|
||||
"""Auth schema"""
|
||||
|
||||
target_class = TokenAuthentication
|
||||
name = "authentik"
|
||||
|
||||
def get_security_definition(self, auto_schema):
|
||||
"""Auth schema"""
|
||||
return {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": "Authorization",
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ from base64 import b64decode
|
||||
from binascii import Error
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from drf_spectacular.authentication import OpenApiAuthenticationExtension
|
||||
from rest_framework.authentication import BaseAuthentication, get_authorization_header
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
from rest_framework.request import Request
|
||||
@ -56,18 +55,3 @@ class TokenAuthentication(BaseAuthentication):
|
||||
return None
|
||||
|
||||
return (token.user, None) # pragma: no cover
|
||||
|
||||
|
||||
class TokenSchema(OpenApiAuthenticationExtension):
|
||||
"""Auth schema"""
|
||||
|
||||
target_class = TokenAuthentication
|
||||
name = "authentik"
|
||||
|
||||
def get_security_definition(self, auto_schema):
|
||||
"""Auth schema"""
|
||||
return {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": "Authorization",
|
||||
}
|
||||
|
@ -11,13 +11,7 @@ from drf_spectacular.utils import (
|
||||
inline_serializer,
|
||||
)
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.fields import (
|
||||
BooleanField,
|
||||
CharField,
|
||||
FileField,
|
||||
IntegerField,
|
||||
ReadOnlyField,
|
||||
)
|
||||
from rest_framework.fields import BooleanField, CharField, FileField, ReadOnlyField
|
||||
from rest_framework.parsers import MultiPartParser
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
@ -107,15 +101,19 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
|
||||
return applications
|
||||
|
||||
@extend_schema(
|
||||
request=inline_serializer(
|
||||
"CheckAccessRequest", fields={"for_user": IntegerField(required=False)}
|
||||
),
|
||||
parameters=[
|
||||
OpenApiParameter(
|
||||
name="for_user",
|
||||
location=OpenApiParameter.QUERY,
|
||||
type=OpenApiTypes.INT,
|
||||
)
|
||||
],
|
||||
responses={
|
||||
200: PolicyTestResultSerializer(),
|
||||
404: OpenApiResponse(description="for_user user not found"),
|
||||
},
|
||||
)
|
||||
@action(detail=True, methods=["POST"])
|
||||
@action(detail=True, methods=["GET"])
|
||||
# pylint: disable=unused-argument
|
||||
def check_access(self, request: Request, slug: str) -> Response:
|
||||
"""Check access to a single application by slug"""
|
||||
@ -204,7 +202,7 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
|
||||
"""Set application icon"""
|
||||
app: Application = self.get_object()
|
||||
icon = request.FILES.get("file", None)
|
||||
clear = request.data.get("clear", False)
|
||||
clear = request.data.get("clear", "false").lower() == "true"
|
||||
if clear:
|
||||
# .delete() saves the model by default
|
||||
app.meta_icon.delete()
|
||||
|
@ -26,6 +26,8 @@ class ImpersonateMiddleware:
|
||||
|
||||
if SESSION_IMPERSONATE_USER in request.session:
|
||||
request.user = request.session[SESSION_IMPERSONATE_USER]
|
||||
# Ensure that the user is active, otherwise nothing will work
|
||||
request.user.is_active = True
|
||||
|
||||
return self.get_response(request)
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
"""authentik core signals"""
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Type
|
||||
|
||||
from django.contrib.auth.signals import user_logged_in, user_logged_out
|
||||
from django.contrib.sessions.backends.cache import KEY_PREFIX
|
||||
from django.core.cache import cache
|
||||
from django.core.signals import Signal
|
||||
from django.db.models import Model
|
||||
from django.db.models.signals import post_save
|
||||
from django.db.models.signals import post_save, pre_delete
|
||||
from django.dispatch import receiver
|
||||
from django.http.request import HttpRequest
|
||||
from prometheus_client import Gauge
|
||||
@ -18,7 +19,7 @@ GAUGE_MODELS = Gauge(
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from authentik.core.models import User
|
||||
from authentik.core.models import AuthenticatedSession, User
|
||||
|
||||
|
||||
@receiver(post_save)
|
||||
@ -60,3 +61,17 @@ def user_logged_out_session(sender, request: HttpRequest, user: "User", **_):
|
||||
AuthenticatedSession.objects.filter(
|
||||
session_key=request.session.session_key
|
||||
).delete()
|
||||
|
||||
|
||||
@receiver(pre_delete)
|
||||
def authenticated_session_delete(
|
||||
sender: Type[Model], instance: "AuthenticatedSession", **_
|
||||
):
|
||||
"""Delete session when authenticated session is deleted"""
|
||||
from authentik.core.models import AuthenticatedSession
|
||||
|
||||
if sender != AuthenticatedSession:
|
||||
return
|
||||
|
||||
cache_key = f"{KEY_PREFIX}{instance.session_key}"
|
||||
cache.delete(cache_key)
|
||||
|
@ -33,6 +33,7 @@ from authentik.flows.planner import (
|
||||
from authentik.flows.views import NEXT_ARG_NAME, SESSION_KEY_GET, SESSION_KEY_PLAN
|
||||
from authentik.lib.utils.urls import redirect_with_qs
|
||||
from authentik.policies.utils import delete_none_keys
|
||||
from authentik.stages.password import BACKEND_DJANGO
|
||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
|
||||
|
||||
@ -198,7 +199,7 @@ class SourceFlowManager:
|
||||
kwargs.update(
|
||||
{
|
||||
# Since we authenticate the user by their token, they have no backend set
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: "django.contrib.auth.backends.ModelBackend",
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: BACKEND_DJANGO,
|
||||
PLAN_CONTEXT_SSO: True,
|
||||
PLAN_CONTEXT_SOURCE: self.source,
|
||||
PLAN_CONTEXT_REDIRECT: final_redirect,
|
||||
|
@ -3,16 +3,6 @@
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block head %}
|
||||
{{ block.super }}
|
||||
<style>
|
||||
.pf-c-background-image::before {
|
||||
background-image: url("{% static 'dist/assets/images/flow_background.jpg' %}");
|
||||
background-position: center;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
{% trans 'End session' %} - {{ tenant.branding_title }}
|
||||
{% endblock %}
|
||||
|
@ -26,7 +26,7 @@ class TestApplicationsAPI(APITestCase):
|
||||
def test_check_access(self):
|
||||
"""Test check_access operation"""
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.post(
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"authentik_api:application-check-access",
|
||||
kwargs={"slug": self.allowed.slug},
|
||||
@ -36,7 +36,7 @@ class TestApplicationsAPI(APITestCase):
|
||||
self.assertJSONEqual(
|
||||
force_str(response.content), {"messages": [], "passing": True}
|
||||
)
|
||||
response = self.client.post(
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"authentik_api:application-check-access",
|
||||
kwargs={"slug": self.denied.slug},
|
||||
|
@ -17,6 +17,9 @@ class TestImpersonation(TestCase):
|
||||
|
||||
def test_impersonate_simple(self):
|
||||
"""test simple impersonation and un-impersonation"""
|
||||
# test with an inactive user to ensure that still works
|
||||
self.other_user.is_active = False
|
||||
self.other_user.save()
|
||||
self.client.force_login(self.akadmin)
|
||||
|
||||
self.client.get(
|
||||
|
@ -2,7 +2,7 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from rest_framework.fields import CharField, DictField
|
||||
from rest_framework.fields import CharField
|
||||
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
from authentik.flows.challenge import Challenge
|
||||
@ -22,18 +22,10 @@ class UILoginButton:
|
||||
icon_url: Optional[str] = None
|
||||
|
||||
|
||||
class UILoginButtonSerializer(PassiveSerializer):
|
||||
"""Serializer for Login buttons of sources"""
|
||||
|
||||
name = CharField()
|
||||
challenge = DictField()
|
||||
icon_url = CharField(required=False, allow_null=True)
|
||||
|
||||
|
||||
class UserSettingSerializer(PassiveSerializer):
|
||||
"""Serializer for User settings for stages and sources"""
|
||||
|
||||
object_uid = CharField()
|
||||
component = CharField()
|
||||
title = CharField()
|
||||
configure_url = CharField()
|
||||
configure_url = CharField(required=False)
|
||||
|
@ -36,6 +36,7 @@ class EventSerializer(ModelSerializer):
|
||||
"client_ip",
|
||||
"created",
|
||||
"expires",
|
||||
"tenant",
|
||||
]
|
||||
|
||||
|
||||
@ -76,6 +77,11 @@ class EventsFilter(django_filters.FilterSet):
|
||||
field_name="action",
|
||||
lookup_expr="icontains",
|
||||
)
|
||||
tenant_name = django_filters.CharFilter(
|
||||
field_name="tenant",
|
||||
lookup_expr="name",
|
||||
label="Tenant name",
|
||||
)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def filter_context_model_pk(self, queryset, name, value):
|
||||
|
@ -40,9 +40,9 @@ class GeoIPReader:
|
||||
return
|
||||
try:
|
||||
reader = Reader(path)
|
||||
LOGGER.info("Loaded GeoIP database")
|
||||
self.__reader = reader
|
||||
self.__last_mtime = stat(path).st_mtime
|
||||
LOGGER.info("Loaded GeoIP database", last_write=self.__last_mtime)
|
||||
except OSError as exc:
|
||||
LOGGER.warning("Failed to load GeoIP database", exc=exc)
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
from functools import partial
|
||||
from typing import Callable
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.models import Model
|
||||
from django.db.models.signals import post_save, pre_delete
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
@ -12,6 +13,7 @@ from authentik.core.models import User
|
||||
from authentik.events.models import Event, EventAction, Notification
|
||||
from authentik.events.signals import EventNewThread
|
||||
from authentik.events.utils import model_to_dict
|
||||
from authentik.lib.utils.errors import exception_to_string
|
||||
|
||||
|
||||
class AuditMiddleware:
|
||||
@ -54,10 +56,19 @@ class AuditMiddleware:
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def process_exception(self, request: HttpRequest, exception: Exception):
|
||||
"""Unregister handlers in case of exception"""
|
||||
"""Disconnect handlers in case of exception"""
|
||||
post_save.disconnect(dispatch_uid=LOCAL.authentik["request_id"])
|
||||
pre_delete.disconnect(dispatch_uid=LOCAL.authentik["request_id"])
|
||||
|
||||
if settings.DEBUG:
|
||||
return
|
||||
thread = EventNewThread(
|
||||
EventAction.SYSTEM_EXCEPTION,
|
||||
request,
|
||||
message=exception_to_string(exception),
|
||||
)
|
||||
thread.run()
|
||||
|
||||
@staticmethod
|
||||
# pylint: disable=unused-argument
|
||||
def post_save_handler(
|
||||
|
55
authentik/events/migrations/0016_add_tenant.py
Normal file
55
authentik/events/migrations/0016_add_tenant.py
Normal file
@ -0,0 +1,55 @@
|
||||
# Generated by Django 3.2.4 on 2021-06-14 15:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import authentik.events.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_events", "0015_alter_event_action"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="event",
|
||||
name="tenant",
|
||||
field=models.JSONField(
|
||||
blank=True, default=authentik.events.models.default_tenant
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="event",
|
||||
name="action",
|
||||
field=models.TextField(
|
||||
choices=[
|
||||
("login", "Login"),
|
||||
("login_failed", "Login Failed"),
|
||||
("logout", "Logout"),
|
||||
("user_write", "User Write"),
|
||||
("suspicious_request", "Suspicious Request"),
|
||||
("password_set", "Password Set"),
|
||||
("secret_view", "Secret View"),
|
||||
("invitation_used", "Invite Used"),
|
||||
("authorize_application", "Authorize Application"),
|
||||
("source_linked", "Source Linked"),
|
||||
("impersonation_started", "Impersonation Started"),
|
||||
("impersonation_ended", "Impersonation Ended"),
|
||||
("policy_execution", "Policy Execution"),
|
||||
("policy_exception", "Policy Exception"),
|
||||
("property_mapping_exception", "Property Mapping Exception"),
|
||||
("system_task_execution", "System Task Execution"),
|
||||
("system_task_exception", "System Task Exception"),
|
||||
("system_exception", "System Exception"),
|
||||
("configuration_error", "Configuration Error"),
|
||||
("model_created", "Model Created"),
|
||||
("model_updated", "Model Updated"),
|
||||
("model_deleted", "Model Deleted"),
|
||||
("email_sent", "Email Sent"),
|
||||
("update_available", "Update Available"),
|
||||
("custom_", "Custom Prefix"),
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
@ -21,11 +21,12 @@ from authentik.core.middleware import (
|
||||
)
|
||||
from authentik.core.models import ExpiringModel, Group, User
|
||||
from authentik.events.geo import GEOIP_READER
|
||||
from authentik.events.utils import cleanse_dict, get_user, sanitize_dict
|
||||
from authentik.events.utils import cleanse_dict, get_user, model_to_dict, sanitize_dict
|
||||
from authentik.lib.sentry import SentryIgnoredException
|
||||
from authentik.lib.utils.http import get_client_ip
|
||||
from authentik.policies.models import PolicyBindingModel
|
||||
from authentik.stages.email.utils import TemplateEmailMessage
|
||||
from authentik.tenants.utils import DEFAULT_TENANT
|
||||
|
||||
LOGGER = get_logger("authentik.events")
|
||||
GAUGE_EVENTS = Gauge(
|
||||
@ -40,6 +41,11 @@ def default_event_duration():
|
||||
return now() + timedelta(days=365)
|
||||
|
||||
|
||||
def default_tenant():
|
||||
"""Get a default value for tenant"""
|
||||
return sanitize_dict(model_to_dict(DEFAULT_TENANT))
|
||||
|
||||
|
||||
class NotificationTransportError(SentryIgnoredException):
|
||||
"""Error raised when a notification fails to be delivered"""
|
||||
|
||||
@ -71,6 +77,7 @@ class EventAction(models.TextChoices):
|
||||
|
||||
SYSTEM_TASK_EXECUTION = "system_task_execution"
|
||||
SYSTEM_TASK_EXCEPTION = "system_task_exception"
|
||||
SYSTEM_EXCEPTION = "system_exception"
|
||||
|
||||
CONFIGURATION_ERROR = "configuration_error"
|
||||
|
||||
@ -94,6 +101,7 @@ class Event(ExpiringModel):
|
||||
context = models.JSONField(default=dict, blank=True)
|
||||
client_ip = models.GenericIPAddressField(null=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
tenant = models.JSONField(default=default_tenant, blank=True)
|
||||
|
||||
# Shadow the expires attribute from ExpiringModel to override the default duration
|
||||
expires = models.DateTimeField(default=default_event_duration)
|
||||
@ -132,6 +140,13 @@ class Event(ExpiringModel):
|
||||
"""Add data from a Django-HttpRequest, allowing the creation of
|
||||
Events independently from requests.
|
||||
`user` arguments optionally overrides user from requests."""
|
||||
if request:
|
||||
self.context["http_request"] = {
|
||||
"path": request.get_full_path(),
|
||||
"method": request.method,
|
||||
}
|
||||
if hasattr(request, "tenant"):
|
||||
self.tenant = sanitize_dict(model_to_dict(request.tenant))
|
||||
if hasattr(request, "user"):
|
||||
original_user = None
|
||||
if hasattr(request, "session"):
|
||||
|
@ -301,10 +301,14 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
|
||||
"""Set Flow background"""
|
||||
flow: Flow = self.get_object()
|
||||
background = request.FILES.get("file", None)
|
||||
clear = request.data.get("clear", False)
|
||||
clear = request.data.get("clear", "false").lower() == "true"
|
||||
if clear:
|
||||
# .delete() saves the model by default
|
||||
flow.background.delete()
|
||||
if flow.background_url.startswith("/media"):
|
||||
# .delete() saves the model by default
|
||||
flow.background.delete()
|
||||
else:
|
||||
flow.background = None
|
||||
flow.save()
|
||||
return Response({})
|
||||
if background:
|
||||
flow.background = background
|
||||
|
@ -93,7 +93,7 @@ class StageViewSet(
|
||||
if not user_settings:
|
||||
continue
|
||||
user_settings.initial_data["object_uid"] = str(stage.pk)
|
||||
if hasattr(stage, "configure_flow"):
|
||||
if hasattr(stage, "configure_flow") and stage.configure_flow:
|
||||
user_settings.initial_data["configure_url"] = reverse(
|
||||
"authentik_flows:configure",
|
||||
kwargs={"stage_uuid": stage.pk},
|
||||
|
@ -6,6 +6,7 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
|
||||
from authentik.flows.models import FlowDesignation
|
||||
from authentik.stages.identification.models import UserFields
|
||||
from authentik.stages.password import BACKEND_DJANGO, BACKEND_LDAP
|
||||
|
||||
|
||||
def create_default_authentication_flow(
|
||||
@ -31,7 +32,7 @@ def create_default_authentication_flow(
|
||||
|
||||
password_stage, _ = PasswordStage.objects.using(db_alias).update_or_create(
|
||||
name="default-authentication-password",
|
||||
defaults={"backends": ["django.contrib.auth.backends.ModelBackend"]},
|
||||
defaults={"backends": [BACKEND_DJANGO, BACKEND_LDAP]},
|
||||
)
|
||||
|
||||
login_stage, _ = UserLoginStage.objects.using(db_alias).update_or_create(
|
||||
|
@ -15,9 +15,6 @@ PREFILL_POLICY_EXPRESSION = """# This policy sets the user for the currently run
|
||||
# by injecting "pending_user"
|
||||
akadmin = ak_user_by(username="akadmin")
|
||||
context["pending_user"] = akadmin
|
||||
# We're also setting the backend for the user, so we can
|
||||
# directly login without having to identify again
|
||||
context["user_backend"] = "django.contrib.auth.backends.ModelBackend"
|
||||
return True"""
|
||||
|
||||
|
||||
|
@ -174,7 +174,7 @@ class FlowExecutorView(APIView):
|
||||
@extend_schema(
|
||||
responses={
|
||||
200: PolymorphicProxySerializer(
|
||||
component_name="FlowChallengeRequest",
|
||||
component_name="ChallengeTypes",
|
||||
serializers=challenge_types(),
|
||||
resource_type_field_name="component",
|
||||
),
|
||||
@ -214,7 +214,7 @@ class FlowExecutorView(APIView):
|
||||
@extend_schema(
|
||||
responses={
|
||||
200: PolymorphicProxySerializer(
|
||||
component_name="FlowChallengeRequest",
|
||||
component_name="ChallengeTypes",
|
||||
serializers=challenge_types(),
|
||||
resource_type_field_name="component",
|
||||
),
|
||||
|
10
authentik/lib/utils/errors.py
Normal file
10
authentik/lib/utils/errors.py
Normal file
@ -0,0 +1,10 @@
|
||||
"""error utils"""
|
||||
from traceback import format_tb
|
||||
|
||||
TRACEBACK_HEADER = "Traceback (most recent call last):\n"
|
||||
|
||||
|
||||
def exception_to_string(exc: Exception) -> str:
|
||||
"""Convert exception to string stackrace"""
|
||||
# Either use passed original exception or whatever we have
|
||||
return TRACEBACK_HEADER + "".join(format_tb(exc.__traceback__)) + str(exc)
|
@ -33,6 +33,13 @@ class ServiceConnectionSerializer(ModelSerializer, MetaNameSerializer):
|
||||
|
||||
component = ReadOnlyField()
|
||||
|
||||
def get_component(self, obj: OutpostServiceConnection) -> str:
|
||||
"""Get object type so that we know how to edit the object"""
|
||||
# pyright: reportGeneralTypeIssues=false
|
||||
if obj.__class__ == OutpostServiceConnection:
|
||||
return ""
|
||||
return obj.component
|
||||
|
||||
class Meta:
|
||||
|
||||
model = OutpostServiceConnection
|
||||
|
@ -63,7 +63,7 @@ class DockerController(BaseController):
|
||||
self.client.images.pull(image_name)
|
||||
container_args = {
|
||||
"image": image_name,
|
||||
"name": f"authentik-proxy-{self.outpost.uuid.hex}",
|
||||
"name": container_name,
|
||||
"detach": True,
|
||||
"ports": {
|
||||
f"{port.port}/{port.protocol.lower()}": port.inner_port or port.port
|
||||
|
@ -8,7 +8,7 @@ from uuid import uuid4
|
||||
from dacite import from_dict
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.core.cache import cache
|
||||
from django.db import models, transaction
|
||||
from django.db import IntegrityError, models, transaction
|
||||
from django.db.models.base import Model
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from docker.client import DockerClient
|
||||
@ -50,6 +50,8 @@ class ServiceConnectionInvalid(SentryIgnoredException):
|
||||
class OutpostConfig:
|
||||
"""Configuration an outpost uses to configure it self"""
|
||||
|
||||
# update website/docs/outposts/outposts.md
|
||||
|
||||
authentik_host: str
|
||||
authentik_host_insecure: bool = False
|
||||
|
||||
@ -141,7 +143,9 @@ class OutpostServiceConnection(models.Model):
|
||||
@property
|
||||
def component(self) -> str:
|
||||
"""Return component used to edit this object"""
|
||||
raise NotImplementedError
|
||||
# This is called when creating an outpost with a service connection
|
||||
# since the response doesn't use the correct inheritance
|
||||
return ""
|
||||
|
||||
class Meta:
|
||||
|
||||
@ -380,21 +384,24 @@ class Outpost(models.Model):
|
||||
tokens = Token.filter_not_expired(
|
||||
identifier=self.token_identifier,
|
||||
intent=TokenIntents.INTENT_API,
|
||||
)
|
||||
if tokens.exists():
|
||||
token = tokens.first()
|
||||
if not token.managed:
|
||||
token.managed = managed
|
||||
token.save()
|
||||
return token
|
||||
return Token.objects.create(
|
||||
user=self.user,
|
||||
identifier=self.token_identifier,
|
||||
intent=TokenIntents.INTENT_API,
|
||||
description=f"Autogenerated by authentik for Outpost {self.name}",
|
||||
expiring=False,
|
||||
managed=managed,
|
||||
)
|
||||
if tokens.exists():
|
||||
return tokens.first()
|
||||
try:
|
||||
return Token.objects.create(
|
||||
user=self.user,
|
||||
identifier=self.token_identifier,
|
||||
intent=TokenIntents.INTENT_API,
|
||||
description=f"Autogenerated by authentik for Outpost {self.name}",
|
||||
expiring=False,
|
||||
managed=managed,
|
||||
)
|
||||
except IntegrityError:
|
||||
# Integrity error happens mostly when managed is re-used
|
||||
Token.objects.filter(managed=managed).delete()
|
||||
Token.objects.filter(identifier=self.token_identifier).delete()
|
||||
return self.token
|
||||
|
||||
def get_required_objects(self) -> Iterable[Union[models.Model, str]]:
|
||||
"""Get an iterator of all objects the user needs read access to"""
|
||||
|
@ -0,0 +1,48 @@
|
||||
# Generated by Django 3.2.4 on 2021-06-14 15:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_policies_event_matcher", "0016_alter_eventmatcherpolicy_action"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="eventmatcherpolicy",
|
||||
name="action",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("login", "Login"),
|
||||
("login_failed", "Login Failed"),
|
||||
("logout", "Logout"),
|
||||
("user_write", "User Write"),
|
||||
("suspicious_request", "Suspicious Request"),
|
||||
("password_set", "Password Set"),
|
||||
("secret_view", "Secret View"),
|
||||
("invitation_used", "Invite Used"),
|
||||
("authorize_application", "Authorize Application"),
|
||||
("source_linked", "Source Linked"),
|
||||
("impersonation_started", "Impersonation Started"),
|
||||
("impersonation_ended", "Impersonation Ended"),
|
||||
("policy_execution", "Policy Execution"),
|
||||
("policy_exception", "Policy Exception"),
|
||||
("property_mapping_exception", "Property Mapping Exception"),
|
||||
("system_task_execution", "System Task Execution"),
|
||||
("system_task_exception", "System Task Exception"),
|
||||
("system_exception", "System Exception"),
|
||||
("configuration_error", "Configuration Error"),
|
||||
("model_created", "Model Created"),
|
||||
("model_updated", "Model Updated"),
|
||||
("model_deleted", "Model Deleted"),
|
||||
("email_sent", "Email Sent"),
|
||||
("update_available", "Update Available"),
|
||||
("custom_", "Custom Prefix"),
|
||||
],
|
||||
help_text="Match created events with this action type. When left empty, all action types will be matched.",
|
||||
),
|
||||
),
|
||||
]
|
@ -1,7 +1,6 @@
|
||||
"""authentik policy task"""
|
||||
from multiprocessing import get_context
|
||||
from multiprocessing.connection import Connection
|
||||
from traceback import format_tb
|
||||
from typing import Optional
|
||||
|
||||
from django.core.cache import cache
|
||||
@ -11,12 +10,12 @@ from sentry_sdk.tracing import Span
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.utils.errors import exception_to_string
|
||||
from authentik.policies.exceptions import PolicyException
|
||||
from authentik.policies.models import PolicyBinding
|
||||
from authentik.policies.types import PolicyRequest, PolicyResult
|
||||
|
||||
LOGGER = get_logger()
|
||||
TRACEBACK_HEADER = "Traceback (most recent call last):\n"
|
||||
|
||||
FORK_CTX = get_context("fork")
|
||||
PROCESS_CLASS = FORK_CTX.Process
|
||||
@ -106,11 +105,7 @@ class PolicyProcess(PROCESS_CLASS):
|
||||
except PolicyException as exc:
|
||||
# Either use passed original exception or whatever we have
|
||||
src_exc = exc.src_exc if exc.src_exc else exc
|
||||
error_string = (
|
||||
TRACEBACK_HEADER
|
||||
+ "".join(format_tb(src_exc.__traceback__))
|
||||
+ str(src_exc)
|
||||
)
|
||||
error_string = exception_to_string(src_exc)
|
||||
# Create policy exception event, only when we're not debugging
|
||||
if not self.request.debug:
|
||||
self.create_event(EventAction.POLICY_EXCEPTION, message=error_string)
|
||||
|
@ -3,11 +3,13 @@ from django.core.cache import cache
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext as _
|
||||
from rest_framework.serializers import BaseSerializer
|
||||
from structlog import get_logger
|
||||
|
||||
from authentik.lib.utils.http import get_client_ip
|
||||
from authentik.policies.models import Policy
|
||||
from authentik.policies.types import PolicyRequest, PolicyResult
|
||||
|
||||
LOGGER = get_logger()
|
||||
CACHE_KEY_IP_PREFIX = "authentik_reputation_ip_"
|
||||
CACHE_KEY_USER_PREFIX = "authentik_reputation_user_"
|
||||
|
||||
@ -35,9 +37,16 @@ class ReputationPolicy(Policy):
|
||||
if self.check_ip:
|
||||
score = cache.get_or_set(CACHE_KEY_IP_PREFIX + remote_ip, 0)
|
||||
passing = passing and score <= self.threshold
|
||||
LOGGER.debug("Score for IP", ip=remote_ip, score=score, passing=passing)
|
||||
if self.check_username:
|
||||
score = cache.get_or_set(CACHE_KEY_USER_PREFIX + request.user.username, 0)
|
||||
passing = passing and score <= self.threshold
|
||||
LOGGER.debug(
|
||||
"Score for Username",
|
||||
username=request.user.username,
|
||||
score=score,
|
||||
passing=passing,
|
||||
)
|
||||
return PolicyResult(passing)
|
||||
|
||||
class Meta:
|
||||
|
@ -1,9 +1,10 @@
|
||||
"""test reputation signals and policy"""
|
||||
from django.contrib.auth import authenticate
|
||||
from django.core.cache import cache
|
||||
from django.test import TestCase
|
||||
from django.test import RequestFactory, TestCase
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.lib.utils.http import DEFAULT_IP
|
||||
from authentik.policies.reputation.models import (
|
||||
CACHE_KEY_IP_PREFIX,
|
||||
CACHE_KEY_USER_PREFIX,
|
||||
@ -19,9 +20,12 @@ class TestReputationPolicy(TestCase):
|
||||
"""test reputation signals and policy"""
|
||||
|
||||
def setUp(self):
|
||||
self.test_ip = "255.255.255.255"
|
||||
self.request_factory = RequestFactory()
|
||||
self.request = self.request_factory.get("/")
|
||||
self.test_ip = "127.0.0.1"
|
||||
self.test_username = "test"
|
||||
cache.delete(CACHE_KEY_IP_PREFIX + self.test_ip)
|
||||
cache.delete(CACHE_KEY_IP_PREFIX + DEFAULT_IP)
|
||||
cache.delete(CACHE_KEY_USER_PREFIX + self.test_username)
|
||||
# We need a user for the one-to-one in userreputation
|
||||
self.user = User.objects.create(username=self.test_username)
|
||||
@ -29,7 +33,9 @@ class TestReputationPolicy(TestCase):
|
||||
def test_ip_reputation(self):
|
||||
"""test IP reputation"""
|
||||
# Trigger negative reputation
|
||||
authenticate(None, username=self.test_username, password=self.test_username)
|
||||
authenticate(
|
||||
self.request, username=self.test_username, password=self.test_username
|
||||
)
|
||||
# Test value in cache
|
||||
self.assertEqual(cache.get(CACHE_KEY_IP_PREFIX + self.test_ip), -1)
|
||||
# Save cache and check db values
|
||||
@ -39,7 +45,9 @@ class TestReputationPolicy(TestCase):
|
||||
def test_user_reputation(self):
|
||||
"""test User reputation"""
|
||||
# Trigger negative reputation
|
||||
authenticate(None, username=self.test_username, password=self.test_username)
|
||||
authenticate(
|
||||
self.request, username=self.test_username, password=self.test_username
|
||||
)
|
||||
# Test value in cache
|
||||
self.assertEqual(cache.get(CACHE_KEY_USER_PREFIX + self.test_username), -1)
|
||||
# Save cache and check db values
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""ProxyProvider API Views"""
|
||||
from typing import Any
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.utils import extend_schema_field, extend_schema_serializer
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.fields import CharField, ListField, SerializerMethodField
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
@ -85,6 +85,7 @@ class ProxyProviderViewSet(UsedByMixin, ModelViewSet):
|
||||
ordering = ["name"]
|
||||
|
||||
|
||||
@extend_schema_serializer(deprecate_fields=["forward_auth_mode"])
|
||||
class ProxyOutpostConfigSerializer(ModelSerializer):
|
||||
"""Proxy provider serializer for outposts"""
|
||||
|
||||
|
@ -120,7 +120,7 @@ class ServiceProviderMetadataParser:
|
||||
)
|
||||
ctx.key = key
|
||||
ctx.verify(signature_node)
|
||||
except xmlsec.VerificationError as exc:
|
||||
except xmlsec.Error as exc:
|
||||
raise ValueError("Failed to verify Metadata signature") from exc
|
||||
|
||||
def parse(self, raw_xml: str) -> ServiceProviderMetadata:
|
||||
|
@ -108,7 +108,7 @@ class AuthNRequestParser:
|
||||
)
|
||||
ctx.key = key
|
||||
ctx.verify(signature_node)
|
||||
except xmlsec.VerificationError as exc:
|
||||
except xmlsec.Error as exc:
|
||||
raise CannotHandleAssertion(ERROR_FAILED_TO_VERIFY) from exc
|
||||
|
||||
return self._parse_xml(decoded_xml, relay_state)
|
||||
@ -160,7 +160,7 @@ class AuthNRequestParser:
|
||||
sign_algorithm_transform,
|
||||
b64decode(signature),
|
||||
)
|
||||
except xmlsec.VerificationError as exc:
|
||||
except xmlsec.Error as exc:
|
||||
raise CannotHandleAssertion(ERROR_FAILED_TO_VERIFY) from exc
|
||||
return self._parse_xml(decoded_xml, relay_state)
|
||||
|
||||
|
@ -2,12 +2,13 @@
|
||||
from base64 import b64encode
|
||||
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from django.http.request import HttpRequest, QueryDict
|
||||
from django.http.request import QueryDict
|
||||
from django.test import RequestFactory, TestCase
|
||||
from guardian.utils import get_anonymous_user
|
||||
|
||||
from authentik.crypto.models import CertificateKeyPair
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.flows.tests.test_planner import dummy_get_response
|
||||
from authentik.providers.saml.models import SAMLPropertyMapping, SAMLProvider
|
||||
from authentik.providers.saml.processors.assertion import AssertionProcessor
|
||||
from authentik.providers.saml.processors.request_parser import AuthNRequestParser
|
||||
@ -58,11 +59,6 @@ qNAZMq1DqpibfCBg
|
||||
-----END CERTIFICATE-----"""
|
||||
|
||||
|
||||
def dummy_get_response(request: HttpRequest): # pragma: no cover
|
||||
"""Dummy get_response for SessionMiddleware"""
|
||||
return None
|
||||
|
||||
|
||||
class TestAuthNRequest(TestCase):
|
||||
"""Test AuthN Request generator and parser"""
|
||||
|
||||
|
@ -7,6 +7,7 @@ from django.utils.translation import gettext as _
|
||||
from django.views import View
|
||||
|
||||
from authentik.core.models import Token, TokenIntents
|
||||
from authentik.stages.password import BACKEND_DJANGO
|
||||
|
||||
|
||||
class UseTokenView(View):
|
||||
@ -18,7 +19,7 @@ class UseTokenView(View):
|
||||
if not tokens.exists():
|
||||
raise Http404
|
||||
token = tokens.first()
|
||||
login(request, token.user, backend="django.contrib.auth.backends.ModelBackend")
|
||||
login(request, token.user, backend=BACKEND_DJANGO)
|
||||
token.delete()
|
||||
messages.warning(request, _("Used recovery-link to authenticate."))
|
||||
return redirect("authentik_core:if-admin")
|
||||
|
@ -375,7 +375,11 @@ if _ERROR_REPORTING:
|
||||
environment=CONFIG.y("error_reporting.environment", "customer"),
|
||||
send_default_pii=CONFIG.y_bool("error_reporting.send_pii", False),
|
||||
)
|
||||
set_tag("authentik.build_hash", os.environ.get(ENV_GIT_HASH_KEY, "tagged"))
|
||||
# Default to empty string as that is what docker has
|
||||
build_hash = os.environ.get(ENV_GIT_HASH_KEY, "")
|
||||
if build_hash == "":
|
||||
build_hash = "tagged"
|
||||
set_tag("authentik.build_hash", build_hash)
|
||||
set_tag(
|
||||
"authentik.env", "kubernetes" if "KUBERNETES_PORT" in os.environ else "compose"
|
||||
)
|
||||
|
@ -39,7 +39,7 @@ from authentik.sources.saml.processors.constants import (
|
||||
from authentik.sources.saml.processors.request import SESSION_REQUEST_ID
|
||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
|
||||
from authentik.stages.user_login.stage import DEFAULT_BACKEND
|
||||
from authentik.stages.user_login.stage import BACKEND_DJANGO
|
||||
|
||||
LOGGER = get_logger()
|
||||
if TYPE_CHECKING:
|
||||
@ -141,7 +141,7 @@ class ResponseProcessor:
|
||||
self._source.authentication_flow,
|
||||
**{
|
||||
PLAN_CONTEXT_PENDING_USER: user,
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: DEFAULT_BACKEND,
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: BACKEND_DJANGO,
|
||||
},
|
||||
)
|
||||
|
||||
@ -204,7 +204,7 @@ class ResponseProcessor:
|
||||
self._source.authentication_flow,
|
||||
**{
|
||||
PLAN_CONTEXT_PENDING_USER: matching_users.first(),
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: DEFAULT_BACKEND,
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: BACKEND_DJANGO,
|
||||
PLAN_CONTEXT_REDIRECT: final_redirect,
|
||||
},
|
||||
)
|
||||
|
@ -2,7 +2,7 @@
|
||||
from django.utils.timezone import now
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.core.models import AuthenticatedSession, User
|
||||
from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.root.celery import CELERY_APP
|
||||
@ -31,11 +31,13 @@ def clean_temporary_users(self: MonitoredTask):
|
||||
continue
|
||||
source = sources.first()
|
||||
source_delta = timedelta_from_string(source.temporary_user_delete_after)
|
||||
if _now - user.last_login >= source_delta:
|
||||
if (
|
||||
_now - user.last_login >= source_delta
|
||||
and not AuthenticatedSession.objects.filter(user=user).exists()
|
||||
):
|
||||
LOGGER.debug(
|
||||
"User is expired and will be deleted.", user=user, delta=source_delta
|
||||
)
|
||||
# TODO: Check if user is signed in anywhere?
|
||||
user.delete()
|
||||
deleted_users += 1
|
||||
messages.append(f"Successfully deleted {deleted_users} users.")
|
||||
|
@ -1,44 +1,6 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-25 14:32
|
||||
|
||||
from django.apps.registry import Apps
|
||||
from django.db import migrations
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
|
||||
from authentik.flows.models import FlowDesignation
|
||||
|
||||
|
||||
def create_default_setup_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||
Flow = apps.get_model("authentik_flows", "Flow")
|
||||
FlowStageBinding = apps.get_model("authentik_flows", "FlowStageBinding")
|
||||
|
||||
AuthenticatorDuoStage = apps.get_model(
|
||||
"authentik_stages_authenticator_duo", "AuthenticatorDuoStage"
|
||||
)
|
||||
|
||||
db_alias = schema_editor.connection.alias
|
||||
|
||||
flow, _ = Flow.objects.using(db_alias).update_or_create(
|
||||
slug="default-authenticator-duo-setup",
|
||||
designation=FlowDesignation.STAGE_CONFIGURATION,
|
||||
defaults={
|
||||
"name": "default-authenticator-duo-setup",
|
||||
"title": "Setup Duo",
|
||||
},
|
||||
)
|
||||
|
||||
stage, _ = AuthenticatorDuoStage.objects.using(db_alias).update_or_create(
|
||||
name="default-authenticator-duo-setup"
|
||||
)
|
||||
|
||||
FlowStageBinding.objects.using(db_alias).update_or_create(
|
||||
target=flow, stage=stage, defaults={"order": 0}
|
||||
)
|
||||
|
||||
for stage in AuthenticatorDuoStage.objects.using(db_alias).filter(
|
||||
configure_flow=None
|
||||
):
|
||||
stage.configure_flow = flow
|
||||
stage.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
@ -50,6 +12,4 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(create_default_setup_flow),
|
||||
]
|
||||
operations = []
|
||||
|
@ -3,4 +3,4 @@
|
||||
INSTALLED_APPS = [
|
||||
"django_otp.plugins.otp_totp",
|
||||
]
|
||||
OTP_TOTP_ISSUER = "authentik"
|
||||
OTP_TOTP_ISSUER = "__to_replace__"
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""TOTP Setup stage"""
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.http.request import QueryDict
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_otp.plugins.otp_totp.models import TOTPDevice
|
||||
from rest_framework.fields import CharField, IntegerField
|
||||
@ -16,6 +17,7 @@ from authentik.flows.challenge import (
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.flows.stage import ChallengeStageView
|
||||
from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage
|
||||
from authentik.stages.authenticator_totp.settings import OTP_TOTP_ISSUER
|
||||
|
||||
LOGGER = get_logger()
|
||||
SESSION_TOTP_DEVICE = "totp_device"
|
||||
@ -54,7 +56,9 @@ class AuthenticatorTOTPStageView(ChallengeStageView):
|
||||
return AuthenticatorTOTPChallenge(
|
||||
data={
|
||||
"type": ChallengeTypes.NATIVE.value,
|
||||
"config_url": device.config_url,
|
||||
"config_url": device.config_url.replace(
|
||||
OTP_TOTP_ISSUER, slugify(self.request.tenant.branding_title)
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
127
authentik/stages/authenticator_validate/tests.py
Normal file
127
authentik/stages/authenticator_validate/tests.py
Normal file
@ -0,0 +1,127 @@
|
||||
"""Test validator stage"""
|
||||
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_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.tests.test_planner import dummy_get_response
|
||||
from authentik.providers.oauth2.generators import (
|
||||
generate_client_id,
|
||||
generate_client_secret,
|
||||
)
|
||||
from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice
|
||||
from authentik.stages.authenticator_validate.api import (
|
||||
AuthenticatorValidateStageSerializer,
|
||||
)
|
||||
from authentik.stages.authenticator_validate.challenge import (
|
||||
get_challenge_for_device,
|
||||
validate_challenge_code,
|
||||
validate_challenge_duo,
|
||||
validate_challenge_webauthn,
|
||||
)
|
||||
from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
|
||||
|
||||
|
||||
class AuthenticatorValidateStageTests(TestCase):
|
||||
"""Test validator stage"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.user = User.objects.get(username="akadmin")
|
||||
self.request_factory = RequestFactory()
|
||||
|
||||
def test_stage_validation(self):
|
||||
"""Test serializer validation"""
|
||||
self.client.force_login(self.user)
|
||||
serializer = AuthenticatorValidateStageSerializer(
|
||||
data={"name": "foo", "not_configured_action": NotConfiguredAction.CONFIGURE}
|
||||
)
|
||||
self.assertFalse(serializer.is_valid())
|
||||
self.assertIn("not_configured_action", serializer.errors)
|
||||
|
||||
def test_device_challenge_totp(self):
|
||||
"""Test device challenge"""
|
||||
request = self.request_factory.get("/")
|
||||
totp_device = TOTPDevice.objects.create(
|
||||
user=self.user, confirmed=True, digits=6
|
||||
)
|
||||
self.assertEqual(get_challenge_for_device(request, totp_device), {})
|
||||
with self.assertRaises(ValidationError):
|
||||
validate_challenge_code("1234", request, self.user)
|
||||
|
||||
def test_device_challenge_webauthn(self):
|
||||
"""Test webauthn"""
|
||||
request = self.request_factory.get("/")
|
||||
request.user = self.user
|
||||
middleware = SessionMiddleware(dummy_get_response)
|
||||
middleware.process_request(request)
|
||||
request.session.save()
|
||||
|
||||
webauthn_device = WebAuthnDevice.objects.create(
|
||||
user=self.user,
|
||||
public_key="qwerqwerqre",
|
||||
credential_id="foobarbaz",
|
||||
sign_count=0,
|
||||
rp_id="foo",
|
||||
)
|
||||
challenge = get_challenge_for_device(request, webauthn_device)
|
||||
del challenge["challenge"]
|
||||
self.assertEqual(
|
||||
challenge,
|
||||
{
|
||||
"allowCredentials": [
|
||||
{
|
||||
"id": "foobarbaz",
|
||||
"transports": ["usb", "nfc", "ble", "internal"],
|
||||
"type": "public-key",
|
||||
}
|
||||
],
|
||||
"rpId": "foo",
|
||||
"timeout": 60000,
|
||||
"userVerification": "discouraged",
|
||||
},
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
validate_challenge_webauthn({}, request, self.user)
|
||||
|
||||
def test_device_challenge_duo(self):
|
||||
"""Test duo"""
|
||||
request = self.request_factory.get("/")
|
||||
stage = AuthenticatorDuoStage.objects.create(
|
||||
name="test",
|
||||
client_id=generate_client_id(),
|
||||
client_secret=generate_client_secret(),
|
||||
api_hostname="",
|
||||
)
|
||||
duo_device = DuoDevice.objects.create(
|
||||
user=self.user,
|
||||
stage=stage,
|
||||
)
|
||||
duo_mock = MagicMock(
|
||||
auth=MagicMock(
|
||||
return_value={
|
||||
"result": "allow",
|
||||
"status": "allow",
|
||||
"status_msg": "Success. Logging you in...",
|
||||
}
|
||||
)
|
||||
)
|
||||
failed_duo_mock = MagicMock(auth=MagicMock(return_value={"result": "deny"}))
|
||||
with patch(
|
||||
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.client",
|
||||
duo_mock,
|
||||
):
|
||||
self.assertEqual(
|
||||
duo_device.pk, validate_challenge_duo(duo_device.pk, request, self.user)
|
||||
)
|
||||
with patch(
|
||||
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.client",
|
||||
failed_duo_mock,
|
||||
):
|
||||
with self.assertRaises(ValidationError):
|
||||
validate_challenge_duo(duo_device.pk, request, self.user)
|
@ -28,8 +28,6 @@ from authentik.stages.authenticator_webauthn.utils import (
|
||||
get_rp_id,
|
||||
)
|
||||
|
||||
RP_NAME = "authentik"
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
SESSION_KEY_WEBAUTHN_AUTHENTICATED = (
|
||||
@ -119,7 +117,7 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView):
|
||||
user = self.get_pending_user()
|
||||
make_credential_options = WebAuthnMakeCredentialOptions(
|
||||
challenge,
|
||||
RP_NAME,
|
||||
self.request.tenant.branding_title,
|
||||
get_rp_id(self.request),
|
||||
user.uid,
|
||||
user.username,
|
||||
|
@ -0,0 +1,31 @@
|
||||
# Generated by Django 3.2.4 on 2021-06-14 15:32
|
||||
|
||||
import django.contrib.postgres.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_stages_identification", "0010_identificationstage_password_stage"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="identificationstage",
|
||||
name="user_fields",
|
||||
field=django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.CharField(
|
||||
choices=[
|
||||
("email", "E Mail"),
|
||||
("username", "Username"),
|
||||
("upn", "Upn"),
|
||||
],
|
||||
max_length=100,
|
||||
),
|
||||
blank=True,
|
||||
help_text="Fields of the user object to match against. (Hold shift to select multiple options)",
|
||||
size=None,
|
||||
),
|
||||
),
|
||||
]
|
@ -17,6 +17,7 @@ class UserFields(models.TextChoices):
|
||||
|
||||
E_MAIL = "email"
|
||||
USERNAME = "username"
|
||||
UPN = "upn"
|
||||
|
||||
|
||||
class IdentificationStage(Stage):
|
||||
|
@ -8,19 +8,20 @@ from django.db.models import Q
|
||||
from django.http import HttpResponse
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from rest_framework.fields import BooleanField, CharField, ListField
|
||||
from drf_spectacular.utils import PolymorphicProxySerializer, extend_schema_field
|
||||
from rest_framework.fields import BooleanField, CharField, DictField, ListField
|
||||
from rest_framework.serializers import ValidationError
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
from authentik.core.models import Application, Source, User
|
||||
from authentik.core.types import UILoginButtonSerializer
|
||||
from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.flows.stage import (
|
||||
PLAN_CONTEXT_PENDING_USER_IDENTIFIER,
|
||||
ChallengeStageView,
|
||||
)
|
||||
from authentik.flows.views import SESSION_KEY_APPLICATION_PRE
|
||||
from authentik.flows.views import SESSION_KEY_APPLICATION_PRE, challenge_types
|
||||
from authentik.stages.identification.models import IdentificationStage
|
||||
from authentik.stages.identification.signals import identification_failed
|
||||
from authentik.stages.password.stage import authenticate
|
||||
@ -28,6 +29,26 @@ from authentik.stages.password.stage import authenticate
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
@extend_schema_field(
|
||||
PolymorphicProxySerializer(
|
||||
component_name="ChallengeTypes",
|
||||
serializers=challenge_types(),
|
||||
resource_type_field_name="component",
|
||||
)
|
||||
)
|
||||
class ChallengeDictWrapper(DictField):
|
||||
"""Wrapper around DictField that annotates itself as challenge proxy"""
|
||||
|
||||
|
||||
class LoginSourceSerializer(PassiveSerializer):
|
||||
"""Serializer for Login buttons of sources"""
|
||||
|
||||
name = CharField()
|
||||
icon_url = CharField(required=False, allow_null=True)
|
||||
|
||||
challenge = ChallengeDictWrapper()
|
||||
|
||||
|
||||
class IdentificationChallenge(Challenge):
|
||||
"""Identification challenges with all UI elements"""
|
||||
|
||||
@ -38,7 +59,7 @@ class IdentificationChallenge(Challenge):
|
||||
enroll_url = CharField(required=False)
|
||||
recovery_url = CharField(required=False)
|
||||
primary_action = CharField()
|
||||
sources = UILoginButtonSerializer(many=True, required=False)
|
||||
sources = LoginSourceSerializer(many=True, required=False)
|
||||
|
||||
component = CharField(default="ak-stage-identification")
|
||||
|
||||
@ -96,7 +117,11 @@ class IdentificationStageView(ChallengeStageView):
|
||||
current_stage: IdentificationStage = self.executor.current_stage
|
||||
query = Q()
|
||||
for search_field in current_stage.user_fields:
|
||||
model_field = search_field
|
||||
model_field = {
|
||||
"email": "email",
|
||||
"username": "username",
|
||||
"upn": "attributes__upn",
|
||||
}[search_field]
|
||||
if current_stage.case_insensitive_matching:
|
||||
model_field += "__iexact"
|
||||
else:
|
||||
@ -150,6 +175,7 @@ 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
|
||||
|
||||
|
@ -9,6 +9,7 @@ from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
|
||||
from authentik.providers.oauth2.generators import generate_client_secret
|
||||
from authentik.sources.oauth.models import OAuthSource
|
||||
from authentik.stages.identification.models import IdentificationStage, UserFields
|
||||
from authentik.stages.password import BACKEND_DJANGO
|
||||
from authentik.stages.password.models import PasswordStage
|
||||
|
||||
|
||||
@ -70,7 +71,7 @@ class TestIdentificationStage(TestCase):
|
||||
def test_valid_with_password(self):
|
||||
"""Test with valid email and password in single step"""
|
||||
pw_stage = PasswordStage.objects.create(
|
||||
name="password", backends=["django.contrib.auth.backends.ModelBackend"]
|
||||
name="password", backends=[BACKEND_DJANGO]
|
||||
)
|
||||
self.stage.password_stage = pw_stage
|
||||
self.stage.save()
|
||||
@ -92,7 +93,7 @@ class TestIdentificationStage(TestCase):
|
||||
def test_invalid_with_password(self):
|
||||
"""Test with valid email and invalid password in single step"""
|
||||
pw_stage = PasswordStage.objects.create(
|
||||
name="password", backends=["django.contrib.auth.backends.ModelBackend"]
|
||||
name="password", backends=[BACKEND_DJANGO]
|
||||
)
|
||||
self.stage.password_stage = pw_stage
|
||||
self.stage.save()
|
||||
|
@ -17,6 +17,7 @@ from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK
|
||||
from authentik.flows.views import SESSION_KEY_PLAN
|
||||
from authentik.stages.invitation.models import Invitation, InvitationStage
|
||||
from authentik.stages.invitation.stage import INVITATION_TOKEN_KEY, PLAN_CONTEXT_PROMPT
|
||||
from authentik.stages.password import BACKEND_DJANGO
|
||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
|
||||
|
||||
@ -46,9 +47,7 @@ class TestUserLoginStage(TestCase):
|
||||
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
||||
)
|
||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||
plan.context[
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
] = "django.contrib.auth.backends.ModelBackend"
|
||||
plan.context[PLAN_CONTEXT_AUTHENTICATION_BACKEND] = BACKEND_DJANGO
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
@ -79,9 +78,7 @@ class TestUserLoginStage(TestCase):
|
||||
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
||||
)
|
||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||
plan.context[
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
] = "django.contrib.auth.backends.ModelBackend"
|
||||
plan.context[PLAN_CONTEXT_AUTHENTICATION_BACKEND] = BACKEND_DJANGO
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
|
@ -0,0 +1,3 @@
|
||||
"""Backend paths"""
|
||||
BACKEND_DJANGO = "django.contrib.auth.backends.ModelBackend"
|
||||
BACKEND_LDAP = "authentik.sources.ldap.auth.LDAPBackend"
|
||||
|
@ -9,17 +9,18 @@ from rest_framework.serializers import BaseSerializer
|
||||
|
||||
from authentik.core.types import UserSettingSerializer
|
||||
from authentik.flows.models import ConfigurableStage, Stage
|
||||
from authentik.stages.password import BACKEND_DJANGO, BACKEND_LDAP
|
||||
|
||||
|
||||
def get_authentication_backends():
|
||||
"""Return all available authentication backends as tuple set"""
|
||||
return [
|
||||
(
|
||||
"django.contrib.auth.backends.ModelBackend",
|
||||
BACKEND_DJANGO,
|
||||
_("authentik-internal Userdatabase"),
|
||||
),
|
||||
(
|
||||
"authentik.sources.ldap.auth.LDAPBackend",
|
||||
BACKEND_LDAP,
|
||||
_("authentik LDAP"),
|
||||
),
|
||||
]
|
||||
|
@ -14,6 +14,7 @@ from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
|
||||
from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK
|
||||
from authentik.flows.views import SESSION_KEY_PLAN
|
||||
from authentik.providers.oauth2.generators import generate_client_secret
|
||||
from authentik.stages.password import BACKEND_DJANGO
|
||||
from authentik.stages.password.models import PasswordStage
|
||||
|
||||
MOCK_BACKEND_AUTHENTICATE = MagicMock(side_effect=PermissionDenied("test"))
|
||||
@ -36,7 +37,7 @@ class TestPasswordStage(TestCase):
|
||||
designation=FlowDesignation.AUTHENTICATION,
|
||||
)
|
||||
self.stage = PasswordStage.objects.create(
|
||||
name="password", backends=["django.contrib.auth.backends.ModelBackend"]
|
||||
name="password", backends=[BACKEND_DJANGO]
|
||||
)
|
||||
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
|
||||
|
||||
|
@ -8,10 +8,10 @@ from structlog.stdlib import get_logger
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.flows.stage import StageView
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.stages.password import BACKEND_DJANGO
|
||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
|
||||
LOGGER = get_logger()
|
||||
DEFAULT_BACKEND = "django.contrib.auth.backends.ModelBackend"
|
||||
USER_LOGIN_AUTHENTICATED = "user_login_authenticated"
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ class UserLoginStageView(StageView):
|
||||
LOGGER.debug(message)
|
||||
return self.executor.stage_invalid()
|
||||
backend = self.executor.plan.context.get(
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND, DEFAULT_BACKEND
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND, BACKEND_DJANGO
|
||||
)
|
||||
login(
|
||||
self.request,
|
||||
|
@ -9,6 +9,7 @@ from authentik.flows.markers import StageMarker
|
||||
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
|
||||
from authentik.flows.views import SESSION_KEY_PLAN
|
||||
from authentik.stages.password import BACKEND_DJANGO
|
||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
from authentik.stages.user_logout.models import UserLogoutStage
|
||||
|
||||
@ -35,9 +36,7 @@ class TestUserLogoutStage(TestCase):
|
||||
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
||||
)
|
||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||
plan.context[
|
||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
] = "django.contrib.auth.backends.ModelBackend"
|
||||
plan.context[PLAN_CONTEXT_AUTHENTICATION_BACKEND] = BACKEND_DJANGO
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
|
@ -9,6 +9,7 @@ from authentik.lib.config import CONFIG
|
||||
from authentik.tenants.models import Tenant
|
||||
|
||||
_q_default = Q(default=True)
|
||||
DEFAULT_TENANT = Tenant(domain="fallback")
|
||||
|
||||
|
||||
def get_tenant_for_request(request: HttpRequest) -> Tenant:
|
||||
@ -17,13 +18,13 @@ def get_tenant_for_request(request: HttpRequest) -> Tenant:
|
||||
Q(domain__iendswith=request.get_host()) | _q_default
|
||||
)
|
||||
if not db_tenants.exists():
|
||||
return Tenant(domain="fallback")
|
||||
return DEFAULT_TENANT
|
||||
return db_tenants.first()
|
||||
|
||||
|
||||
def context_processor(request: HttpRequest) -> dict[str, Any]:
|
||||
"""Context Processor that injects tenant object into every template"""
|
||||
tenant = getattr(request, "tenant", Tenant(domain="fallback"))
|
||||
tenant = getattr(request, "tenant", DEFAULT_TENANT)
|
||||
return {
|
||||
"tenant": tenant,
|
||||
"ak_version": __version__,
|
||||
|
@ -21,7 +21,7 @@ services:
|
||||
networks:
|
||||
- internal
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.1-rc2}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.1-rc6}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
@ -52,7 +52,7 @@ services:
|
||||
- "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-rc2}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.1-rc6}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
networks:
|
||||
|
@ -1,3 +1,3 @@
|
||||
package constants
|
||||
|
||||
const VERSION = "2021.6.1-rc2"
|
||||
const VERSION = "2021.6.1-rc6"
|
||||
|
@ -3,7 +3,6 @@ package ldap
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
@ -66,15 +65,15 @@ func (pi *ProviderInstance) Bind(username string, bindDN, bindPW string, conn ne
|
||||
|
||||
params := url.Values{}
|
||||
params.Add("goauthentik.io/outpost/ldap", "true")
|
||||
passed, err := pi.solveFlowChallenge(username, bindPW, apiClient, params.Encode(), 1)
|
||||
if err != nil {
|
||||
passed, rerr := pi.solveFlowChallenge(username, bindPW, apiClient, params.Encode(), 1)
|
||||
if rerr != ldap.LDAPResultSuccess {
|
||||
pi.log.WithField("bindDN", bindDN).WithError(err).Warning("failed to solve challenge")
|
||||
return ldap.LDAPResultOperationsError, nil
|
||||
return rerr, nil
|
||||
}
|
||||
if !passed {
|
||||
return ldap.LDAPResultInvalidCredentials, nil
|
||||
}
|
||||
p, _, err := apiClient.CoreApi.CoreApplicationsCheckAccessCreate(context.Background(), pi.appSlug).Execute()
|
||||
p, _, err := apiClient.CoreApi.CoreApplicationsCheckAccessRetrieve(context.Background(), pi.appSlug).Execute()
|
||||
if !p.Passing {
|
||||
pi.log.WithField("bindDN", bindDN).Info("Access denied for user")
|
||||
return ldap.LDAPResultInsufficientAccessRights, nil
|
||||
@ -138,12 +137,12 @@ type ChallengeInt interface {
|
||||
GetResponseErrors() map[string][]api.ErrorDetail
|
||||
}
|
||||
|
||||
func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, client *api.APIClient, urlParams string, depth int) (bool, error) {
|
||||
func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, client *api.APIClient, urlParams string, depth int) (bool, ldap.LDAPResultCode) {
|
||||
req := client.FlowsApi.FlowsExecutorGet(context.Background(), pi.flowSlug).Query(urlParams)
|
||||
challenge, _, err := req.Execute()
|
||||
if err != nil {
|
||||
pi.log.WithError(err).Warning("Failed to get challenge")
|
||||
return false, err
|
||||
return false, ldap.LDAPResultOperationsError
|
||||
}
|
||||
ch := challenge.GetActualInstance().(ChallengeInt)
|
||||
pi.log.WithField("component", ch.GetComponent()).WithField("type", ch.GetType()).Debug("Got challenge")
|
||||
@ -162,45 +161,51 @@ func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, c
|
||||
}
|
||||
}
|
||||
if deviceChallenge == nil {
|
||||
return false, errors.New("got ak-stage-authenticator-validate without duo")
|
||||
pi.log.Warning("got ak-stage-authenticator-validate without duo")
|
||||
return false, ldap.LDAPResultOperationsError
|
||||
}
|
||||
devId, err := strconv.Atoi(deviceChallenge.DeviceUid)
|
||||
if err != nil {
|
||||
return false, errors.New("failed to convert duo device id to int")
|
||||
pi.log.Warning("failed to convert duo device id to int")
|
||||
return false, ldap.LDAPResultOperationsError
|
||||
}
|
||||
devId32 := int32(devId)
|
||||
inner := api.NewAuthenticatorValidationChallengeResponseRequest()
|
||||
inner.Duo = &devId32
|
||||
responseReq = responseReq.FlowChallengeResponseRequest(api.AuthenticatorValidationChallengeResponseRequestAsFlowChallengeResponseRequest(inner))
|
||||
case "ak-stage-access-denied":
|
||||
return false, errors.New("got ak-stage-access-denied")
|
||||
pi.log.Info("got ak-stage-access-denied")
|
||||
return false, ldap.LDAPResultInsufficientAccessRights
|
||||
default:
|
||||
return false, fmt.Errorf("unsupported challenge type: %s", ch.GetComponent())
|
||||
pi.log.WithField("component", ch.GetComponent()).Warning("unsupported challenge type")
|
||||
return false, ldap.LDAPResultOperationsError
|
||||
}
|
||||
response, _, err := responseReq.Execute()
|
||||
ch = response.GetActualInstance().(ChallengeInt)
|
||||
pi.log.WithField("component", ch.GetComponent()).WithField("type", ch.GetType()).Debug("Got response")
|
||||
switch ch.GetComponent() {
|
||||
case "ak-stage-access-denied":
|
||||
return false, errors.New("got ak-stage-access-denied")
|
||||
pi.log.Info("got ak-stage-access-denied")
|
||||
return false, ldap.LDAPResultInsufficientAccessRights
|
||||
}
|
||||
if ch.GetType() == "redirect" {
|
||||
return true, nil
|
||||
return true, ldap.LDAPResultSuccess
|
||||
}
|
||||
if err != nil {
|
||||
pi.log.WithError(err).Warning("Failed to submit challenge")
|
||||
return false, err
|
||||
return false, ldap.LDAPResultOperationsError
|
||||
}
|
||||
if len(ch.GetResponseErrors()) > 0 {
|
||||
for key, errs := range ch.GetResponseErrors() {
|
||||
for _, err := range errs {
|
||||
pi.log.WithField("key", key).WithField("code", err.Code).WithField("msg", err.String).Warning("Flow error")
|
||||
return false, nil
|
||||
return false, ldap.LDAPResultInsufficientAccessRights
|
||||
}
|
||||
}
|
||||
}
|
||||
if depth >= 10 {
|
||||
return false, errors.New("exceeded stage recursion depth")
|
||||
pi.log.Warning("exceeded stage recursion depth")
|
||||
return false, ldap.LDAPResultOperationsError
|
||||
}
|
||||
return pi.solveFlowChallenge(bindDN, password, client, urlParams, depth+1)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
const VERSION = "2021.6.1-rc2"
|
||||
const VERSION = "2021.6.1-rc6"
|
||||
|
||||
func BUILD() string {
|
||||
build := os.Getenv("GIT_BUILD_HASH")
|
||||
|
191
schema.yml
191
schema.yml
@ -1,7 +1,7 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: authentik
|
||||
version: 2021.6.1-rc1
|
||||
version: 2021.6.1-rc5
|
||||
description: Making authentication simple.
|
||||
contact:
|
||||
email: hello@beryju.org
|
||||
@ -1504,10 +1504,14 @@ paths:
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/api/v2beta/core/applications/{slug}/check_access/:
|
||||
post:
|
||||
operationId: core_applications_check_access_create
|
||||
get:
|
||||
operationId: core_applications_check_access_retrieve
|
||||
description: Check access to a single application by slug
|
||||
parameters:
|
||||
- in: query
|
||||
name: for_user
|
||||
schema:
|
||||
type: integer
|
||||
- in: path
|
||||
name: slug
|
||||
schema:
|
||||
@ -1516,17 +1520,6 @@ paths:
|
||||
required: true
|
||||
tags:
|
||||
- core
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CheckAccessRequestRequest'
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CheckAccessRequestRequest'
|
||||
multipart/form-data:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CheckAccessRequestRequest'
|
||||
security:
|
||||
- authentik: []
|
||||
- cookieAuth: []
|
||||
@ -2717,14 +2710,10 @@ paths:
|
||||
name: is_active
|
||||
schema:
|
||||
type: boolean
|
||||
title: Active
|
||||
description: Designates whether this user should be treated as active. Unselect
|
||||
this instead of deleting accounts.
|
||||
- in: query
|
||||
name: is_superuser
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
type: boolean
|
||||
- in: query
|
||||
name: name
|
||||
schema:
|
||||
@ -3041,7 +3030,7 @@ paths:
|
||||
- in: query
|
||||
name: has_key
|
||||
schema:
|
||||
type: string
|
||||
type: boolean
|
||||
description: Only return certificate-key pairs with keys
|
||||
- in: query
|
||||
name: name
|
||||
@ -3429,6 +3418,11 @@ paths:
|
||||
description: A search term.
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: tenant_name
|
||||
schema:
|
||||
type: string
|
||||
description: Tenant name
|
||||
- in: query
|
||||
name: username
|
||||
schema:
|
||||
@ -3545,6 +3539,11 @@ paths:
|
||||
description: A search term.
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: tenant_name
|
||||
schema:
|
||||
type: string
|
||||
description: Tenant name
|
||||
- in: query
|
||||
name: top_n
|
||||
schema:
|
||||
@ -4609,7 +4608,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FlowChallengeRequest'
|
||||
$ref: '#/components/schemas/ChallengeTypes'
|
||||
description: ''
|
||||
'404':
|
||||
description: No Token found
|
||||
@ -4655,7 +4654,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FlowChallengeRequest'
|
||||
$ref: '#/components/schemas/ChallengeTypes'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
@ -18413,17 +18412,75 @@ 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
|
||||
- shell
|
||||
- redirect
|
||||
type: string
|
||||
CheckAccessRequestRequest:
|
||||
type: object
|
||||
properties:
|
||||
for_user:
|
||||
type: integer
|
||||
ChallengeTypes:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/AccessDeniedChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorDuoChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorStaticChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorTOTPChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorValidationChallenge'
|
||||
- $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'
|
||||
- $ref: '#/components/schemas/IdentificationChallenge'
|
||||
- $ref: '#/components/schemas/PasswordChallenge'
|
||||
- $ref: '#/components/schemas/PlexAuthenticationChallenge'
|
||||
- $ref: '#/components/schemas/PromptChallenge'
|
||||
- $ref: '#/components/schemas/RedirectChallenge'
|
||||
- $ref: '#/components/schemas/ShellChallenge'
|
||||
discriminator:
|
||||
propertyName: component
|
||||
mapping:
|
||||
ak-stage-access-denied: '#/components/schemas/AccessDeniedChallenge'
|
||||
ak-stage-authenticator-duo: '#/components/schemas/AuthenticatorDuoChallenge'
|
||||
ak-stage-authenticator-static: '#/components/schemas/AuthenticatorStaticChallenge'
|
||||
ak-stage-authenticator-totp: '#/components/schemas/AuthenticatorTOTPChallenge'
|
||||
ak-stage-authenticator-validate: '#/components/schemas/AuthenticatorValidationChallenge'
|
||||
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'
|
||||
ak-stage-identification: '#/components/schemas/IdentificationChallenge'
|
||||
ak-stage-password: '#/components/schemas/PasswordChallenge'
|
||||
ak-flow-sources-plex: '#/components/schemas/PlexAuthenticationChallenge'
|
||||
ak-stage-prompt: '#/components/schemas/PromptChallenge'
|
||||
xak-flow-redirect: '#/components/schemas/RedirectChallenge'
|
||||
xak-flow-shell: '#/components/schemas/ShellChallenge'
|
||||
ClientTypeEnum:
|
||||
enum:
|
||||
- confidential
|
||||
@ -19097,6 +19154,9 @@ components:
|
||||
expires:
|
||||
type: string
|
||||
format: date-time
|
||||
tenant:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
required:
|
||||
- action
|
||||
- app
|
||||
@ -19169,6 +19229,7 @@ components:
|
||||
- property_mapping_exception
|
||||
- system_task_execution
|
||||
- system_task_exception
|
||||
- system_exception
|
||||
- configuration_error
|
||||
- model_created
|
||||
- model_updated
|
||||
@ -19222,6 +19283,9 @@ components:
|
||||
expires:
|
||||
type: string
|
||||
format: date-time
|
||||
tenant:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
required:
|
||||
- action
|
||||
- app
|
||||
@ -19387,45 +19451,6 @@ components:
|
||||
- slug
|
||||
- stages
|
||||
- title
|
||||
FlowChallengeRequest:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/AccessDeniedChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorDuoChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorStaticChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorTOTPChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorValidationChallenge'
|
||||
- $ref: '#/components/schemas/AuthenticatorWebAuthnChallenge'
|
||||
- $ref: '#/components/schemas/AutosubmitChallenge'
|
||||
- $ref: '#/components/schemas/CaptchaChallenge'
|
||||
- $ref: '#/components/schemas/ConsentChallenge'
|
||||
- $ref: '#/components/schemas/DummyChallenge'
|
||||
- $ref: '#/components/schemas/EmailChallenge'
|
||||
- $ref: '#/components/schemas/IdentificationChallenge'
|
||||
- $ref: '#/components/schemas/PasswordChallenge'
|
||||
- $ref: '#/components/schemas/PlexAuthenticationChallenge'
|
||||
- $ref: '#/components/schemas/PromptChallenge'
|
||||
- $ref: '#/components/schemas/RedirectChallenge'
|
||||
- $ref: '#/components/schemas/ShellChallenge'
|
||||
discriminator:
|
||||
propertyName: component
|
||||
mapping:
|
||||
ak-stage-access-denied: '#/components/schemas/AccessDeniedChallenge'
|
||||
ak-stage-authenticator-duo: '#/components/schemas/AuthenticatorDuoChallenge'
|
||||
ak-stage-authenticator-static: '#/components/schemas/AuthenticatorStaticChallenge'
|
||||
ak-stage-authenticator-totp: '#/components/schemas/AuthenticatorTOTPChallenge'
|
||||
ak-stage-authenticator-validate: '#/components/schemas/AuthenticatorValidationChallenge'
|
||||
ak-stage-authenticator-webauthn: '#/components/schemas/AuthenticatorWebAuthnChallenge'
|
||||
ak-stage-autosubmit: '#/components/schemas/AutosubmitChallenge'
|
||||
ak-stage-captcha: '#/components/schemas/CaptchaChallenge'
|
||||
ak-stage-consent: '#/components/schemas/ConsentChallenge'
|
||||
ak-stage-dummy: '#/components/schemas/DummyChallenge'
|
||||
ak-stage-email: '#/components/schemas/EmailChallenge'
|
||||
ak-stage-identification: '#/components/schemas/IdentificationChallenge'
|
||||
ak-stage-password: '#/components/schemas/PasswordChallenge'
|
||||
ak-flow-sources-plex: '#/components/schemas/PlexAuthenticationChallenge'
|
||||
ak-stage-prompt: '#/components/schemas/PromptChallenge'
|
||||
xak-flow-redirect: '#/components/schemas/RedirectChallenge'
|
||||
xak-flow-shell: '#/components/schemas/ShellChallenge'
|
||||
FlowChallengeResponseRequest:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/AuthenticatorDuoChallengeResponseRequest'
|
||||
@ -19775,7 +19800,7 @@ components:
|
||||
sources:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UILoginButton'
|
||||
$ref: '#/components/schemas/LoginSource'
|
||||
required:
|
||||
- password_fields
|
||||
- primary_action
|
||||
@ -20471,6 +20496,20 @@ components:
|
||||
required:
|
||||
- logins_failed_per_1h
|
||||
- logins_per_1h
|
||||
LoginSource:
|
||||
type: object
|
||||
description: Serializer for Login buttons of sources
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
icon_url:
|
||||
type: string
|
||||
nullable: true
|
||||
challenge:
|
||||
$ref: '#/components/schemas/ChallengeTypes'
|
||||
required:
|
||||
- challenge
|
||||
- name
|
||||
NameIdPolicyEnum:
|
||||
enum:
|
||||
- urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
|
||||
@ -26137,6 +26176,7 @@ components:
|
||||
forward_auth_mode:
|
||||
type: boolean
|
||||
readOnly: true
|
||||
deprecated: true
|
||||
required:
|
||||
- external_host
|
||||
- forward_auth_mode
|
||||
@ -27524,21 +27564,6 @@ components:
|
||||
- description
|
||||
- model_name
|
||||
- name
|
||||
UILoginButton:
|
||||
type: object
|
||||
description: Serializer for Login buttons of sources
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
challenge:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
icon_url:
|
||||
type: string
|
||||
nullable: true
|
||||
required:
|
||||
- challenge
|
||||
- name
|
||||
UsedBy:
|
||||
type: object
|
||||
description: A list of all objects referencing the queried object
|
||||
@ -27687,6 +27712,7 @@ components:
|
||||
enum:
|
||||
- email
|
||||
- username
|
||||
- upn
|
||||
type: string
|
||||
UserLoginStage:
|
||||
type: object
|
||||
@ -27917,7 +27943,6 @@ components:
|
||||
type: string
|
||||
required:
|
||||
- component
|
||||
- configure_url
|
||||
- object_uid
|
||||
- title
|
||||
UserWriteStage:
|
||||
|
@ -1,5 +1,4 @@
|
||||
env
|
||||
helm
|
||||
static
|
||||
htmlcov
|
||||
*.env.yml
|
||||
|
380
web/package-lock.json
generated
380
web/package-lock.json
generated
@ -9,14 +9,14 @@
|
||||
"version": "0.0.0",
|
||||
"license": "GNU GPLv3",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.14.5",
|
||||
"@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-typescript": "^7.14.5",
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"@lingui/cli": "^3.10.2",
|
||||
"@lingui/core": "^3.10.2",
|
||||
"@lingui/core": "^3.10.3",
|
||||
"@lingui/macro": "^3.10.2",
|
||||
"@patternfly/patternfly": "^4.108.2",
|
||||
"@polymer/iron-form": "^3.0.1",
|
||||
@ -24,13 +24,13 @@
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"@rollup/plugin-typescript": "^8.2.1",
|
||||
"@sentry/browser": "^6.5.1",
|
||||
"@sentry/tracing": "^6.5.1",
|
||||
"@sentry/browser": "^6.7.0",
|
||||
"@sentry/tracing": "^6.7.0",
|
||||
"@types/chart.js": "^2.9.32",
|
||||
"@types/codemirror": "5.60.0",
|
||||
"@types/grecaptcha": "^3.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.26.1",
|
||||
"@typescript-eslint/parser": "^4.26.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.27.0",
|
||||
"@typescript-eslint/parser": "^4.27.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.5.0",
|
||||
"authentik-api": "file:api",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
@ -48,7 +48,7 @@
|
||||
"lit-html": "^1.4.1",
|
||||
"moment": "^2.29.1",
|
||||
"rapidoc": "^9.0.0",
|
||||
"rollup": "^2.51.1",
|
||||
"rollup": "^2.51.2",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-cssimport": "^1.0.2",
|
||||
@ -57,7 +57,7 @@
|
||||
"rollup-plugin-sourcemaps": "^0.6.3",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"ts-lit-plugin": "^1.2.1",
|
||||
"tslib": "^2.2.0",
|
||||
"tslib": "^2.3.0",
|
||||
"typescript": "^4.3.2",
|
||||
"webcomponent-qr-code": "^1.0.5",
|
||||
"yaml": "^1.10.2"
|
||||
@ -110,16 +110,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.5.tgz",
|
||||
"integrity": "sha512-RN/AwP2DJmQTZSfiDaD+JQQ/J99KsIpOCfBE5pL+5jJSt7nI3nYGoAXZu+ffYSQ029NLs2DstZb+eR81uuARgg==",
|
||||
"version": "7.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz",
|
||||
"integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.14.5",
|
||||
"@babel/generator": "^7.14.5",
|
||||
"@babel/helper-compilation-targets": "^7.14.5",
|
||||
"@babel/helper-module-transforms": "^7.14.5",
|
||||
"@babel/helpers": "^7.14.5",
|
||||
"@babel/parser": "^7.14.5",
|
||||
"@babel/helpers": "^7.14.6",
|
||||
"@babel/parser": "^7.14.6",
|
||||
"@babel/template": "^7.14.5",
|
||||
"@babel/traverse": "^7.14.5",
|
||||
"@babel/types": "^7.14.5",
|
||||
@ -479,9 +479,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.5.tgz",
|
||||
"integrity": "sha512-xtcWOuN9VL6nApgVHtq3PPcQv5qFBJzoSZzJ/2c0QK/IP/gxVcoWSNQwFEGvmbQsuS9rhYqjILDGGXcTkA705Q==",
|
||||
"version": "7.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz",
|
||||
"integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.14.5",
|
||||
"@babel/traverse": "^7.14.5",
|
||||
@ -505,9 +505,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.5.tgz",
|
||||
"integrity": "sha512-TM8C+xtH/9n1qzX+JNHi7AN2zHMTiPUtspO0ZdHflW8KaskkALhMmuMHb4bCmNdv9VAPzJX3/bXqkVLnAvsPfg==",
|
||||
"version": "7.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.6.tgz",
|
||||
"integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
@ -2047,9 +2047,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lingui/core": {
|
||||
"version": "3.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.10.2.tgz",
|
||||
"integrity": "sha512-RL4Bn1s4Ukd0GBlEFO/+GoxnK48xuZR2GwFslg/eQxcQmeOA4c1Jw/tbvMKDfi40XwqMBWcS0G2njpWjuHC3SA==",
|
||||
"version": "3.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.10.3.tgz",
|
||||
"integrity": "sha512-BiuWi5xPpQa27oIWWnkOYNx4qTMdMeu7vp5y1AGPYQ/4SO0rHfAtOxXtvRU/ktVwht/lIgx5Ygq5J3F+XLvOQA==",
|
||||
"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.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.5.1.tgz",
|
||||
"integrity": "sha512-iVLCdEFwsoWAzE/hNknexPQjjDpMQV7mmaq9Z1P63bD6MfhwVTx4hG4pHn8HEvC38VvCVf1wv0v/LxtoODAYXg==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.7.0.tgz",
|
||||
"integrity": "sha512-sZvy2fxHjHXPdlaz8Ax02BeUbdILRv6a4i9FvMHvgSBeDiAVRIS+ihBhJAqziNOqwwXYThCSPKcCYGyTTncrVw==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "6.5.1",
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/utils": "6.5.1",
|
||||
"@sentry/core": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2333,14 +2333,14 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.5.1.tgz",
|
||||
"integrity": "sha512-Mh3sl/iUOT1myHmM6RlDy2ARzkUClx/g4DAt1rJ/IpQBOlDYQraplXSIW80i/hzRgQDfwhwgf4wUa5DicKBjKw==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.7.0.tgz",
|
||||
"integrity": "sha512-1TzDQIsS71a+6T1o3+NPyIgsTc37wdGh7cKZ8DRQ4bsML7MAkBV/LJeTVbXa0S9xha1v9v/oPindnHX5vBLJbg==",
|
||||
"dependencies": {
|
||||
"@sentry/hub": "6.5.1",
|
||||
"@sentry/minimal": "6.5.1",
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/utils": "6.5.1",
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/minimal": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2353,12 +2353,12 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/hub": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.5.1.tgz",
|
||||
"integrity": "sha512-lBRMBVMYP8B4PfRiM70murbtJAXiIAao/asDEMIRNGMP6pI2ArqXfJCBYDkStukhikYD0Kqb4trXq+JYF07Hbg==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.7.0.tgz",
|
||||
"integrity": "sha512-8e1IF6v8OIjuZVsolBAFoHhY0fEolsWwmZzm9k5N1wXWRbu4gpLHnCtDw47u2O9CFYr+b//bNXjmsA+DTckPkw==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/utils": "6.5.1",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2371,12 +2371,12 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/minimal": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.5.1.tgz",
|
||||
"integrity": "sha512-q9Do/oreu1RP695CXCLowVDuQyk7ilE6FGdz2QLpTXAfx8247qOwk6+zy9Kea/Djk93+BoSDVQUSneNiVwl0nQ==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.7.0.tgz",
|
||||
"integrity": "sha512-q0SX2t1+6c8TSe8nI4+EsWc8+kSsKiGhoGo2tN2OTk4EXKCYEsEEDqB9iu7md5StmtmrO3UnRiYwT7JV8QGOeg==",
|
||||
"dependencies": {
|
||||
"@sentry/hub": "6.5.1",
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2389,14 +2389,14 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/tracing": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.5.1.tgz",
|
||||
"integrity": "sha512-y1W/xFC2hAuKqSuuaovkElHY4pbli3XoXrreesg8PtO7ilX6ZbatOQbHsEsHQyoUv0F6aVA+MABOxWH2jt7tfw==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.7.0.tgz",
|
||||
"integrity": "sha512-5joTxxDB4v2J1B3CIGDj4AJKJpeGztqExQMkCrwwWgBsZ+fFfctRSCyiwYo50TU93Zt/rt0rDjj8QF4o8ZH09A==",
|
||||
"dependencies": {
|
||||
"@sentry/hub": "6.5.1",
|
||||
"@sentry/minimal": "6.5.1",
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/utils": "6.5.1",
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/minimal": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2409,19 +2409,19 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.5.1.tgz",
|
||||
"integrity": "sha512-b/7a6CMoytaeFPx4IBjfxPw3nPvsQh7ui1C8Vw0LxNNDgBwVhPLzUOWeLWbo5YZCVbGEMIWwtCUQYWxneceZSA==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.7.0.tgz",
|
||||
"integrity": "sha512-5pKv0yJEOnkjy3J3eiGaM1CD2+p3rXkctJa8loZH7QgY7mJgUTKpozO3YymUmGjblthlrbuhH+5wUIBnVF60Bg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.5.1.tgz",
|
||||
"integrity": "sha512-Wv86JYGQH+ZJ5XGFQX7h6ijl32667ikenoL9EyXMn8UoOYX/MLwZoQZin1P60wmKkYR9ifTNVmpaI9OoTaH+UQ==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.7.0.tgz",
|
||||
"integrity": "sha512-K6s9svqOF4TT4AwvlDdiV9ZSGStSnf64s8KH1DNqwu5EZULvXvg0kbqgi6ZJTDHcchbnwHm7hLMNfuw95Aqi4Q==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/types": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -2579,12 +2579,12 @@
|
||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.26.1.tgz",
|
||||
"integrity": "sha512-aoIusj/8CR+xDWmZxARivZjbMBQTT9dImUtdZ8tVCVRXgBUuuZyM5Of5A9D9arQPxbi/0rlJLcuArclz/rCMJw==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.27.0.tgz",
|
||||
"integrity": "sha512-DsLqxeUfLVNp3AO7PC3JyaddmEHTtI9qTSAs+RB6ja27QvIM0TA8Cizn1qcS6vOu+WDLFJzkwkgweiyFhssDdQ==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/experimental-utils": "4.26.1",
|
||||
"@typescript-eslint/scope-manager": "4.26.1",
|
||||
"@typescript-eslint/experimental-utils": "4.27.0",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"debug": "^4.3.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
@ -2610,14 +2610,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/experimental-utils": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.26.1.tgz",
|
||||
"integrity": "sha512-sQHBugRhrXzRCs9PaGg6rowie4i8s/iD/DpTB+EXte8OMDfdCG5TvO73XlO9Wc/zi0uyN4qOmX9hIjQEyhnbmQ==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.27.0.tgz",
|
||||
"integrity": "sha512-n5NlbnmzT2MXlyT+Y0Jf0gsmAQzCnQSWXKy4RGSXVStjDvS5we9IWbh7qRVKdGcxT0WYlgcCYUK/HRg7xFhvjQ==",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.7",
|
||||
"@typescript-eslint/scope-manager": "4.26.1",
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/typescript-estree": "4.26.1",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/typescript-estree": "4.27.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
@ -2650,13 +2650,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.26.1.tgz",
|
||||
"integrity": "sha512-q7F3zSo/nU6YJpPJvQveVlIIzx9/wu75lr6oDbDzoeIRWxpoc/HQ43G4rmMoCc5my/3uSj2VEpg/D83LYZF5HQ==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.27.0.tgz",
|
||||
"integrity": "sha512-XpbxL+M+gClmJcJ5kHnUpBGmlGdgNvy6cehgR6ufyxkEJMGP25tZKCaKyC0W/JVpuhU3VU1RBn7SYUPKSMqQvQ==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "4.26.1",
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/typescript-estree": "4.26.1",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/typescript-estree": "4.27.0",
|
||||
"debug": "^4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -2676,12 +2676,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.26.1.tgz",
|
||||
"integrity": "sha512-TW1X2p62FQ8Rlne+WEShyd7ac2LA6o27S9i131W4NwDSfyeVlQWhw8ylldNNS8JG6oJB9Ha9Xyc+IUcqipvheQ==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.27.0.tgz",
|
||||
"integrity": "sha512-DY73jK6SEH6UDdzc6maF19AHQJBFVRf6fgAXHPXCGEmpqD4vYgPEzqpFz1lf/daSbOcMpPPj9tyXXDPW2XReAw==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/visitor-keys": "4.26.1"
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/visitor-keys": "4.27.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
@ -2692,9 +2692,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.26.1.tgz",
|
||||
"integrity": "sha512-STyMPxR3cS+LaNvS8yK15rb8Y0iL0tFXq0uyl6gY45glyI7w0CsyqyEXl/Fa0JlQy+pVANeK3sbwPneCbWE7yg==",
|
||||
"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==",
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
},
|
||||
@ -2704,12 +2704,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.26.1.tgz",
|
||||
"integrity": "sha512-l3ZXob+h0NQzz80lBGaykdScYaiEbFqznEs99uwzm8fPHhDjwaBFfQkjUC/slw6Sm7npFL8qrGEAMxcfBsBJUg==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.27.0.tgz",
|
||||
"integrity": "sha512-KH03GUsUj41sRLLEy2JHstnezgpS5VNhrJouRdmh6yNdQ+yl8w5LrSwBkExM+jWwCJa7Ct2c8yl8NdtNRyQO6g==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/visitor-keys": "4.26.1",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/visitor-keys": "4.27.0",
|
||||
"debug": "^4.3.1",
|
||||
"globby": "^11.0.3",
|
||||
"is-glob": "^4.0.1",
|
||||
@ -2749,11 +2749,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.26.1.tgz",
|
||||
"integrity": "sha512-IGouNSSd+6x/fHtYRyLOM6/C+QxMDzWlDtN41ea+flWuSF9g02iqcIlX8wM53JkfljoIjP0U+yp7SiTS1onEkw==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.27.0.tgz",
|
||||
"integrity": "sha512-es0GRYNZp0ieckZ938cEANfEhsfHrzuLrePukLKtY3/KPXcq1Xd555Mno9/GOgXhKzn0QfkDLVgqWO3dGY80bg==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -6771,9 +6771,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "2.51.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.1.tgz",
|
||||
"integrity": "sha512-8xfDbAtBleXotb6qKEHWuo/jkn94a9dVqGc7Rwl3sqspCVlnCfbRek7ldhCARSi7h32H0xR4QThm1t9zHN+3uw==",
|
||||
"version": "2.51.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.2.tgz",
|
||||
"integrity": "sha512-ReV2eGEadA7hmXSzjxdDKs10neqH2QURf2RxJ6ayAlq93ugy6qIvXMmbc5cWMGCDh1h5T4thuWO1e2VNbMq8FA==",
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
@ -7570,9 +7570,9 @@
|
||||
"integrity": "sha512-zKmsCQs4dZaeSKjEA7pLFDv7FHHqAFLPd0Mr//OIJvu8M+4p4bgSFJwZSEBEg3ec9W7RzRz1vi8giiX0+mheBQ=="
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
|
||||
"integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
|
||||
},
|
||||
"node_modules/tsutils": {
|
||||
"version": "3.21.0",
|
||||
@ -8071,16 +8071,16 @@
|
||||
"integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w=="
|
||||
},
|
||||
"@babel/core": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.5.tgz",
|
||||
"integrity": "sha512-RN/AwP2DJmQTZSfiDaD+JQQ/J99KsIpOCfBE5pL+5jJSt7nI3nYGoAXZu+ffYSQ029NLs2DstZb+eR81uuARgg==",
|
||||
"version": "7.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz",
|
||||
"integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.14.5",
|
||||
"@babel/generator": "^7.14.5",
|
||||
"@babel/helper-compilation-targets": "^7.14.5",
|
||||
"@babel/helper-module-transforms": "^7.14.5",
|
||||
"@babel/helpers": "^7.14.5",
|
||||
"@babel/parser": "^7.14.5",
|
||||
"@babel/helpers": "^7.14.6",
|
||||
"@babel/parser": "^7.14.6",
|
||||
"@babel/template": "^7.14.5",
|
||||
"@babel/traverse": "^7.14.5",
|
||||
"@babel/types": "^7.14.5",
|
||||
@ -8345,9 +8345,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/helpers": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.5.tgz",
|
||||
"integrity": "sha512-xtcWOuN9VL6nApgVHtq3PPcQv5qFBJzoSZzJ/2c0QK/IP/gxVcoWSNQwFEGvmbQsuS9rhYqjILDGGXcTkA705Q==",
|
||||
"version": "7.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz",
|
||||
"integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==",
|
||||
"requires": {
|
||||
"@babel/template": "^7.14.5",
|
||||
"@babel/traverse": "^7.14.5",
|
||||
@ -8365,9 +8365,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.5.tgz",
|
||||
"integrity": "sha512-TM8C+xtH/9n1qzX+JNHi7AN2zHMTiPUtspO0ZdHflW8KaskkALhMmuMHb4bCmNdv9VAPzJX3/bXqkVLnAvsPfg=="
|
||||
"version": "7.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.6.tgz",
|
||||
"integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ=="
|
||||
},
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
|
||||
"version": "7.14.5",
|
||||
@ -9431,9 +9431,9 @@
|
||||
}
|
||||
},
|
||||
"@lingui/core": {
|
||||
"version": "3.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.10.2.tgz",
|
||||
"integrity": "sha512-RL4Bn1s4Ukd0GBlEFO/+GoxnK48xuZR2GwFslg/eQxcQmeOA4c1Jw/tbvMKDfi40XwqMBWcS0G2njpWjuHC3SA==",
|
||||
"version": "3.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.10.3.tgz",
|
||||
"integrity": "sha512-BiuWi5xPpQa27oIWWnkOYNx4qTMdMeu7vp5y1AGPYQ/4SO0rHfAtOxXtvRU/ktVwht/lIgx5Ygq5J3F+XLvOQA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"make-plural": "^6.2.2",
|
||||
@ -9670,13 +9670,13 @@
|
||||
}
|
||||
},
|
||||
"@sentry/browser": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.5.1.tgz",
|
||||
"integrity": "sha512-iVLCdEFwsoWAzE/hNknexPQjjDpMQV7mmaq9Z1P63bD6MfhwVTx4hG4pHn8HEvC38VvCVf1wv0v/LxtoODAYXg==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.7.0.tgz",
|
||||
"integrity": "sha512-sZvy2fxHjHXPdlaz8Ax02BeUbdILRv6a4i9FvMHvgSBeDiAVRIS+ihBhJAqziNOqwwXYThCSPKcCYGyTTncrVw==",
|
||||
"requires": {
|
||||
"@sentry/core": "6.5.1",
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/utils": "6.5.1",
|
||||
"@sentry/core": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9688,14 +9688,14 @@
|
||||
}
|
||||
},
|
||||
"@sentry/core": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.5.1.tgz",
|
||||
"integrity": "sha512-Mh3sl/iUOT1myHmM6RlDy2ARzkUClx/g4DAt1rJ/IpQBOlDYQraplXSIW80i/hzRgQDfwhwgf4wUa5DicKBjKw==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.7.0.tgz",
|
||||
"integrity": "sha512-1TzDQIsS71a+6T1o3+NPyIgsTc37wdGh7cKZ8DRQ4bsML7MAkBV/LJeTVbXa0S9xha1v9v/oPindnHX5vBLJbg==",
|
||||
"requires": {
|
||||
"@sentry/hub": "6.5.1",
|
||||
"@sentry/minimal": "6.5.1",
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/utils": "6.5.1",
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/minimal": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9707,12 +9707,12 @@
|
||||
}
|
||||
},
|
||||
"@sentry/hub": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.5.1.tgz",
|
||||
"integrity": "sha512-lBRMBVMYP8B4PfRiM70murbtJAXiIAao/asDEMIRNGMP6pI2ArqXfJCBYDkStukhikYD0Kqb4trXq+JYF07Hbg==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.7.0.tgz",
|
||||
"integrity": "sha512-8e1IF6v8OIjuZVsolBAFoHhY0fEolsWwmZzm9k5N1wXWRbu4gpLHnCtDw47u2O9CFYr+b//bNXjmsA+DTckPkw==",
|
||||
"requires": {
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/utils": "6.5.1",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9724,12 +9724,12 @@
|
||||
}
|
||||
},
|
||||
"@sentry/minimal": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.5.1.tgz",
|
||||
"integrity": "sha512-q9Do/oreu1RP695CXCLowVDuQyk7ilE6FGdz2QLpTXAfx8247qOwk6+zy9Kea/Djk93+BoSDVQUSneNiVwl0nQ==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.7.0.tgz",
|
||||
"integrity": "sha512-q0SX2t1+6c8TSe8nI4+EsWc8+kSsKiGhoGo2tN2OTk4EXKCYEsEEDqB9iu7md5StmtmrO3UnRiYwT7JV8QGOeg==",
|
||||
"requires": {
|
||||
"@sentry/hub": "6.5.1",
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9741,14 +9741,14 @@
|
||||
}
|
||||
},
|
||||
"@sentry/tracing": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.5.1.tgz",
|
||||
"integrity": "sha512-y1W/xFC2hAuKqSuuaovkElHY4pbli3XoXrreesg8PtO7ilX6ZbatOQbHsEsHQyoUv0F6aVA+MABOxWH2jt7tfw==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.7.0.tgz",
|
||||
"integrity": "sha512-5joTxxDB4v2J1B3CIGDj4AJKJpeGztqExQMkCrwwWgBsZ+fFfctRSCyiwYo50TU93Zt/rt0rDjj8QF4o8ZH09A==",
|
||||
"requires": {
|
||||
"@sentry/hub": "6.5.1",
|
||||
"@sentry/minimal": "6.5.1",
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/utils": "6.5.1",
|
||||
"@sentry/hub": "6.7.0",
|
||||
"@sentry/minimal": "6.7.0",
|
||||
"@sentry/types": "6.7.0",
|
||||
"@sentry/utils": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9760,16 +9760,16 @@
|
||||
}
|
||||
},
|
||||
"@sentry/types": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.5.1.tgz",
|
||||
"integrity": "sha512-b/7a6CMoytaeFPx4IBjfxPw3nPvsQh7ui1C8Vw0LxNNDgBwVhPLzUOWeLWbo5YZCVbGEMIWwtCUQYWxneceZSA=="
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.7.0.tgz",
|
||||
"integrity": "sha512-5pKv0yJEOnkjy3J3eiGaM1CD2+p3rXkctJa8loZH7QgY7mJgUTKpozO3YymUmGjblthlrbuhH+5wUIBnVF60Bg=="
|
||||
},
|
||||
"@sentry/utils": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.5.1.tgz",
|
||||
"integrity": "sha512-Wv86JYGQH+ZJ5XGFQX7h6ijl32667ikenoL9EyXMn8UoOYX/MLwZoQZin1P60wmKkYR9ifTNVmpaI9OoTaH+UQ==",
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.7.0.tgz",
|
||||
"integrity": "sha512-K6s9svqOF4TT4AwvlDdiV9ZSGStSnf64s8KH1DNqwu5EZULvXvg0kbqgi6ZJTDHcchbnwHm7hLMNfuw95Aqi4Q==",
|
||||
"requires": {
|
||||
"@sentry/types": "6.5.1",
|
||||
"@sentry/types": "6.7.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -9926,12 +9926,12 @@
|
||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.26.1.tgz",
|
||||
"integrity": "sha512-aoIusj/8CR+xDWmZxARivZjbMBQTT9dImUtdZ8tVCVRXgBUuuZyM5Of5A9D9arQPxbi/0rlJLcuArclz/rCMJw==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.27.0.tgz",
|
||||
"integrity": "sha512-DsLqxeUfLVNp3AO7PC3JyaddmEHTtI9qTSAs+RB6ja27QvIM0TA8Cizn1qcS6vOu+WDLFJzkwkgweiyFhssDdQ==",
|
||||
"requires": {
|
||||
"@typescript-eslint/experimental-utils": "4.26.1",
|
||||
"@typescript-eslint/scope-manager": "4.26.1",
|
||||
"@typescript-eslint/experimental-utils": "4.27.0",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"debug": "^4.3.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
@ -9941,14 +9941,14 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.26.1.tgz",
|
||||
"integrity": "sha512-sQHBugRhrXzRCs9PaGg6rowie4i8s/iD/DpTB+EXte8OMDfdCG5TvO73XlO9Wc/zi0uyN4qOmX9hIjQEyhnbmQ==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.27.0.tgz",
|
||||
"integrity": "sha512-n5NlbnmzT2MXlyT+Y0Jf0gsmAQzCnQSWXKy4RGSXVStjDvS5we9IWbh7qRVKdGcxT0WYlgcCYUK/HRg7xFhvjQ==",
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.7",
|
||||
"@typescript-eslint/scope-manager": "4.26.1",
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/typescript-estree": "4.26.1",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/typescript-estree": "4.27.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
@ -9964,37 +9964,37 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.26.1.tgz",
|
||||
"integrity": "sha512-q7F3zSo/nU6YJpPJvQveVlIIzx9/wu75lr6oDbDzoeIRWxpoc/HQ43G4rmMoCc5my/3uSj2VEpg/D83LYZF5HQ==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.27.0.tgz",
|
||||
"integrity": "sha512-XpbxL+M+gClmJcJ5kHnUpBGmlGdgNvy6cehgR6ufyxkEJMGP25tZKCaKyC0W/JVpuhU3VU1RBn7SYUPKSMqQvQ==",
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "4.26.1",
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/typescript-estree": "4.26.1",
|
||||
"@typescript-eslint/scope-manager": "4.27.0",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/typescript-estree": "4.27.0",
|
||||
"debug": "^4.3.1"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.26.1.tgz",
|
||||
"integrity": "sha512-TW1X2p62FQ8Rlne+WEShyd7ac2LA6o27S9i131W4NwDSfyeVlQWhw8ylldNNS8JG6oJB9Ha9Xyc+IUcqipvheQ==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.27.0.tgz",
|
||||
"integrity": "sha512-DY73jK6SEH6UDdzc6maF19AHQJBFVRf6fgAXHPXCGEmpqD4vYgPEzqpFz1lf/daSbOcMpPPj9tyXXDPW2XReAw==",
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/visitor-keys": "4.26.1"
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/visitor-keys": "4.27.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.26.1.tgz",
|
||||
"integrity": "sha512-STyMPxR3cS+LaNvS8yK15rb8Y0iL0tFXq0uyl6gY45glyI7w0CsyqyEXl/Fa0JlQy+pVANeK3sbwPneCbWE7yg=="
|
||||
"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=="
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.26.1.tgz",
|
||||
"integrity": "sha512-l3ZXob+h0NQzz80lBGaykdScYaiEbFqznEs99uwzm8fPHhDjwaBFfQkjUC/slw6Sm7npFL8qrGEAMxcfBsBJUg==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.27.0.tgz",
|
||||
"integrity": "sha512-KH03GUsUj41sRLLEy2JHstnezgpS5VNhrJouRdmh6yNdQ+yl8w5LrSwBkExM+jWwCJa7Ct2c8yl8NdtNRyQO6g==",
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/visitor-keys": "4.26.1",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"@typescript-eslint/visitor-keys": "4.27.0",
|
||||
"debug": "^4.3.1",
|
||||
"globby": "^11.0.3",
|
||||
"is-glob": "^4.0.1",
|
||||
@ -10018,11 +10018,11 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.26.1.tgz",
|
||||
"integrity": "sha512-IGouNSSd+6x/fHtYRyLOM6/C+QxMDzWlDtN41ea+flWuSF9g02iqcIlX8wM53JkfljoIjP0U+yp7SiTS1onEkw==",
|
||||
"version": "4.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.27.0.tgz",
|
||||
"integrity": "sha512-es0GRYNZp0ieckZ938cEANfEhsfHrzuLrePukLKtY3/KPXcq1Xd555Mno9/GOgXhKzn0QfkDLVgqWO3dGY80bg==",
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.26.1",
|
||||
"@typescript-eslint/types": "4.27.0",
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
}
|
||||
},
|
||||
@ -13202,9 +13202,9 @@
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.51.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.1.tgz",
|
||||
"integrity": "sha512-8xfDbAtBleXotb6qKEHWuo/jkn94a9dVqGc7Rwl3sqspCVlnCfbRek7ldhCARSi7h32H0xR4QThm1t9zHN+3uw==",
|
||||
"version": "2.51.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.2.tgz",
|
||||
"integrity": "sha512-ReV2eGEadA7hmXSzjxdDKs10neqH2QURf2RxJ6ayAlq93ugy6qIvXMmbc5cWMGCDh1h5T4thuWO1e2VNbMq8FA==",
|
||||
"requires": {
|
||||
"fsevents": "~2.3.1"
|
||||
}
|
||||
@ -13870,9 +13870,9 @@
|
||||
"integrity": "sha512-zKmsCQs4dZaeSKjEA7pLFDv7FHHqAFLPd0Mr//OIJvu8M+4p4bgSFJwZSEBEg3ec9W7RzRz1vi8giiX0+mheBQ=="
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
|
||||
"integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
|
||||
},
|
||||
"tsutils": {
|
||||
"version": "3.21.0",
|
||||
|
@ -38,14 +38,14 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.14.5",
|
||||
"@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-typescript": "^7.14.5",
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"@lingui/cli": "^3.10.2",
|
||||
"@lingui/core": "^3.10.2",
|
||||
"@lingui/core": "^3.10.3",
|
||||
"@lingui/macro": "^3.10.2",
|
||||
"@patternfly/patternfly": "^4.108.2",
|
||||
"@polymer/iron-form": "^3.0.1",
|
||||
@ -53,13 +53,13 @@
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"@rollup/plugin-typescript": "^8.2.1",
|
||||
"@sentry/browser": "^6.5.1",
|
||||
"@sentry/tracing": "^6.5.1",
|
||||
"@sentry/browser": "^6.7.0",
|
||||
"@sentry/tracing": "^6.7.0",
|
||||
"@types/chart.js": "^2.9.32",
|
||||
"@types/codemirror": "5.60.0",
|
||||
"@types/grecaptcha": "^3.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.26.1",
|
||||
"@typescript-eslint/parser": "^4.26.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.27.0",
|
||||
"@typescript-eslint/parser": "^4.27.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.5.0",
|
||||
"authentik-api": "file:api",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
@ -77,7 +77,7 @@
|
||||
"lit-html": "^1.4.1",
|
||||
"moment": "^2.29.1",
|
||||
"rapidoc": "^9.0.0",
|
||||
"rollup": "^2.51.1",
|
||||
"rollup": "^2.51.2",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-cssimport": "^1.0.2",
|
||||
@ -86,7 +86,7 @@
|
||||
"rollup-plugin-sourcemaps": "^0.6.3",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"ts-lit-plugin": "^1.2.1",
|
||||
"tslib": "^2.2.0",
|
||||
"tslib": "^2.3.0",
|
||||
"typescript": "^4.3.2",
|
||||
"webcomponent-qr-code": "^1.0.5",
|
||||
"yaml": "^1.10.2"
|
||||
|
@ -8,10 +8,22 @@ export interface EventUser {
|
||||
}
|
||||
|
||||
export interface EventContext {
|
||||
[key: string]: EventContext | string | number | string[];
|
||||
[key: string]: EventContext | EventModel | string | number | string[];
|
||||
}
|
||||
|
||||
export interface EventWithContext extends Event {
|
||||
user: EventUser;
|
||||
context: EventContext;
|
||||
}
|
||||
|
||||
export interface EventModel {
|
||||
pk: string;
|
||||
name: string;
|
||||
app: string;
|
||||
model_name: string;
|
||||
}
|
||||
|
||||
export interface EventRequest {
|
||||
path: string;
|
||||
method: string;
|
||||
}
|
||||
|
@ -7,8 +7,9 @@ import { config } from "./Config";
|
||||
import { Config } from "authentik-api";
|
||||
|
||||
export const TAG_SENTRY_COMPONENT = "authentik.component";
|
||||
export const TAG_SENTRY_CAPABILITIES = "authentik.capabilities";
|
||||
|
||||
export function configureSentry(canDoPpi: boolean = false, tags: { [key: string]: string; } = {}): Promise<Config> {
|
||||
export function configureSentry(canDoPpi: boolean = false): Promise<Config> {
|
||||
return config().then((config) => {
|
||||
if (config.errorReportingEnabled) {
|
||||
Sentry.init({
|
||||
@ -53,7 +54,7 @@ export function configureSentry(canDoPpi: boolean = false, tags: { [key: string]
|
||||
return event;
|
||||
},
|
||||
});
|
||||
Sentry.setTags(tags);
|
||||
Sentry.setTag(TAG_SENTRY_CAPABILITIES, config.capabilities.join(","));
|
||||
if (window.location.pathname.includes("if/")) {
|
||||
// Get the interface name from URL
|
||||
const intf = window.location.pathname.replace(/.+if\/(.+)\//, "$1");
|
||||
|
@ -257,6 +257,12 @@ body {
|
||||
.pf-c-dropdown__toggle::before {
|
||||
border-color: transparent;
|
||||
}
|
||||
.pf-c-toggle-group__button {
|
||||
color: var(--ak-dark-foreground) !important;
|
||||
}
|
||||
.pf-c-toggle-group__button:not(.pf-m-selected) {
|
||||
background-color: var(--ak-dark-background-light) !important;
|
||||
}
|
||||
/* inputs help text */
|
||||
.pf-c-form__helper-text:not(.pf-m-error) {
|
||||
color: var(--ak-dark-foreground);
|
||||
|
@ -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-rc2";
|
||||
export const VERSION = "2021.6.1-rc6";
|
||||
export const PAGE_SIZE = 20;
|
||||
export const EVENT_REFRESH = "ak-refresh";
|
||||
export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";
|
||||
|
@ -1,27 +0,0 @@
|
||||
import { customElement, CSSResult, html, LitElement, property, TemplateResult } from "lit-element";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css";
|
||||
import PFBanner from "@patternfly/patternfly/components/Banner/banner.css";
|
||||
import AKGlobal from "../authentik.css";
|
||||
|
||||
@customElement("ak-banner")
|
||||
export class Banner extends LitElement {
|
||||
|
||||
@property()
|
||||
level = "pf-m-warning";
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFBanner, PFFlex, AKGlobal];
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<div class="pf-c-banner ${this.level} pf-m-sticky">
|
||||
<div class="pf-l-flex pf-m-justify-content-center pf-m-justify-content-space-between-on-lg pf-m-nowrap" style="height: 100%;">
|
||||
<div class="pf-u-display-none pf-u-display-block-on-lg">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
}
|
@ -7,7 +7,6 @@ import PFFormControl from "@patternfly/patternfly/components/FormControl/form-co
|
||||
import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css";
|
||||
import PFBackdrop from "@patternfly/patternfly/components/Backdrop/backdrop.css";
|
||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||
import PFStack from "@patternfly/patternfly/layouts/Stack/stack.css";
|
||||
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||
import PFTitle from "@patternfly/patternfly/components/Title/title.css";
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
@ -40,7 +39,7 @@ export class ModalButton extends LitElement {
|
||||
open = false;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFButton, PFModalBox, PFForm, PFTitle, PFFormControl, PFBullseye, PFBackdrop, PFPage, PFStack, PFCard, PFContent, AKGlobal, MODAL_BUTTON_STYLES];
|
||||
return [PFBase, PFButton, PFModalBox, PFForm, PFTitle, PFFormControl, PFBullseye, PFBackdrop, PFPage, PFCard, PFContent, AKGlobal, MODAL_BUTTON_STYLES];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
|
@ -19,7 +19,6 @@ export class Sidebar extends LitElement {
|
||||
css`
|
||||
:host {
|
||||
z-index: 100;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.pf-c-nav__link.pf-m-current::after,
|
||||
.pf-c-nav__link.pf-m-current:hover::after,
|
||||
|
@ -21,6 +21,13 @@ export class SidebarItem extends LitElement {
|
||||
z-index: 100;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
:host([highlight]) .pf-c-nav__item {
|
||||
background-color: var(--ak-accent);
|
||||
margin: 16px;
|
||||
}
|
||||
:host([highlight]) .pf-c-nav__item .pf-c-nav__link {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
.pf-c-nav__link.pf-m-current::after,
|
||||
.pf-c-nav__link.pf-m-current:hover::after,
|
||||
.pf-c-nav__item.pf-m-current:not(.pf-m-expanded) .pf-c-nav__link::after {
|
||||
@ -75,6 +82,12 @@ export class SidebarItem extends LitElement {
|
||||
@property({ type: Boolean })
|
||||
isActive = false;
|
||||
|
||||
@property({ type: Boolean })
|
||||
isAbsoluteLink?: boolean;
|
||||
|
||||
@property({ type: Boolean })
|
||||
highlight?: boolean;
|
||||
|
||||
parent?: SidebarItem;
|
||||
|
||||
get childItems(): SidebarItem[] {
|
||||
@ -159,9 +172,15 @@ export class SidebarItem extends LitElement {
|
||||
</li>`;
|
||||
}
|
||||
return html`<li class="pf-c-nav__item">
|
||||
<a href="#${this.path}" class="pf-c-nav__link ${this.isActive ? "pf-m-current" : ""}">
|
||||
<slot name="label"></slot>
|
||||
</a>
|
||||
${this.path ? html`
|
||||
<a href="${this.isAbsoluteLink ? "" : "#"}${this.path}" class="pf-c-nav__link ${this.isActive ? "pf-m-current" : ""}">
|
||||
<slot name="label"></slot>
|
||||
</a>
|
||||
` : html`
|
||||
<span class="pf-c-nav__link">
|
||||
<slot name="label"></slot>
|
||||
</span>
|
||||
`}
|
||||
</li>`;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import "./stages/password/PasswordStage";
|
||||
import "./stages/prompt/PromptStage";
|
||||
import "./sources/plex/PlexLoginInit";
|
||||
import { StageHost } from "./stages/base";
|
||||
import { ChallengeChoices, CurrentTenant, FlowChallengeRequest, FlowChallengeResponseRequest, FlowsApi, RedirectChallenge, ShellChallenge } from "authentik-api";
|
||||
import { ChallengeChoices, CurrentTenant, ChallengeTypes, FlowChallengeResponseRequest, FlowsApi, RedirectChallenge, ShellChallenge } from "authentik-api";
|
||||
import { DEFAULT_CONFIG, tenant } from "../api/Config";
|
||||
import { ifDefined } from "lit-html/directives/if-defined";
|
||||
import { until } from "lit-html/directives/until";
|
||||
@ -40,7 +40,7 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
flowSlug: string;
|
||||
|
||||
@property({attribute: false})
|
||||
challenge?: FlowChallengeRequest;
|
||||
challenge?: ChallengeTypes;
|
||||
|
||||
@property({type: Boolean})
|
||||
loading = false;
|
||||
@ -107,8 +107,8 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
}).then((data) => {
|
||||
this.challenge = data;
|
||||
this.postUpdate();
|
||||
}).catch((e: Error) => {
|
||||
this.errorMessage(e.toString());
|
||||
}).catch((e: Error | Response) => {
|
||||
this.errorMessage(e);
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
@ -128,15 +128,21 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
this.setBackground(this.challenge.flowInfo.background);
|
||||
}
|
||||
this.postUpdate();
|
||||
}).catch((e: Error) => {
|
||||
}).catch((e: Error | Response) => {
|
||||
// Catch JSON or Update errors
|
||||
this.errorMessage(e.toString());
|
||||
this.errorMessage(e);
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
errorMessage(error: string): void {
|
||||
async errorMessage(error: Error | Response): Promise<void> {
|
||||
let body = "";
|
||||
if (error instanceof Error) {
|
||||
body = error.message;
|
||||
} else if (error instanceof Response) {
|
||||
body = await error.text();
|
||||
}
|
||||
this.challenge = {
|
||||
type: ChallengeChoices.Shell,
|
||||
body: `<header class="pf-c-login__main-header">
|
||||
@ -146,7 +152,7 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
</header>
|
||||
<div class="pf-c-login__main-body">
|
||||
<h3>${t`Something went wrong! Please try again later.`}</h3>
|
||||
<pre class="ak-exception">${error}</pre>
|
||||
<pre class="ak-exception">${body}</pre>
|
||||
</div>
|
||||
<footer class="pf-c-login__main-footer">
|
||||
<ul class="pf-c-login__main-footer-links">
|
||||
@ -157,7 +163,7 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
</li>
|
||||
</ul>
|
||||
</footer>`
|
||||
} as FlowChallengeRequest;
|
||||
} as ChallengeTypes;
|
||||
}
|
||||
|
||||
renderLoading(): TemplateResult {
|
||||
|
@ -11,7 +11,7 @@ import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";
|
||||
import AKGlobal from "../../../authentik.css";
|
||||
import "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import { FlowChallengeRequest, IdentificationChallenge, IdentificationChallengeResponseRequest, UILoginButton } from "authentik-api";
|
||||
import { IdentificationChallenge, IdentificationChallengeResponseRequest, LoginSource, UserFieldsEnum } from "authentik-api";
|
||||
|
||||
export const PasswordManagerPrefill: {
|
||||
password: string | undefined;
|
||||
@ -21,6 +21,7 @@ export const PasswordManagerPrefill: {
|
||||
totp: undefined,
|
||||
};
|
||||
|
||||
export const OR_LIST_FORMATTERS = new Intl.ListFormat("default", { style: "short", type: "disjunction" });
|
||||
|
||||
@customElement("ak-stage-identification")
|
||||
export class IdentificationStage extends BaseStage<IdentificationChallenge, IdentificationChallengeResponseRequest> {
|
||||
@ -109,7 +110,7 @@ export class IdentificationStage extends BaseStage<IdentificationChallenge, Iden
|
||||
wrapperForm.appendChild(totp);
|
||||
}
|
||||
|
||||
renderSource(source: UILoginButton): TemplateResult {
|
||||
renderSource(source: LoginSource): TemplateResult {
|
||||
let icon = html`<i class="fas fas fa-share-square" title="${source.name}"></i>`;
|
||||
if (source.iconUrl) {
|
||||
icon = html`<img src="${source.iconUrl}" alt="${source.name}">`;
|
||||
@ -117,7 +118,7 @@ export class IdentificationStage extends BaseStage<IdentificationChallenge, Iden
|
||||
return html`<li class="pf-c-login__main-footer-links-item">
|
||||
<button type="button" @click=${() => {
|
||||
if (!this.host) return;
|
||||
this.host.challenge = source.challenge as FlowChallengeRequest;
|
||||
this.host.challenge = source.challenge;
|
||||
}}>
|
||||
${icon}
|
||||
</button>
|
||||
@ -142,21 +143,23 @@ export class IdentificationStage extends BaseStage<IdentificationChallenge, Iden
|
||||
}
|
||||
|
||||
renderInput(): TemplateResult {
|
||||
let label = "";
|
||||
let type = "text";
|
||||
if (!this.challenge?.userFields) {
|
||||
return html`<p>
|
||||
${t`Select one of the sources below to login.`}
|
||||
</p>`;
|
||||
}
|
||||
if (this.challenge?.userFields === ["email"]) {
|
||||
label = t`Email`;
|
||||
const fields = (this.challenge?.userFields || []).sort();
|
||||
// Check if the field should be *only* email to set the input type
|
||||
if (fields.includes(UserFieldsEnum.Email) && fields.length === 1) {
|
||||
type = "email";
|
||||
} else if (this.challenge?.userFields === ["username"]) {
|
||||
label = t`Username`;
|
||||
} else {
|
||||
label = t`Email or username`;
|
||||
}
|
||||
const uiFields: { [key: string]: string } = {
|
||||
[UserFieldsEnum.Username]: t`Username`,
|
||||
[UserFieldsEnum.Email]: t`Email`,
|
||||
[UserFieldsEnum.Upn]: t`UPN`,
|
||||
};
|
||||
const label = OR_LIST_FORMATTERS.format(fields.map(f => uiFields[f]));
|
||||
return html`<ak-form-element
|
||||
label=${label}
|
||||
?required="${true}"
|
||||
@ -165,7 +168,7 @@ export class IdentificationStage extends BaseStage<IdentificationChallenge, Iden
|
||||
<!-- @ts-ignore -->
|
||||
<input type=${type}
|
||||
name="uidField"
|
||||
placeholder="Email or Username"
|
||||
placeholder=${label}
|
||||
autofocus=""
|
||||
autocomplete="username"
|
||||
class="pf-c-form-control"
|
||||
|
7
web/src/global.d.ts
vendored
7
web/src/global.d.ts
vendored
@ -1 +1,8 @@
|
||||
declare module "*.css";
|
||||
|
||||
declare namespace Intl {
|
||||
class ListFormat {
|
||||
constructor(locale: string, args: { [key: string]: string });
|
||||
public format: (items: string[]) => string;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,102 @@
|
||||
import "../elements/messages/MessageContainer";
|
||||
import { customElement, html, TemplateResult } from "lit-element";
|
||||
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
|
||||
import { me } from "../api/Users";
|
||||
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "../elements/router/Route";
|
||||
import { Interface } from "./Interface";
|
||||
import "./locale";
|
||||
import "../elements/sidebar/SidebarItem";
|
||||
import { t } from "@lingui/macro";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
|
||||
|
||||
import "../elements/router/RouterOutlet";
|
||||
import "../elements/messages/MessageContainer";
|
||||
import "../elements/notifications/NotificationDrawer";
|
||||
import "../elements/sidebar/Sidebar";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { EVENT_NOTIFICATION_TOGGLE, EVENT_SIDEBAR_TOGGLE, VERSION } from "../constants";
|
||||
import { AdminApi } from "authentik-api";
|
||||
import { DEFAULT_CONFIG } from "../api/Config";
|
||||
|
||||
|
||||
@customElement("ak-interface-admin")
|
||||
export class AdminInterface extends Interface {
|
||||
export class AdminInterface extends LitElement {
|
||||
|
||||
@property({type: Boolean})
|
||||
sidebarOpen = true;
|
||||
|
||||
@property({type: Boolean})
|
||||
notificationOpen = false;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFPage, PFButton, PFDrawer, css`
|
||||
.pf-c-page__main, .pf-c-drawer__content, .pf-c-page__drawer {
|
||||
z-index: auto !important;
|
||||
}
|
||||
`];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.sidebarOpen = window.innerWidth >= 1280;
|
||||
window.addEventListener("resize", () => {
|
||||
this.sidebarOpen = window.innerWidth >= 1280;
|
||||
});
|
||||
window.addEventListener(EVENT_SIDEBAR_TOGGLE, () => {
|
||||
this.sidebarOpen = !this.sidebarOpen;
|
||||
});
|
||||
window.addEventListener(EVENT_NOTIFICATION_TOGGLE, () => {
|
||||
this.notificationOpen = !this.notificationOpen;
|
||||
});
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`
|
||||
<div class="pf-c-page">
|
||||
<ak-sidebar class="pf-c-page__sidebar ${this.sidebarOpen ? "pf-m-expanded" : "pf-m-collapsed"}">
|
||||
${this.renderSidebarItems()}
|
||||
</ak-sidebar>
|
||||
<div class="pf-c-page__drawer">
|
||||
<div class="pf-c-drawer ${this.notificationOpen ? "pf-m-expanded" : "pf-m-collapsed"}">
|
||||
<div class="pf-c-drawer__main">
|
||||
<div class="pf-c-drawer__content">
|
||||
<div class="pf-c-drawer__body">
|
||||
<main class="pf-c-page__main">
|
||||
<ak-router-outlet role="main" class="pf-c-page__main" tabindex="-1" id="main-content" defaultUrl="/library">
|
||||
</ak-router-outlet>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<ak-notification-drawer class="pf-c-drawer__panel pf-m-width-33">
|
||||
</ak-notification-drawer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
renderSidebarItems(): TemplateResult {
|
||||
const superUserCondition = () => {
|
||||
return me().then(u => u.user.isSuperuser || false);
|
||||
};
|
||||
return html`
|
||||
${until(new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve().then(version => {
|
||||
if (version.versionCurrent !== VERSION) {
|
||||
return html`<ak-sidebar-item ?highlight=${true}>
|
||||
<span slot="label">${t`A newer version of the frontend is available.`}</span>
|
||||
</ak-sidebar-item>`;
|
||||
}
|
||||
return html``;
|
||||
}))}
|
||||
${until(me().then((u) => {
|
||||
if (u.original) {
|
||||
return html`<ak-sidebar-item ?highlight=${true} ?isAbsoluteLink=${true} path=${`/-/impersonation/end/?back=${window.location.pathname}%23${window.location.hash}`}>
|
||||
<span slot="label">${t`You're currently impersonating ${u.user.username}. Click to stop.`}</span>
|
||||
</ak-sidebar-item>`;
|
||||
}
|
||||
return html``;
|
||||
}))}
|
||||
<ak-sidebar-item path="/library">
|
||||
<span slot="label">${t`Library`}</span>
|
||||
</ak-sidebar-item>
|
||||
|
@ -1,99 +0,0 @@
|
||||
import { css, CSSResult, html, LitElement, property, TemplateResult } from "lit-element";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
|
||||
|
||||
import "../elements/router/RouterOutlet";
|
||||
import "../elements/messages/MessageContainer";
|
||||
import "../elements/notifications/NotificationDrawer";
|
||||
import "../elements/Banner";
|
||||
import "../elements/sidebar/Sidebar";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { me } from "../api/Users";
|
||||
import { t } from "@lingui/macro";
|
||||
import { EVENT_NOTIFICATION_TOGGLE, EVENT_SIDEBAR_TOGGLE, VERSION } from "../constants";
|
||||
import { AdminApi } from "authentik-api";
|
||||
import { DEFAULT_CONFIG } from "../api/Config";
|
||||
|
||||
export abstract class Interface extends LitElement {
|
||||
@property({type: Boolean})
|
||||
sidebarOpen = true;
|
||||
|
||||
@property({type: Boolean})
|
||||
notificationOpen = false;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFPage, PFButton, PFDrawer, css`
|
||||
.pf-c-page__main, .pf-c-drawer__content, .pf-c-page__drawer {
|
||||
z-index: auto !important;
|
||||
}
|
||||
`];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.sidebarOpen = window.innerWidth >= 1280;
|
||||
window.addEventListener("resize", () => {
|
||||
this.sidebarOpen = window.innerWidth >= 1280;
|
||||
});
|
||||
window.addEventListener(EVENT_SIDEBAR_TOGGLE, () => {
|
||||
this.sidebarOpen = !this.sidebarOpen;
|
||||
});
|
||||
window.addEventListener(EVENT_NOTIFICATION_TOGGLE, () => {
|
||||
this.notificationOpen = !this.notificationOpen;
|
||||
});
|
||||
}
|
||||
|
||||
renderSidebarItems(): TemplateResult {
|
||||
return html``;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`
|
||||
${until(new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve().then(version => {
|
||||
if (version.versionCurrent !== VERSION) {
|
||||
return html`<ak-banner>
|
||||
${t`A newer version of the frontend is available.`}
|
||||
<button @click=${() => { window.location.reload(true); }}>
|
||||
${t`Reload`}
|
||||
</button>
|
||||
</ak-banner>`;
|
||||
}
|
||||
return html``;
|
||||
}))}
|
||||
${until(me().then((u) => {
|
||||
if (u.original) {
|
||||
return html`<ak-banner>
|
||||
${t`You're currently impersonating ${u.user.username}.`}
|
||||
<a href=${`/-/impersonation/end/?back=${window.location.pathname}%23${window.location.hash}`}>
|
||||
${t`Stop impersonation`}
|
||||
</a>
|
||||
</ak-banner>`;
|
||||
}
|
||||
return html``;
|
||||
}))}
|
||||
<div class="pf-c-page">
|
||||
<ak-sidebar class="pf-c-page__sidebar ${this.sidebarOpen ? "pf-m-expanded" : "pf-m-collapsed"}">
|
||||
${this.renderSidebarItems()}
|
||||
</ak-sidebar>
|
||||
<div class="pf-c-page__drawer">
|
||||
<div class="pf-c-drawer ${this.notificationOpen ? "pf-m-expanded" : "pf-m-collapsed"}">
|
||||
<div class="pf-c-drawer__main">
|
||||
<div class="pf-c-drawer__content">
|
||||
<div class="pf-c-drawer__body">
|
||||
<main class="pf-c-page__main">
|
||||
<ak-router-outlet role="main" class="pf-c-page__main" tabindex="-1" id="main-content" defaultUrl="/library">
|
||||
</ak-router-outlet>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<ak-notification-drawer class="pf-c-drawer__panel pf-m-width-33">
|
||||
</ak-notification-drawer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
}
|
@ -32,7 +32,7 @@ msgstr "6 digits, widely compatible"
|
||||
msgid "8 digits, not compatible with apps like Google Authenticator"
|
||||
msgstr "8 digits, not compatible with apps like Google Authenticator"
|
||||
|
||||
#: src/interfaces/Interface.ts
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
msgid "A newer version of the frontend is available."
|
||||
msgstr "A newer version of the frontend is available."
|
||||
|
||||
@ -674,11 +674,14 @@ msgstr "Configuration"
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
#: src/pages/stages/password/PasswordStageForm.ts
|
||||
msgid "Configuration flow"
|
||||
msgstr "Configuration flow"
|
||||
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
msgid "Configuration stage"
|
||||
msgstr "Configuration stage"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts
|
||||
msgid "Configure WebAuthn"
|
||||
msgstr "Configure WebAuthn"
|
||||
@ -1283,10 +1286,6 @@ msgstr "Email address"
|
||||
msgid "Email info:"
|
||||
msgstr "Email info:"
|
||||
|
||||
#: src/flows/stages/identification/IdentificationStage.ts
|
||||
msgid "Email or username"
|
||||
msgstr "Email or username"
|
||||
|
||||
#: src/pages/stages/prompt/PromptForm.ts
|
||||
msgid "Email: Text field with Email type."
|
||||
msgstr "Email: Text field with Email type."
|
||||
@ -1392,6 +1391,7 @@ msgstr "Event {0}"
|
||||
msgid "Events"
|
||||
msgstr "Events"
|
||||
|
||||
#: src/pages/events/EventInfo.ts
|
||||
#: src/pages/events/EventInfo.ts
|
||||
#: src/pages/events/EventInfo.ts
|
||||
msgid "Exception"
|
||||
@ -2498,6 +2498,10 @@ msgstr "Only send notification once, for example when sending a webhook into a c
|
||||
msgid "Open application"
|
||||
msgstr "Open application"
|
||||
|
||||
#: src/pages/events/EventInfo.ts
|
||||
msgid "Open issue on GitHub..."
|
||||
msgstr "Open issue on GitHub..."
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr "OpenID Configuration Issuer"
|
||||
@ -2928,10 +2932,6 @@ msgstr "Regular expressions for which authentication is not required. Each new l
|
||||
msgid "Related"
|
||||
msgstr "Related"
|
||||
|
||||
#: src/interfaces/Interface.ts
|
||||
msgid "Reload"
|
||||
msgstr "Reload"
|
||||
|
||||
#: src/pages/stages/user_logout/UserLogoutStageForm.ts
|
||||
msgid "Remove the user from the current session."
|
||||
msgstr "Remove the user from the current session."
|
||||
@ -3409,10 +3409,6 @@ msgstr "Status: Disabled"
|
||||
msgid "Status: Enabled"
|
||||
msgstr "Status: Enabled"
|
||||
|
||||
#: src/interfaces/Interface.ts
|
||||
msgid "Stop impersonation"
|
||||
msgstr "Stop impersonation"
|
||||
|
||||
#: src/pages/events/EventInfo.ts
|
||||
#: src/pages/stages/email/EmailStageForm.ts
|
||||
msgid "Subject"
|
||||
@ -3772,6 +3768,7 @@ msgstr "Task finished with warnings"
|
||||
msgid "Template"
|
||||
msgstr "Template"
|
||||
|
||||
#: src/pages/events/EventListPage.ts
|
||||
#: src/pages/tenants/TenantListPage.ts
|
||||
msgid "Tenant"
|
||||
msgstr "Tenant"
|
||||
@ -3981,6 +3978,11 @@ msgstr "UI settings"
|
||||
msgid "UID"
|
||||
msgstr "UID"
|
||||
|
||||
#: src/flows/stages/identification/IdentificationStage.ts
|
||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||
msgid "UPN"
|
||||
msgstr "UPN"
|
||||
|
||||
#: src/pages/sources/oauth/OAuthSourceForm.ts
|
||||
msgid "URL settings"
|
||||
msgstr "URL settings"
|
||||
@ -4517,9 +4519,9 @@ msgstr "Yes"
|
||||
msgid "You can only select providers that match the type of the outpost."
|
||||
msgstr "You can only select providers that match the type of the outpost."
|
||||
|
||||
#: src/interfaces/Interface.ts
|
||||
msgid "You're currently impersonating {0}."
|
||||
msgstr "You're currently impersonating {0}."
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
msgid "You're currently impersonating {0}. Click to stop."
|
||||
msgstr "You're currently impersonating {0}. Click to stop."
|
||||
|
||||
#: src/pages/stages/password/PasswordStageForm.ts
|
||||
msgid "authentik Builtin Database"
|
||||
@ -4529,6 +4531,10 @@ msgstr "authentik Builtin Database"
|
||||
msgid "authentik LDAP Backend"
|
||||
msgstr "authentik LDAP Backend"
|
||||
|
||||
#: src/elements/forms/DeleteForm.ts
|
||||
msgid "connecting object will be deleted"
|
||||
msgstr "connecting object will be deleted"
|
||||
|
||||
#: src/elements/Tabs.ts
|
||||
msgid "no tabs defined"
|
||||
msgstr "no tabs defined"
|
||||
|
@ -669,10 +669,13 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Configuration flow"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Configuration stage"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Configure WebAuthn"
|
||||
msgstr ""
|
||||
@ -1275,10 +1278,6 @@ msgstr ""
|
||||
msgid "Email info:"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Email or username"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Email: Text field with Email type."
|
||||
msgstr ""
|
||||
@ -1384,6 +1383,7 @@ msgstr ""
|
||||
msgid "Events"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Exception"
|
||||
@ -2490,6 +2490,10 @@ msgstr ""
|
||||
msgid "Open application"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Open issue on GitHub..."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr ""
|
||||
@ -2920,10 +2924,6 @@ msgstr ""
|
||||
msgid "Related"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Reload"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Remove the user from the current session."
|
||||
msgstr ""
|
||||
@ -3401,10 +3401,6 @@ msgstr ""
|
||||
msgid "Status: Enabled"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Stop impersonation"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
msgid "Subject"
|
||||
@ -3764,6 +3760,7 @@ msgstr ""
|
||||
msgid "Template"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
msgid "Tenant"
|
||||
msgstr ""
|
||||
@ -3969,6 +3966,11 @@ msgstr ""
|
||||
msgid "UID"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
msgid "UPN"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "URL settings"
|
||||
msgstr ""
|
||||
@ -4504,7 +4506,7 @@ msgid "You can only select providers that match the type of the outpost."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "You're currently impersonating {0}."
|
||||
msgid "You're currently impersonating {0}. Click to stop."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
@ -4515,6 +4517,10 @@ msgstr ""
|
||||
msgid "authentik LDAP Backend"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "connecting object will be deleted"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "no tabs defined"
|
||||
msgstr ""
|
||||
|
@ -34,7 +34,7 @@ export class UserCountStatusChart extends AKChart<UserMetrics> {
|
||||
pageSize: 1
|
||||
})).pagination.count;
|
||||
const superusers = (await api.coreUsersList({
|
||||
isSuperuser: "true"
|
||||
isSuperuser: true
|
||||
})).pagination.count;
|
||||
this.centerText = count.toString();
|
||||
return {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Application, CoreApi, CheckAccessRequestRequest, PolicyTestResult } from "authentik-api";
|
||||
import { Application, CoreApi, PolicyTestResult } from "authentik-api";
|
||||
import { t } from "@lingui/macro";
|
||||
import { customElement, property } from "lit-element";
|
||||
import { html, TemplateResult } from "lit-html";
|
||||
@ -8,7 +8,7 @@ import { until } from "lit-html/directives/until";
|
||||
import "../../elements/forms/HorizontalFormElement";
|
||||
|
||||
@customElement("ak-application-check-access-form")
|
||||
export class ApplicationCheckAccessForm extends Form<CheckAccessRequestRequest> {
|
||||
export class ApplicationCheckAccessForm extends Form<number> {
|
||||
|
||||
@property({attribute: false})
|
||||
application!: Application;
|
||||
@ -17,17 +17,17 @@ export class ApplicationCheckAccessForm extends Form<CheckAccessRequestRequest>
|
||||
result?: PolicyTestResult;
|
||||
|
||||
@property({ attribute: false})
|
||||
request?: CheckAccessRequestRequest;
|
||||
request?: number;
|
||||
|
||||
getSuccessMessage(): string {
|
||||
return t`Successfully sent test-request.`;
|
||||
}
|
||||
|
||||
send = (data: CheckAccessRequestRequest): Promise<PolicyTestResult> => {
|
||||
send = (data: number): Promise<PolicyTestResult> => {
|
||||
this.request = data;
|
||||
return new CoreApi(DEFAULT_CONFIG).coreApplicationsCheckAccessCreate({
|
||||
return new CoreApi(DEFAULT_CONFIG).coreApplicationsCheckAccessRetrieve({
|
||||
slug: this.application?.slug,
|
||||
checkAccessRequestRequest: data,
|
||||
forUser: data,
|
||||
}).then(result => this.result = result);
|
||||
};
|
||||
|
||||
@ -68,7 +68,7 @@ export class ApplicationCheckAccessForm extends Form<CheckAccessRequestRequest>
|
||||
ordering: "username",
|
||||
}).then(users => {
|
||||
return users.results.map(user => {
|
||||
return html`<option ?selected=${user.pk.toString() === this.request?.forUser?.toString()} value=${user.pk}>${user.username}</option>`;
|
||||
return html`<option ?selected=${user.pk.toString() === this.request?.toString()} value=${user.pk}>${user.username}</option>`;
|
||||
});
|
||||
}), html`<option>${t`Loading...`}</option>`)}
|
||||
</select>
|
||||
|
@ -5,13 +5,14 @@ import { EventMatcherPolicyActionEnum, FlowsApi } from "authentik-api";
|
||||
import "../../elements/Spinner";
|
||||
import "../../elements/Expand";
|
||||
import { PFSize } from "../../elements/Spinner";
|
||||
import { EventContext, EventWithContext } from "../../api/Events";
|
||||
import { EventContext, EventModel, EventWithContext } from "../../api/Events";
|
||||
import { DEFAULT_CONFIG } from "../../api/Config";
|
||||
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
|
||||
import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import PFList from "@patternfly/patternfly/components/List/list.css";
|
||||
import { VERSION } from "../../constants";
|
||||
|
||||
@customElement("ak-event-info")
|
||||
export class EventInfo extends LitElement {
|
||||
@ -20,7 +21,7 @@ export class EventInfo extends LitElement {
|
||||
event!: EventWithContext;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFFlex, PFList, PFDescriptionList,
|
||||
return [PFBase, PFButton, PFFlex, PFList, PFDescriptionList,
|
||||
css`
|
||||
code {
|
||||
display: block;
|
||||
@ -40,7 +41,7 @@ export class EventInfo extends LitElement {
|
||||
];
|
||||
}
|
||||
|
||||
getModelInfo(context: EventContext): TemplateResult {
|
||||
getModelInfo(context: EventModel): TemplateResult {
|
||||
if (context === null) {
|
||||
return html`<span>-</span>`;
|
||||
}
|
||||
@ -50,7 +51,7 @@ export class EventInfo extends LitElement {
|
||||
<span class="pf-c-description-list__text">${t`UID`}</span>
|
||||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">${context.pk as string}</div>
|
||||
<div class="pf-c-description-list__text">${context.pk}</div>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="pf-c-description-list__group">
|
||||
@ -58,7 +59,7 @@ export class EventInfo extends LitElement {
|
||||
<span class="pf-c-description-list__text">${t`Name`}</span>
|
||||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">${context.name as string}</div>
|
||||
<div class="pf-c-description-list__text">${context.name}</div>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="pf-c-description-list__group">
|
||||
@ -66,7 +67,7 @@ export class EventInfo extends LitElement {
|
||||
<span class="pf-c-description-list__text">${t`App`}</span>
|
||||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">${context.app as string}</div>
|
||||
<div class="pf-c-description-list__text">${context.app}</div>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="pf-c-description-list__group">
|
||||
@ -74,7 +75,7 @@ export class EventInfo extends LitElement {
|
||||
<span class="pf-c-description-list__text">${t`Model Name`}</span>
|
||||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">${context.model_name as string}</div>
|
||||
<div class="pf-c-description-list__text">${context.model_name}</div>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>`;
|
||||
@ -137,6 +138,52 @@ export class EventInfo extends LitElement {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
buildGitHubIssueUrl(context: EventContext): string {
|
||||
const httpRequest = this.event.context.http_request as EventContext;
|
||||
let title = "";
|
||||
if (httpRequest) {
|
||||
title = `${httpRequest?.method} ${httpRequest?.path}`;
|
||||
}
|
||||
// https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-issues/about-automation-for-issues-and-pull-requests-with-query-parameters
|
||||
const fullBody = `
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Logs**
|
||||
<details>
|
||||
<summary>Stacktrace from authentik</summary>
|
||||
|
||||
\`\`\`
|
||||
${context.message as string}
|
||||
\`\`\`
|
||||
</details>
|
||||
|
||||
|
||||
**Version and Deployment (please complete the following information):**
|
||||
- authentik version: ${VERSION}
|
||||
- Deployment: [e.g. docker-compose, helm]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
`;
|
||||
return `https://github.com/goauthentik/authentik/issues/
|
||||
new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
|
||||
&body=${encodeURIComponent(fullBody)}`.trim();
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
if (!this.event) {
|
||||
return html`<ak-spinner size=${PFSize.Medium}></ak-spinner>`;
|
||||
@ -147,13 +194,13 @@ export class EventInfo extends LitElement {
|
||||
case EventMatcherPolicyActionEnum.ModelDeleted:
|
||||
return html`
|
||||
<h3>${t`Affected model:`}</h3>
|
||||
${this.getModelInfo(this.event.context?.model as EventContext)}
|
||||
${this.getModelInfo(this.event.context?.model as EventModel)}
|
||||
`;
|
||||
case EventMatcherPolicyActionEnum.AuthorizeApplication:
|
||||
return html`<div class="pf-l-flex">
|
||||
<div class="pf-l-flex__item">
|
||||
<h3>${t`Authorized application:`}</h3>
|
||||
${this.getModelInfo(this.event.context.authorized_application as EventContext)}
|
||||
${this.getModelInfo(this.event.context.authorized_application as EventModel)}
|
||||
</div>
|
||||
<div class="pf-l-flex__item">
|
||||
<h3>${t`Using flow`}</h3>
|
||||
@ -175,7 +222,24 @@ export class EventInfo extends LitElement {
|
||||
case EventMatcherPolicyActionEnum.SecretView:
|
||||
return html`
|
||||
<h3>${t`Secret:`}</h3>
|
||||
${this.getModelInfo(this.event.context.secret as EventContext)}`;
|
||||
${this.getModelInfo(this.event.context.secret as EventModel)}`;
|
||||
case EventMatcherPolicyActionEnum.SystemException:
|
||||
return html`
|
||||
<a
|
||||
class="pf-c-button pf-m-primary"
|
||||
target="_blank"
|
||||
href=${this.buildGitHubIssueUrl(
|
||||
this.event.context
|
||||
)}>
|
||||
${t`Open issue on GitHub...`}
|
||||
</a>
|
||||
<div class="pf-l-flex">
|
||||
<div class="pf-l-flex__item">
|
||||
<h3>${t`Exception`}</h3>
|
||||
<code>${this.event.context.message}</code>
|
||||
</div>
|
||||
</div>
|
||||
<ak-expand>${this.defaultResponse()}</ak-expand>`;
|
||||
case EventMatcherPolicyActionEnum.PropertyMappingException:
|
||||
return html`<div class="pf-l-flex">
|
||||
<div class="pf-l-flex__item">
|
||||
@ -192,12 +256,12 @@ export class EventInfo extends LitElement {
|
||||
return html`<div class="pf-l-flex">
|
||||
<div class="pf-l-flex__item">
|
||||
<h3>${t`Binding`}</h3>
|
||||
${this.getModelInfo(this.event.context.binding as EventContext)}
|
||||
${this.getModelInfo(this.event.context.binding as EventModel)}
|
||||
</div>
|
||||
<div class="pf-l-flex__item">
|
||||
<h3>${t`Request`}</h3>
|
||||
<ul class="pf-c-list">
|
||||
<li>${t`Object`}: ${this.getModelInfo((this.event.context.request as EventContext).obj as EventContext)}</li>
|
||||
<li>${t`Object`}: ${this.getModelInfo((this.event.context.request as EventContext).obj as EventModel)}</li>
|
||||
<li><span>${t`Context`}: <code>${JSON.stringify((this.event.context.request as EventContext).context, null, 4)}</code></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -211,12 +275,12 @@ export class EventInfo extends LitElement {
|
||||
return html`<div class="pf-l-flex">
|
||||
<div class="pf-l-flex__item">
|
||||
<h3>${t`Binding`}</h3>
|
||||
${this.getModelInfo(this.event.context.binding as EventContext)}
|
||||
${this.getModelInfo(this.event.context.binding as EventModel)}
|
||||
</div>
|
||||
<div class="pf-l-flex__item">
|
||||
<h3>${t`Request`}</h3>
|
||||
<ul class="pf-c-list">
|
||||
<li>${t`Object`}: ${this.getModelInfo((this.event.context.request as EventContext).obj as EventContext)}</li>
|
||||
<li>${t`Object`}: ${this.getModelInfo((this.event.context.request as EventContext).obj as EventModel)}</li>
|
||||
<li><span>${t`Context`}: <code>${JSON.stringify((this.event.context.request as EventContext).context, null, 4)}</code></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -252,7 +316,7 @@ export class EventInfo extends LitElement {
|
||||
return html`<div class="pf-l-flex">
|
||||
<div class="pf-l-flex__item">
|
||||
<h3>${t`Using source`}</h3>
|
||||
${this.getModelInfo(this.event.context.using_source as EventContext)}
|
||||
${this.getModelInfo(this.event.context.using_source as EventModel)}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ export class EventListPage extends TablePage<Event> {
|
||||
new TableColumn(t`User`, "user"),
|
||||
new TableColumn(t`Creation Date`, "created"),
|
||||
new TableColumn(t`Client IP`, "client_ip"),
|
||||
new TableColumn(t`Tenant`, "tenant_name"),
|
||||
new TableColumn(""),
|
||||
];
|
||||
}
|
||||
@ -62,6 +63,7 @@ export class EventListPage extends TablePage<Event> {
|
||||
html`-`,
|
||||
html`<span>${item.created?.toLocaleString()}</span>`,
|
||||
html`<span>${item.clientIp || "-"}</span>`,
|
||||
html`<span>${item.tenant?.name || "-"}</span>`,
|
||||
html`<a href="#/events/log/${item.pk}">
|
||||
<i class="fas fas fa-share-square"></i>
|
||||
</a>`,
|
||||
|
@ -103,7 +103,7 @@ export class FlowListPage extends TablePage<Flow> {
|
||||
}}>
|
||||
${t`Execute`}
|
||||
</button>
|
||||
<a class="pf-c-button pf-m-secondary" href=${flow.exportUrl}>
|
||||
<a class="pf-c-button pf-m-secondary" href=${item.exportUrl}>
|
||||
${t`Export`}
|
||||
</a>`,
|
||||
];
|
||||
|
@ -102,7 +102,11 @@ export class OutpostForm extends ModelForm<Outpost, string> {
|
||||
ordering: "pk"
|
||||
}).then(scs => {
|
||||
return scs.results.map(sc => {
|
||||
return html`<option value=${ifDefined(sc.pk)} ?selected=${this.instance?.serviceConnection === sc.pk}>
|
||||
let selected = this.instance?.serviceConnection === sc.pk;
|
||||
if (scs.results.length === 1 && !this.instance) {
|
||||
selected = true;
|
||||
}
|
||||
return html`<option value=${ifDefined(sc.pk)} ?selected=${selected}>
|
||||
${sc.name} (${sc.verboseName})
|
||||
</option>`;
|
||||
});
|
||||
@ -127,13 +131,16 @@ export class OutpostForm extends ModelForm<Outpost, string> {
|
||||
label=${t`Configuration`}
|
||||
name="config">
|
||||
<ak-codemirror mode="yaml" value="${until(new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesDefaultSettingsRetrieve().then(config => {
|
||||
let fc = config.config;
|
||||
if (this.instance) {
|
||||
fc = this.instance.config;
|
||||
}
|
||||
return YAML.stringify(fc);
|
||||
}))}"></ak-codemirror>
|
||||
let fc = config.config;
|
||||
if (this.instance) {
|
||||
fc = this.instance.config;
|
||||
}
|
||||
return YAML.stringify(fc);
|
||||
}))}"></ak-codemirror>
|
||||
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
|
||||
<p class="pf-c-form__helper-text">
|
||||
See <a target="_blank" href="https://goauthentik.io/docs/outposts/outposts#configuration">documentation</a>.
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</form>`;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
|
||||
<option value="" ?selected=${this.instance?.rsaKey === undefined}>---------</option>
|
||||
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
|
||||
ordering: "pk",
|
||||
hasKey: "true",
|
||||
hasKey: true,
|
||||
}).then(keys => {
|
||||
return keys.results.map(key => {
|
||||
let selected = this.instance?.rsaKey === key.pk;
|
||||
|
@ -218,7 +218,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
|
||||
<option value="" ?selected=${this.instance?.certificate === undefined}>---------</option>
|
||||
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
|
||||
ordering: "pk",
|
||||
hasKey: "true",
|
||||
hasKey: true,
|
||||
}).then(keys => {
|
||||
return keys.results.map(key => {
|
||||
return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.certificate === key.pk}>${key.name}</option>`;
|
||||
|
@ -115,7 +115,7 @@ export class SAMLProviderFormPage extends ModelForm<SAMLProvider, number> {
|
||||
<option value="" ?selected=${this.instance?.signingKp === undefined}>---------</option>
|
||||
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
|
||||
ordering: "pk",
|
||||
hasKey: "true",
|
||||
hasKey: true,
|
||||
}).then(keys => {
|
||||
return keys.results.map(key => {
|
||||
return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.signingKp === key.pk}>${key.name}</option>`;
|
||||
|
@ -163,7 +163,7 @@ export class SAMLProviderViewPage extends LitElement {
|
||||
<ak-action-button
|
||||
class="pf-m-secondary"
|
||||
.apiRequest=${() => {
|
||||
const fullUrl = window.location.origin + this.provider.metadataDownloadUrl;
|
||||
const fullUrl = window.location.origin + this.provider?.metadataDownloadUrl;
|
||||
return navigator.clipboard.writeText(fullUrl);
|
||||
}}>
|
||||
${t`Copy download URL`}
|
||||
|
@ -15,7 +15,7 @@ export class ConsentStageForm extends ModelForm<ConsentStage, string> {
|
||||
return new StagesApi(DEFAULT_CONFIG).stagesConsentRetrieve({
|
||||
stageUuid: pk,
|
||||
}).then(stage => {
|
||||
this.showExpiresIn = stage.name === ConsentStageModeEnum.Expiring;
|
||||
this.showExpiresIn = stage.mode === ConsentStageModeEnum.Expiring;
|
||||
return stage;
|
||||
});
|
||||
}
|
||||
|
@ -72,6 +72,9 @@ export class IdentificationStageForm extends ModelForm<IdentificationStage, stri
|
||||
<option value=${UserFieldsEnum.Email} ?selected=${this.isUserFieldSelected(UserFieldsEnum.Email)}>
|
||||
${t`Email`}
|
||||
</option>
|
||||
<option value=${UserFieldsEnum.Upn} ?selected=${this.isUserFieldSelected(UserFieldsEnum.Upn)}>
|
||||
${t`UPN`}
|
||||
</option>
|
||||
</select>
|
||||
<p class="pf-c-form__helper-text">${t`Fields a user can identify themselves with. If no fields are selected, the user will only be able to use sources.`}</p>
|
||||
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
|
||||
|
@ -38,19 +38,19 @@ export class UserSettingsPage extends LitElement {
|
||||
renderStageSettings(stage: UserSetting): TemplateResult {
|
||||
switch (stage.component) {
|
||||
case "ak-user-settings-authenticator-webauthn":
|
||||
return html`<ak-user-settings-authenticator-webauthn objectId=${stage.objectUid} configureUrl=${stage.configureUrl}>
|
||||
return html`<ak-user-settings-authenticator-webauthn objectId=${stage.objectUid} .configureUrl=${stage.configureUrl}>
|
||||
</ak-user-settings-authenticator-webauthn>`;
|
||||
case "ak-user-settings-password":
|
||||
return html`<ak-user-settings-password objectId=${stage.objectUid} configureUrl=${stage.configureUrl}>
|
||||
return html`<ak-user-settings-password objectId=${stage.objectUid} .configureUrl=${stage.configureUrl}>
|
||||
</ak-user-settings-password>`;
|
||||
case "ak-user-settings-authenticator-totp":
|
||||
return html`<ak-user-settings-authenticator-totp objectId=${stage.objectUid} configureUrl=${stage.configureUrl}>
|
||||
return html`<ak-user-settings-authenticator-totp objectId=${stage.objectUid} .configureUrl=${stage.configureUrl}>
|
||||
</ak-user-settings-authenticator-totp>`;
|
||||
case "ak-user-settings-authenticator-static":
|
||||
return html`<ak-user-settings-authenticator-static objectId=${stage.objectUid} configureUrl=${stage.configureUrl}>
|
||||
return html`<ak-user-settings-authenticator-static objectId=${stage.objectUid} .configureUrl=${stage.configureUrl}>
|
||||
</ak-user-settings-authenticator-static>`;
|
||||
case "ak-user-settings-authenticator-duo":
|
||||
return html`<ak-user-settings-authenticator-duo objectId=${stage.objectUid} configureUrl=${stage.configureUrl}>
|
||||
return html`<ak-user-settings-authenticator-duo objectId=${stage.objectUid} .configureUrl=${stage.configureUrl}>
|
||||
</ak-user-settings-authenticator-duo>`;
|
||||
default:
|
||||
return html`<p>${t`Error: unsupported stage settings: ${stage.component}`}</p>`;
|
||||
@ -60,7 +60,7 @@ export class UserSettingsPage extends LitElement {
|
||||
renderSourceSettings(source: UserSetting): TemplateResult {
|
||||
switch (source.component) {
|
||||
case "ak-user-settings-source-oauth":
|
||||
return html`<ak-user-settings-source-oauth objectId=${source.objectUid} title=${source.title} configureUrl=${source.configureUrl}>
|
||||
return html`<ak-user-settings-source-oauth objectId=${source.objectUid} title=${source.title} .configureUrl=${source.configureUrl}>
|
||||
</ak-user-settings-source-oauth>`;
|
||||
default:
|
||||
return html`<p>${t`Error: unsupported source settings: ${source.component}`}</p>`;
|
||||
|
@ -30,20 +30,12 @@ export class UserActiveForm extends DeleteForm {
|
||||
</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section class="pf-c-page__main-section">
|
||||
<div class="pf-l-stack">
|
||||
<div class="pf-l-stack__item">
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<form class="pf-c-form pf-m-horizontal">
|
||||
<p>
|
||||
${t`Are you sure you want to update ${this.objectLabel} "${this.obj?.name}"?`}
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section class="pf-c-page__main-section pf-m-light">
|
||||
<form class="pf-c-form pf-m-horizontal">
|
||||
<p>
|
||||
${t`Are you sure you want to update ${this.objectLabel} "${this.obj?.name}"?`}
|
||||
</p>
|
||||
</form>
|
||||
</section>
|
||||
<footer class="pf-c-modal-box__footer">
|
||||
<ak-spinner-button
|
||||
|
@ -19,10 +19,6 @@ This will send a POST request to the given URL with the following contents:
|
||||
|
||||
The `Content-Type` header is set to `text/json`.
|
||||
|
||||
:::warning
|
||||
This will send a request for each user of the group selected in the trigger.
|
||||
:::
|
||||
|
||||
## Slack Webhook
|
||||
|
||||
This sends a request using the Slack-specific format. This is also compatible with Discord's webhooks by appending `/slack` to the Discord webhook URL.
|
||||
|
@ -5,3 +5,7 @@ title: WebAuthn authenticator setup stage
|
||||
This stage configures a WebAuthn-based Authenticator. This can either be a browser, biometrics or a Security stick like a YubiKey.
|
||||
|
||||
There are no stage-specific settings.
|
||||
|
||||
:::warning
|
||||
Currently, the WebAuthn stage does NOT support Apple FaceID and Android Fingerprint/SafetyNet.
|
||||
:::
|
||||
|
@ -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-rc2/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.1-rc6/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-rc2 >> .env`
|
||||
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.6.1-rc6 >> .env`
|
||||
|
||||
If this is a fresh authentik install run the following commands to generate a password:
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user