Compare commits

..

83 Commits

Author SHA1 Message Date
276d8fe5cf release: 2021.8.4 2021-09-02 20:21:21 +02:00
92ce5f0931 web: improve error display when only {'detail'} is returned
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 19:55:37 +02:00
7fea20375f *: fix tests not using APITestCase
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 19:14:21 +02:00
d4d4034d2c web: Update Web API Client version (#1336)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-02 17:42:55 +02:00
f0db408699 api: add v3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 17:40:02 +02:00
5e200655d9 web: Update Web API Client version (#1335)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-02 17:13:16 +02:00
d5d1f2a645 web: show version in logs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 17:10:43 +02:00
cc5cc43baa api: fix sentry endpoint not working due to mime-media
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 16:56:53 +02:00
e512f085db root: allow enabling s3 backup ssl verification
closes #1332

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 09:41:55 +02:00
f323c01bd8 build(deps): bump django from 3.2.6 to 3.2.7 (#1333) 2021-09-02 09:12:24 +02:00
f56cacb406 build(deps): bump boto3 from 1.18.33 to 1.18.34 (#1334) 2021-09-02 09:12:03 +02:00
eaecd31e9f ci: always run codecov and testspace
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 22:59:51 +02:00
36989d82e1 ci: merge on testspace
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 22:35:17 +02:00
50777d9022 ci: re-add testspace (#1331)
* ci: re-add testspace

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* ci: fix double k3d

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 22:33:10 +02:00
a15571bd3e outposts/proxy: detect empty authentik_host
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 22:09:07 +02:00
26fd66d831 stages/authenticator_validate: fix variable shadowing, optimization
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:54:54 +02:00
0be873025a ci: fix bumpversion path
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:38:04 +02:00
28ada49910 website/docs: final 2021.8.4 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:37:00 +02:00
4fc8e61f8c stages/authenticator_validate: show single button for multiple webauthn authenticators
tested with browser + yubikey 5

closes #1096

The order of allowCredentials doesn't seem to matter, chrome seems to always choose the internal authenticator first.

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:28:52 +02:00
7d26ea1a9c web/admin: fix list of webauthn devices not updating after rename
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:05:18 +02:00
3a58dc62e1 ci: fix missing branch
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 18:34:57 +02:00
71fe7bc827 ci: fix sha being used instead of timestamp
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 17:10:42 +02:00
933336c38b ci: fix images not being pushed with correct tags
* ci: debug

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* ci: fix branch and sha

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 16:19:29 +02:00
371feb9a31 ci: fix images not being pushed
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 15:07:13 +02:00
95a2fd3c9e web: Update Web API Client version (#1327)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-01 14:48:48 +02:00
17cb76c334 stages/invitation: fix invitation not inheriting ExpiringModel
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 14:25:19 +02:00
88f0dfc8cc web/admin: fallback for invitation list on first load
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 13:33:05 +02:00
f82aada23b web/admin: fix flow executor not opening in new tab
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 13:19:09 +02:00
ecaee92634 build(deps): bump @sentry/tracing from 6.11.0 to 6.12.0 in /web (#1322)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.11.0 to 6.12.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.11.0...6.12.0)

---
updated-dependencies:
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-01 09:26:53 +02:00
89252ec47b build(deps): bump @sentry/tracing from 6.11.0 to 6.12.0 in /website (#1320)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.11.0 to 6.12.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.11.0...6.12.0)

---
updated-dependencies:
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-01 09:26:33 +02:00
f0f25ab291 build(deps): bump @sentry/react from 6.11.0 to 6.12.0 in /website (#1321) 2021-09-01 08:40:07 +02:00
e4d0fec15a build(deps): bump @sentry/browser from 6.11.0 to 6.12.0 in /web (#1323) 2021-09-01 08:39:56 +02:00
6b10baf086 build(deps): bump docker from 5.0.0 to 5.0.1 (#1324) 2021-09-01 08:39:21 +02:00
f148b5d341 build(deps): bump boto3 from 1.18.32 to 1.18.33 (#1326) 2021-09-01 08:39:12 +02:00
1471ff8940 build(deps): bump drf-spectacular from 0.18.0 to 0.18.1 (#1325) 2021-09-01 08:39:01 +02:00
d9a6ec2ac0 webiste/docs: update extensionvs/v1beta ingress
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-31 21:11:01 +02:00
5745ffa0a8 ci: don't login to docker on forks
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-31 09:31:10 +02:00
b26202db35 build(deps): bump @typescript-eslint/parser in /web (#1316) 2021-08-31 08:42:14 +02:00
6318577a51 build(deps): bump @typescript-eslint/eslint-plugin in /web (#1317) 2021-08-31 08:16:59 +02:00
6a2cd45847 build(deps-dev): bump pytest from 6.2.4 to 6.2.5 (#1318) 2021-08-31 08:16:44 +02:00
ef5cea2c01 build(deps): bump boto3 from 1.18.31 to 1.18.32 (#1319) 2021-08-31 08:16:32 +02:00
69f4d54bae ci: migrate ci to gh actions (#1315) 2021-08-30 20:21:15 +02:00
b1eec5a7d2 outposts/proxy: add more logging
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 17:18:52 +02:00
1b8271d767 flows: disable compatibility_mode by default
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 17:18:43 +02:00
3e9f5ec5ef providers/proxy: improve error handling for non-tls ingresses
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 14:43:57 +02:00
63f57b6a77 events: improve logging for task exceptions
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 14:43:44 +02:00
a016f99450 core: fix user_obj being empty on token API
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 12:51:17 +02:00
adc18b2991 build(deps): bump boto3 from 1.18.30 to 1.18.31 (#1314)
Bumps [boto3](https://github.com/boto/boto3) from 1.18.30 to 1.18.31.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.18.30...1.18.31)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-30 09:12:58 +02:00
e37a326b95 website/docs: prepare 8.4 docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 22:12:49 +02:00
048467e97d outpost/ldap: delay user information removal upon closing of connection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 21:13:46 +02:00
cc2cd6919f outpost/embedded: only send requests for non-akprox paths when we're doing proxy mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 21:13:28 +02:00
0c6e781e5b providers/proxy: fix traefik middleware being generated with wrong ports for embedded outposts
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 20:49:11 +02:00
7294d8fca5 website/docs: add note for cross-namespace reference in traefik
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 20:46:17 +02:00
16ec5680b4 web: Update Web API Client version (#1313)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-08-29 19:51:10 +02:00
87920fb1d7 website/docs: add docs for websocket connections
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 19:49:18 +02:00
523b96a6d2 api: add basic rate limiting for sentry endpoint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 19:33:18 +02:00
45731d8069 cmd: add option to disable embedded outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 19:19:13 +02:00
e872371970 website/docs: add embedded outpost docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 14:43:13 +02:00
08e8cf850a web/flows: fix FlowExecutor not updating when challenge changes from outside
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 13:49:57 +02:00
b1ed2154ac policies/password: fix PasswordStage not being usable with prompt stages, rework validation logic
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 00:40:36 +02:00
7ef2aa3eb9 web: Update Web API Client version (#1312) 2021-08-28 19:08:38 +02:00
160139813d release: 2021.8.3 2021-08-28 16:58:44 +02:00
582ad92c76 outposts/k8s: improve error handling
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-28 14:58:26 +02:00
f61736e3d1 stages/identification: add error handling when password isn't set
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-28 12:54:10 +02:00
eb02c96281 website/docs: make it clearer to use context[]
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-28 12:53:57 +02:00
8619552920 website/docs: prepare 2021.8.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 23:12:53 +02:00
6237352e25 web/flows: fix checkboxes not being rendered correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 23:09:53 +02:00
2d8b4f543b providers/proxy: fix url parsing for traefik labels on docker containers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 22:21:16 +02:00
8542dc10ab providers/proxy: fix docker container labels not being inherited correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 20:20:34 +02:00
c55b63337c web/flows: fix post-challenge updates not always being called by using setter
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 19:45:23 +02:00
12ddee3bb6 outpost: add additional labels to docker container
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 19:26:27 +02:00
dc41d0af27 outposts: add configurable docker_network for outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 19:26:11 +02:00
3323b50036 web/flows: also check for redirects as result of posting challenge
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 10:08:15 +02:00
8acb15a7fd outpost: fix flow executor not sending password for identification stage
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 09:43:07 +02:00
f601e04b38 web/flows: assign location from redirect challenge in request handler not render
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 09:43:00 +02:00
f50529cb5b build(deps): bump @docusaurus/preset-classic in /website (#1307)
Bumps [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) from 2.0.0-beta.4 to 2.0.0-beta.5.
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v2.0.0-beta.5/packages/docusaurus-preset-classic)

---
updated-dependencies:
- dependency-name: "@docusaurus/preset-classic"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-27 09:20:09 +02:00
3f1b6f9ed4 build(deps): bump typescript from 4.3.5 to 4.4.2 in /web (#1306) 2021-08-27 08:36:43 +02:00
f1ab0f4314 build(deps): bump @patternfly/patternfly from 4.125.3 to 4.132.2 in /web (#1308) 2021-08-27 08:36:34 +02:00
4d1129f385 build(deps): bump boto3 from 1.18.29 to 1.18.30 (#1310) 2021-08-27 08:36:19 +02:00
03ac9c6e16 build(deps): bump @docusaurus/plugin-client-redirects in /website (#1309) 2021-08-27 08:36:11 +02:00
c0839924f1 build(deps): bump github.com/go-openapi/runtime from 0.19.30 to 0.19.31 (#1311) 2021-08-27 08:35:57 +02:00
91e3aa760a web: Update Web API Client version (#1305)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-08-26 19:06:13 +02:00
5c0681d57b website/docs: add 2021.8.2 docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-26 18:56:42 +02:00
119 changed files with 2412 additions and 3951 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2021.8.2
current_version = 2021.8.4
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
@ -23,7 +23,7 @@ values =
[bumpversion:file:schema.yml]
[bumpversion:file:.github/workflows/release.yml]
[bumpversion:file:.github/workflows/release-publish.yml]
[bumpversion:file:authentik/__init__.py]

240
.github/workflows/ci-main.yml vendored Normal file
View File

@ -0,0 +1,240 @@
name: authentik-ci-main
on:
push:
paths-ignore:
- website
env:
POSTGRES_DB: authentik
POSTGRES_USER: authentik
POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77"
jobs:
lint-pylint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: prepare
run: scripts/ci_prepare.sh
- name: run pylint
run: pipenv run pylint authentik tests lifecycle
lint-black:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: prepare
run: scripts/ci_prepare.sh
- name: run black
run: pipenv run black --check authentik tests lifecycle
lint-isort:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: prepare
run: scripts/ci_prepare.sh
- name: run isort
run: pipenv run isort --check authentik tests lifecycle
lint-bandit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: prepare
run: scripts/ci_prepare.sh
- name: run bandit
run: pipenv run bandit -r authentik tests lifecycle
lint-pyright:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- uses: actions/setup-node@v2
with:
node-version: '16'
- name: prepare
run: |
scripts/ci_prepare.sh
npm install -g pyright@1.1.136
- name: run bandit
run: pipenv run pyright e2e lifecycle
test-migrations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: prepare
run: scripts/ci_prepare.sh
- name: run migrations
run: pipenv run python -m lifecycle.migrate
test-migrations-from-stable:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: checkout stable
run: |
# Copy current, latest config to local
cp authentik/lib/default.yml local.env.yml
git checkout $(git describe --abbrev=0 --match 'version/*')
- name: prepare
run: scripts/ci_prepare.sh
- name: run migrations to stable
run: pipenv run python -m lifecycle.migrate
- name: checkout current code
run: |
set -x
git checkout $GITHUB_REF
pipenv sync --dev
- name: migrate to latest
run: pipenv run python -m lifecycle.migrate
test-unittest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: prepare
run: scripts/ci_prepare.sh
- uses: testspace-com/setup-testspace@v1
with:
domain: ${{github.repository_owner}}
- name: run unittest
run: |
pipenv run make test
pipenv run coverage xml
- name: run testspace
if: ${{ always() }}
run: |
testspace unittest.xml ?add
- if: ${{ always() }}
uses: codecov/codecov-action@v2
test-integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: prepare
run: scripts/ci_prepare.sh
- uses: testspace-com/setup-testspace@v1
with:
domain: ${{github.repository_owner}}
- name: prepare k3d
run: |
wget -q -O - https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash
- name: run integration
run: |
pipenv run make test-integration
pipenv run coverage xml
- name: run testspace
if: ${{ always() }}
run: |
testspace unittest.xml ?add
- if: ${{ always() }}
uses: codecov/codecov-action@v2
test-e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- uses: testspace-com/setup-testspace@v1
with:
domain: ${{github.repository_owner}}
- name: prepare
run: |
scripts/ci_prepare.sh
docker-compose -f tests/e2e/ci.docker-compose.yml up -d
- name: prepare web ui
run: |
cd web
npm i
npm run build
- name: run e2e
run: |
pipenv run make test-e2e
pipenv run coverage xml
- name: run testspace
if: ${{ always() }}
run: |
testspace unittest.xml ?add
- if: ${{ always() }}
uses: codecov/codecov-action@v2
report:
if: ${{ always() }}
needs:
- test-unittest
- test-integration
- test-e2e
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: testspace-com/setup-testspace@v1
with:
domain: ${{github.repository_owner}}
- name: finish testspace
run: |
testspace ?finish
build:
needs:
- lint-pylint
- lint-black
- lint-isort
- lint-bandit
- lint-pyright
- test-migrations
- test-migrations-from-stable
- test-unittest
- test-integration
- test-e2e
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: prepare variables
id: ev
run: |
python ./scripts/gh_do_set_branch.py
- name: Login to Container Registry
uses: docker/login-action@v1
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
with:
registry: beryju.org
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASSWORD }}
- name: Building Docker Image
uses: docker/build-push-action@v2
with:
push: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
tags: |
beryju.org/authentik/server:gh-${{ steps.ev.outputs.branchName }}
beryju.org/authentik/server:gh-${{ steps.ev.outputs.branchName }}-${{ steps.ev.outputs.timestamp }}
build-args: |
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}

66
.github/workflows/ci-outpost.yml vendored Normal file
View File

@ -0,0 +1,66 @@
name: authentik-ci-outpost
on:
push:
jobs:
lint-golint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '^1.16.3'
- name: Generate API
run: |
make gen-outpost
- name: Run linter
run: |
# Create folder structure for go embeds
mkdir -p web/dist
mkdir -p website/help
touch web/dist/test website/help/test
docker run \
--rm \
-v $(pwd):/app \
-w /app \
golangci/golangci-lint:v1.39.0 \
golangci-lint run -v --timeout 200s
build:
needs:
- lint-golint
strategy:
matrix:
type:
- proxy
- ldap
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: prepare variables
id: ev
run: |
python ./scripts/gh_do_set_branch.py
- name: Login to Container Registry
uses: docker/login-action@v1
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
with:
registry: beryju.org
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASSWORD }}
- name: Building Docker Image
uses: docker/build-push-action@v2
with:
push: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
tags: |
beryju.org/authentik/outpost-${{ matrix.type }}:gh-${{ steps.ev.outputs.branchName }}
beryju.org/authentik/outpost-${{ matrix.type }}:gh-${{ steps.ev.outputs.branchName }}-${{ steps.ev.outputs.timestamp }}
beryju.org/authentik/outpost-${{ matrix.type }}:gh-${{ steps.ev.outputs.sha }}
file: ${{ matrix.type }}.Dockerfile
platforms: linux/amd64,linux/arm64
build-args: |
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}

82
.github/workflows/ci-web.yml vendored Normal file
View File

@ -0,0 +1,82 @@
name: authentik-ci-web
on:
push:
jobs:
lint-eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: |
cd web
npm install
- name: Generate API
run: make gen-web
- name: Eslint
run: |
cd web
npm run lint
lint-prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: |
cd web
npm install
- name: Generate API
run: make gen-web
- name: prettier
run: |
cd web
npm run prettier-check
lint-lit-analyse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: |
cd web
npm install
- name: Generate API
run: make gen-web
- name: prettier
run: |
cd web
npm run lit-analyse
build:
needs:
- lint-eslint
- lint-prettier
- lint-lit-analyse
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: |
cd web
npm install
- name: Generate API
run: make gen-web
- name: build
run: |
cd web
npm run build

View File

@ -33,14 +33,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik:2021.8.2,
beryju/authentik:2021.8.4,
beryju/authentik:latest,
ghcr.io/goauthentik/server:2021.8.2,
ghcr.io/goauthentik/server:2021.8.4,
ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64
context: .
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.8.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.8.4', 'rc') }}
run: |
docker pull beryju/authentik:latest
docker tag beryju/authentik:latest beryju/authentik:stable
@ -75,14 +75,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-proxy:2021.8.2,
beryju/authentik-proxy:2021.8.4,
beryju/authentik-proxy:latest,
ghcr.io/goauthentik/proxy:2021.8.2,
ghcr.io/goauthentik/proxy:2021.8.4,
ghcr.io/goauthentik/proxy:latest
file: proxy.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.8.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.8.4', 'rc') }}
run: |
docker pull beryju/authentik-proxy:latest
docker tag beryju/authentik-proxy:latest beryju/authentik-proxy:stable
@ -117,14 +117,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-ldap:2021.8.2,
beryju/authentik-ldap:2021.8.4,
beryju/authentik-ldap:latest,
ghcr.io/goauthentik/ldap:2021.8.2,
ghcr.io/goauthentik/ldap:2021.8.4,
ghcr.io/goauthentik/ldap:latest
file: ldap.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.8.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.8.4', 'rc') }}
run: |
docker pull beryju/authentik-ldap:latest
docker tag beryju/authentik-ldap:latest beryju/authentik-ldap:stable
@ -175,7 +175,7 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
version: authentik@2021.8.2
version: authentik@2021.8.4
environment: beryjuorg-prod
sourcemaps: './web/dist'
url_prefix: '~/static/dist'

154
Pipfile.lock generated
View File

@ -122,19 +122,19 @@
},
"boto3": {
"hashes": [
"sha256:4dc7e346e92c01e8a997daa58a4c990151841d2d2962067325d963f665c7287a",
"sha256:79b7e6e0167def749352968ed6eb96954d9e2dd1dca8f297f122414753ce73a3"
"sha256:5116e9bdec19adcc5531a9b7b535be77d5314eef092aaf7033ace48a9be65036",
"sha256:658ddf4ba552f654fd4d48335fa95ff4e3e1a4e82f90021a1a1d3de4a5428ba4"
],
"index": "pypi",
"version": "==1.18.29"
"version": "==1.18.34"
},
"botocore": {
"hashes": [
"sha256:1f16998b4f5a88e6844196feee7fa5eef6b36034d377f9845c7df12b8803b3be",
"sha256:fec924f63b40bd29b522fa109ecbc45f16eedcbeb22b68c6c79773c22a552b16"
"sha256:1b4999fb0e1a4c050c4d9118ebdaac8d83761ef32c3c0f13a25f9204045998fe",
"sha256:ec2cdf1c8ed64a7f392f352125d248c76103fa9d137b275b7c76836776cedf56"
],
"markers": "python_version >= '3.6'",
"version": "==1.21.29"
"version": "==1.21.34"
},
"cachetools": {
"hashes": [
@ -359,11 +359,11 @@
},
"django": {
"hashes": [
"sha256:7f92413529aa0e291f3be78ab19be31aefb1e1c9a52cd59e130f505f27a51f13",
"sha256:f27f8544c9d4c383bbe007c57e3235918e258364577373d4920e9162837be022"
"sha256:95b318319d6997bac3595517101ad9cc83fe5672ac498ba48d1a410f47afecd2",
"sha256:e93c93565005b37ddebf2396b4dc4b6913c1838baa82efdfb79acedd5816c240"
],
"index": "pypi",
"version": "==3.2.6"
"version": "==3.2.7"
},
"django-dbbackup": {
"git": "https://github.com/django-dbbackup/django-dbbackup.git",
@ -443,19 +443,19 @@
},
"docker": {
"hashes": [
"sha256:3e8bc47534e0ca9331d72c32f2881bb13b93ded0bcdeab3c833fb7cf61c0a9a5",
"sha256:fc961d622160e8021c10d1bcabc388c57d55fb1f917175afbe24af442e6879bd"
"sha256:5aafaec0d2a1de0e32010b43b5eac9f6f851c9db99a46ad32b8e44eeeb55616d",
"sha256:b88eef725b33c0ed59c67506631bbb09b480b7ca5a739bbbb948b446443fe914"
],
"index": "pypi",
"version": "==5.0.0"
"version": "==5.0.1"
},
"drf-spectacular": {
"hashes": [
"sha256:5b1c27de127c86564be5a967a6fa195cfe161b552d98364282ae9e6ed3d75a85",
"sha256:8588706c27f44adfbb3405bae9ef9cd6506f4b59d4cbd66c59780dce035602d9"
"sha256:98681add6671db9e6dba5f0d3dcf8aab5950cbb978497390507356e593bf082f",
"sha256:a430bab0f4ecfc90786b7b63bbee3f9a56094201fbed9bdfbf952e99e6469104"
],
"index": "pypi",
"version": "==0.18.0"
"version": "==0.18.1"
},
"duo-client": {
"hashes": [
@ -490,11 +490,11 @@
},
"google-auth": {
"hashes": [
"sha256:c012c8be7c442c8309ca8fa0876fef33f5fd977c467be1e1c1c2f721e8ebd73c",
"sha256:ea1af050b3e06eb73e4470f704d23007307bc0e87c13e015f6b90460f1407bd3"
"sha256:104475dc4d57bbae49017aea16fffbb763204fa2d6a70f1f3cc79962c1a383a4",
"sha256:cde472372e030e1e0bc64dac00fb53e6c095d7ab641f4281e2c995e85e205d8b"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.1"
"version": "==2.0.2"
},
"gunicorn": {
"hashes": [
@ -1151,11 +1151,11 @@
},
"typing-extensions": {
"hashes": [
"sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
"sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
"sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
"sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e",
"sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7",
"sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"
],
"version": "==3.10.0.0"
"version": "==3.10.0.2"
},
"ua-parser": {
"hashes": [
@ -1420,11 +1420,11 @@
},
"astroid": {
"hashes": [
"sha256:b6c2d75cd7c2982d09e7d41d70213e863b3ba34d3bd4014e08f167cee966e99e",
"sha256:ecc50f9b3803ebf8ea19aa2c6df5622d8a5c31456a53c741d3be044d96ff0948"
"sha256:3b680ce0419b8a771aba6190139a3998d14b413852506d99aff8dc2bf65ee67c",
"sha256:dc1e8b28427d6bbef6b8842b18765ab58f558c42bb80540bd7648c98412af25e"
],
"markers": "python_version ~= '3.6'",
"version": "==2.7.2"
"version": "==2.7.3"
},
"attrs": {
"hashes": [
@ -1652,19 +1652,19 @@
},
"platformdirs": {
"hashes": [
"sha256:4666d822218db6a262bdfdc9c39d21f23b4cfdb08af331a81e92751daf6c866c",
"sha256:632daad3ab546bd8e6af0537d09805cec458dce201bccfe23012df73332e181e"
"sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f",
"sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648"
],
"markers": "python_version >= '3.6'",
"version": "==2.2.0"
"version": "==2.3.0"
},
"pluggy": {
"hashes": [
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.13.1"
"markers": "python_version >= '3.6'",
"version": "==1.0.0"
},
"py": {
"hashes": [
@ -1707,11 +1707,11 @@
},
"pytest": {
"hashes": [
"sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b",
"sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"
"sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89",
"sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"
],
"index": "pypi",
"version": "==6.2.4"
"version": "==6.2.5"
},
"pytest-django": {
"hashes": [
@ -1758,49 +1758,49 @@
},
"regex": {
"hashes": [
"sha256:03840a07a402576b8e3a6261f17eb88abd653ad4e18ec46ef10c9a63f8c99ebd",
"sha256:06ba444bbf7ede3890a912bd4904bb65bf0da8f0d8808b90545481362c978642",
"sha256:1f9974826aeeda32a76648fc677e3125ade379869a84aa964b683984a2dea9f1",
"sha256:330836ad89ff0be756b58758878409f591d4737b6a8cef26a162e2a4961c3321",
"sha256:38600fd58c2996829480de7d034fb2d3a0307110e44dae80b6b4f9b3d2eea529",
"sha256:3a195e26df1fbb40ebee75865f9b64ba692a5824ecb91c078cc665b01f7a9a36",
"sha256:41acdd6d64cd56f857e271009966c2ffcbd07ec9149ca91f71088574eaa4278a",
"sha256:45f97ade892ace20252e5ccecdd7515c7df5feeb42c3d2a8b8c55920c3551c30",
"sha256:4b0c211c55d4aac4309c3209833c803fada3fc21cdf7b74abedda42a0c9dc3ce",
"sha256:5d5209c3ba25864b1a57461526ebde31483db295fc6195fdfc4f8355e10f7376",
"sha256:615fb5a524cffc91ab4490b69e10ae76c1ccbfa3383ea2fad72e54a85c7d47dd",
"sha256:61e734c2bcb3742c3f454dfa930ea60ea08f56fd1a0eb52d8cb189a2f6be9586",
"sha256:640ccca4d0a6fcc6590f005ecd7b16c3d8f5d52174e4854f96b16f34c39d6cb7",
"sha256:6dbd51c3db300ce9d3171f4106da18fe49e7045232630fe3d4c6e37cb2b39ab9",
"sha256:71a904da8c9c02aee581f4452a5a988c3003207cb8033db426f29e5b2c0b7aea",
"sha256:8021dee64899f993f4b5cca323aae65aabc01a546ed44356a0965e29d7893c94",
"sha256:8b8d551f1bd60b3e1c59ff55b9e8d74607a5308f66e2916948cafd13480b44a3",
"sha256:93f9f720081d97acee38a411e861d4ce84cbc8ea5319bc1f8e38c972c47af49f",
"sha256:96f0c79a70642dfdf7e6a018ebcbea7ea5205e27d8e019cad442d2acfc9af267",
"sha256:9966337353e436e6ba652814b0a957a517feb492a98b8f9d3b6ba76d22301dcc",
"sha256:a34ba9e39f8269fd66ab4f7a802794ffea6d6ac500568ec05b327a862c21ce23",
"sha256:a49f85f0a099a5755d0a2cc6fc337e3cb945ad6390ec892332c691ab0a045882",
"sha256:a795829dc522227265d72b25d6ee6f6d41eb2105c15912c230097c8f5bfdbcdc",
"sha256:a89ca4105f8099de349d139d1090bad387fe2b208b717b288699ca26f179acbe",
"sha256:ac95101736239260189f426b1e361dc1b704513963357dc474beb0f39f5b7759",
"sha256:ae87ab669431f611c56e581679db33b9a467f87d7bf197ac384e71e4956b4456",
"sha256:b091dcfee169ad8de21b61eb2c3a75f9f0f859f851f64fdaf9320759a3244239",
"sha256:b511c6009d50d5c0dd0bab85ed25bc8ad6b6f5611de3a63a59786207e82824bb",
"sha256:b79dc2b2e313565416c1e62807c7c25c67a6ff0a0f8d83a318df464555b65948",
"sha256:bca14dfcfd9aae06d7d8d7e105539bd77d39d06caaae57a1ce945670bae744e0",
"sha256:c835c30f3af5c63a80917b72115e1defb83de99c73bc727bddd979a3b449e183",
"sha256:ccd721f1d4fc42b541b633d6e339018a08dd0290dc67269df79552843a06ca92",
"sha256:d6c2b1d78ceceb6741d703508cd0e9197b34f6bf6864dab30f940f8886e04ade",
"sha256:d6ec4ae13760ceda023b2e5ef1f9bc0b21e4b0830458db143794a117fdbdc044",
"sha256:d8b623fc429a38a881ab2d9a56ef30e8ea20c72a891c193f5ebbddc016e083ee",
"sha256:ea9753d64cba6f226947c318a923dadaf1e21cd8db02f71652405263daa1f033",
"sha256:ebbceefbffae118ab954d3cd6bf718f5790db66152f95202ebc231d58ad4e2c2",
"sha256:ecb6e7c45f9cd199c10ec35262b53b2247fb9a408803ed00ee5bb2b54aa626f5",
"sha256:ef9326c64349e2d718373415814e754183057ebc092261387a2c2f732d9172b2",
"sha256:f93a9d8804f4cec9da6c26c8cfae2c777028b4fdd9f49de0302e26e00bb86504",
"sha256:faf08b0341828f6a29b8f7dd94d5cf8cc7c39bfc3e67b78514c54b494b66915a"
"sha256:04f6b9749e335bb0d2f68c707f23bb1773c3fb6ecd10edf0f04df12a8920d468",
"sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354",
"sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308",
"sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d",
"sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc",
"sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8",
"sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797",
"sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2",
"sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13",
"sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d",
"sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a",
"sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0",
"sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73",
"sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1",
"sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed",
"sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a",
"sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b",
"sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f",
"sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256",
"sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb",
"sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2",
"sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983",
"sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb",
"sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645",
"sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8",
"sha256:b4c220a1fe0d2c622493b0a1fd48f8f991998fb447d3cd368033a4b86cf1127a",
"sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906",
"sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f",
"sha256:c206587c83e795d417ed3adc8453a791f6d36b67c81416676cad053b4104152c",
"sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892",
"sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0",
"sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e",
"sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e",
"sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed",
"sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c",
"sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374",
"sha256:ed4b50355b066796dacdd1cf538f2ce57275d001838f9b132fab80b75e8c84dd",
"sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791",
"sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a",
"sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1",
"sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759"
],
"version": "==2021.8.21"
"version": "==2021.8.28"
},
"requests": {
"hashes": [

View File

@ -5,13 +5,14 @@
---
[![](https://img.shields.io/discord/809154715984199690?label=Discord&style=for-the-badge)](https://discord.gg/jg33eMhnj6)
[![CI Build status](https://img.shields.io/azure-devops/build/beryjuorg/authentik/6?style=for-the-badge)](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=6)
[![Tests](https://img.shields.io/azure-devops/tests/beryjuorg/authentik/6?compact_message&style=for-the-badge)](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=6)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-main?label=core%20build&style=for-the-badge)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-web?label=web%20build&style=for-the-badge)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-outpost?label=outpost%20build&style=for-the-badge)
[![Code Coverage](https://img.shields.io/codecov/c/gh/goauthentik/authentik?style=for-the-badge)](https://codecov.io/gh/goauthentik/authentik)
![Docker pulls](https://img.shields.io/docker/pulls/beryju/authentik.svg?style=for-the-badge)
![Latest version](https://img.shields.io/docker/v/beryju/authentik?sort=semver&style=for-the-badge)
![LGTM Grade](https://img.shields.io/lgtm/grade/python/github/goauthentik/authentik?style=for-the-badge)
[Transifex](https://www.transifex.com/beryjuorg/authentik/)
[![](https://img.shields.io/badge/Help%20translate-transifex-blue?style=for-the-badge)](https://www.transifex.com/beryjuorg/authentik/)
## What is authentik?

View File

@ -1,3 +1,3 @@
"""authentik"""
__version__ = "2021.8.2"
__version__ = "2021.8.4"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -1,8 +1,10 @@
"""authentik api urls"""
from django.urls import include, path
from authentik.api.v2.urls import urlpatterns as v2_urls
from authentik.api.v3.urls import urlpatterns as v3_urls
urlpatterns = [
path("v2beta/", include(v2_urls)),
# Remove in 2022.1
path("v2beta/", include(v3_urls)),
path("v3/", include(v3_urls)),
]

View File

@ -4,16 +4,44 @@ from json import loads
from django.conf import settings
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from django.views.generic.base import View
from requests import post
from requests.exceptions import RequestException
from rest_framework.authentication import SessionAuthentication
from rest_framework.parsers import BaseParser
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.throttling import AnonRateThrottle
from rest_framework.views import APIView
from authentik.lib.config import CONFIG
class SentryTunnelView(View):
class PlainTextParser(BaseParser):
"""Plain text parser."""
media_type = "text/plain"
def parse(self, stream, media_type=None, parser_context=None) -> str:
"""Simply return a string representing the body of the request."""
return stream.read()
class CsrfExemptSessionAuthentication(SessionAuthentication):
"""CSRF-exempt Session authentication"""
def enforce_csrf(self, request: Request):
return # To not perform the csrf check previously happening
class SentryTunnelView(APIView):
"""Sentry tunnel, to prevent ad blockers from blocking sentry"""
serializer_class = None
parser_classes = [PlainTextParser]
throttle_classes = [AnonRateThrottle]
permission_classes = [AllowAny]
authentication_classes = [CsrfExemptSessionAuthentication]
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Sentry tunnel, to prevent ad blockers from blocking sentry"""
# Only allow usage of this endpoint when error reporting is enabled

View File

@ -1,4 +1,4 @@
"""api v2 urls"""
"""api v3 urls"""
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from drf_spectacular.views import SpectacularAPIView
@ -10,8 +10,8 @@ from authentik.admin.api.system import SystemView
from authentik.admin.api.tasks import TaskViewSet
from authentik.admin.api.version import VersionView
from authentik.admin.api.workers import WorkerView
from authentik.api.v2.config import ConfigView
from authentik.api.v2.sentry import SentryTunnelView
from authentik.api.v3.config import ConfigView
from authentik.api.v3.sentry import SentryTunnelView
from authentik.api.views import APIBrowserView
from authentik.core.api.applications import ApplicationViewSet
from authentik.core.api.authenticated_sessions import AuthenticatedSessionViewSet

View File

@ -23,7 +23,7 @@ from authentik.managed.api import ManagedSerializer
class TokenSerializer(ManagedSerializer, ModelSerializer):
"""Token Serializer"""
user_obj = UserSerializer(required=False)
user_obj = UserSerializer(required=False, source="user")
def validate(self, attrs: dict[Any, str]) -> dict[Any, str]:
"""Ensure only API or App password tokens are created."""

View File

@ -11,6 +11,7 @@ from django.core.cache import cache
from prometheus_client import Gauge
from authentik.events.models import Event, EventAction
from authentik.lib.utils.errors import exception_to_string
GAUGE_TASKS = Gauge(
"authentik_system_tasks",
@ -174,9 +175,7 @@ class MonitoredTask(Task):
).save(self.result_timeout_hours)
Event.new(
EventAction.SYSTEM_TASK_EXCEPTION,
message=(
f"Task {self.__name__} encountered an error: " "\n".join(self._result.messages)
),
message=(f"Task {self.__name__} encountered an error: {exception_to_string(exc)}"),
).save()
return super().on_failure(exc, task_id, args, kwargs, einfo=einfo)

View File

@ -31,6 +31,7 @@ class FlowPlanProcess(PROCESS_CLASS): # pragma: no cover
self.request = RequestFactory().get("/")
def run(self):
"""Execute 1000 flow plans"""
print(f"Proc {self.index} Running")
def test_inner():

View File

@ -0,0 +1,21 @@
# Generated by Django 3.2.6 on 2021-08-30 14:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0023_alter_flow_background"),
]
operations = [
migrations.AlterField(
model_name="flow",
name="compatibility_mode",
field=models.BooleanField(
default=False,
help_text="Enable compatibility mode, increases compatibility with password managers on mobile devices.",
),
),
]

View File

@ -125,7 +125,7 @@ class Flow(SerializerModel, PolicyBindingModel):
)
compatibility_mode = models.BooleanField(
default=True,
default=False,
help_text=_(
"Enable compatibility mode, increases compatibility with "
"password managers on mobile devices."

View File

@ -2,10 +2,10 @@
from unittest.mock import MagicMock, PropertyMock, patch
from django.http import HttpRequest, HttpResponse
from django.test import TestCase
from django.test.client import RequestFactory
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -37,7 +37,7 @@ def to_stage_response(request: HttpRequest, source: HttpResponse):
TO_STAGE_RESPONSE_MOCK = MagicMock(side_effect=to_stage_response)
class TestFlowExecutor(TestCase):
class TestFlowExecutor(APITestCase):
"""Test views logic"""
def setUp(self):

View File

@ -1,5 +1,5 @@
"""flow views tests"""
from django.test import Client, TestCase
from django.test import TestCase
from django.urls import reverse
from authentik.flows.models import Flow, FlowDesignation
@ -10,9 +10,6 @@ from authentik.flows.views import SESSION_KEY_PLAN
class TestHelperView(TestCase):
"""Test helper views logic"""
def setUp(self):
self.client = Client()
def test_default_view(self):
"""Test that ToDefaultFlow returns the expected URL"""
flow = Flow.objects.filter(

View File

@ -29,7 +29,9 @@ class DockerController(BaseController):
raise ControllerException from exc
def _get_labels(self) -> dict[str, str]:
return {}
return {
"io.goauthentik.outpost-uuid": self.outpost.pk.hex,
}
def _get_env(self) -> dict[str, str]:
return {
@ -49,6 +51,17 @@ class DockerController(BaseController):
return True
return False
def _comp_labels(self, container: Container) -> bool:
"""Check if container's labels is equal to what we would set. Return true if container needs
to be rebuilt."""
should_be = self._get_labels()
for key, expected_value in should_be.items():
if key not in container.labels:
return True
if container.labels[key] != expected_value:
return True
return False
def _comp_ports(self, container: Container) -> bool:
"""Check that the container has the correct ports exposed. Return true if container needs
to be rebuilt."""
@ -92,9 +105,11 @@ class DockerController(BaseController):
"environment": self._get_env(),
"labels": self._get_labels(),
"restart_policy": {"Name": "unless-stopped"},
"network": self.outpost.config.docker_network,
}
if settings.TEST:
del container_args["ports"]
del container_args["network"]
container_args["network_mode"] = "host"
return (
self.client.containers.create(**container_args),
@ -133,6 +148,11 @@ class DockerController(BaseController):
self.logger.info("Container has outdated config, re-creating...")
self.down()
return self.up(depth + 1)
# Check that container values match our values
if self._comp_labels(container):
self.logger.info("Container has outdated labels, re-creating...")
self.down()
return self.up(depth + 1)
if (
container.attrs.get("HostConfig", {})
.get("RestartPolicy", {})

View File

@ -3,10 +3,11 @@ from typing import TYPE_CHECKING, Generic, TypeVar
from django.utils.text import slugify
from kubernetes.client import V1ObjectMeta
from kubernetes.client.exceptions import ApiException, OpenApiException
from kubernetes.client.models.v1_deployment import V1Deployment
from kubernetes.client.models.v1_pod import V1Pod
from kubernetes.client.rest import ApiException
from structlog.stdlib import get_logger
from urllib3.exceptions import HTTPError
from authentik import __version__
from authentik.lib.sentry import SentryIgnoredException
@ -72,8 +73,9 @@ class KubernetesObjectReconciler(Generic[T]):
try:
try:
current = self.retrieve()
except ApiException as exc:
if exc.status == 404:
except (OpenApiException, HTTPError) as exc:
# pylint: disable=no-member
if isinstance(exc, ApiException) and exc.status == 404:
self.logger.debug("Failed to get current, triggering recreate")
raise NeedsRecreate from exc
self.logger.debug("Other unhandled error", exc=exc)
@ -104,8 +106,9 @@ class KubernetesObjectReconciler(Generic[T]):
current = self.retrieve()
self.delete(current)
self.logger.debug("Removing")
except ApiException as exc:
if exc.status == 404:
except (OpenApiException, HTTPError) as exc:
# pylint: disable=no-member
if isinstance(exc, ApiException) and exc.status == 404:
self.logger.debug("Failed to get current, assuming non-existant")
return
self.logger.debug("Other unhandled error", exc=exc)

View File

@ -3,8 +3,9 @@ from io import StringIO
from typing import Type
from kubernetes.client.api_client import ApiClient
from kubernetes.client.exceptions import ApiException
from kubernetes.client.exceptions import OpenApiException
from structlog.testing import capture_logs
from urllib3.exceptions import HTTPError
from yaml import dump_all
from authentik.outposts.controllers.base import BaseController, ControllerException
@ -12,7 +13,7 @@ from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
from authentik.outposts.controllers.k8s.secret import SecretReconciler
from authentik.outposts.controllers.k8s.service import ServiceReconciler
from authentik.outposts.models import KubernetesServiceConnection, Outpost
from authentik.outposts.models import KubernetesServiceConnection, Outpost, ServiceConnectionInvalid
class KubernetesController(BaseController):
@ -40,7 +41,7 @@ class KubernetesController(BaseController):
reconciler = self.reconcilers[reconcile_key](self)
reconciler.up()
except ApiException as exc:
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def up_with_logs(self) -> list[str]:
@ -55,7 +56,7 @@ class KubernetesController(BaseController):
reconciler.up()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
return all_logs
except ApiException as exc:
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def down(self):
@ -65,7 +66,7 @@ class KubernetesController(BaseController):
self.logger.debug("Tearing down object", name=reconcile_key)
reconciler.down()
except ApiException as exc:
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def down_with_logs(self) -> list[str]:
@ -80,7 +81,7 @@ class KubernetesController(BaseController):
reconciler.down()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
return all_logs
except ApiException as exc:
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def get_static_deployment(self) -> str:

View File

@ -56,6 +56,7 @@ class ServiceConnectionInvalid(SentryIgnoredException):
@dataclass
# pylint: disable=too-many-instance-attributes
class OutpostConfig:
"""Configuration an outpost uses to configure it self"""
@ -67,8 +68,10 @@ class OutpostConfig:
log_level: str = CONFIG.y("log_level")
error_reporting_enabled: bool = CONFIG.y_bool("error_reporting.enabled")
error_reporting_environment: str = CONFIG.y("error_reporting.environment", "customer")
object_naming_template: str = field(default="ak-outpost-%(name)s")
docker_network: Optional[str] = field(default=None)
kubernetes_replicas: int = field(default=1)
kubernetes_namespace: str = field(default_factory=get_namespace)
kubernetes_ingress_annotations: dict[str, str] = field(default_factory=dict)
@ -362,7 +365,7 @@ class Outpost(ManagedModel):
)
try:
assign_perm(code_name, user, model_or_perm)
except Permission.DoesNotExist as exc:
except (Permission.DoesNotExist, AttributeError) as exc:
LOGGER.warning(
"permission doesn't exist",
code_name=code_name,

View File

@ -8,8 +8,11 @@ from structlog.stdlib import get_logger
from authentik.policies.models import Policy
from authentik.policies.types import PolicyRequest, PolicyResult
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
LOGGER = get_logger()
RE_LOWER = re.compile("[a-z]")
RE_UPPER = re.compile("[A-Z]")
class PasswordPolicy(Policy):
@ -38,31 +41,39 @@ class PasswordPolicy(Policy):
return "ak-policy-password-form"
def passes(self, request: PolicyRequest) -> PolicyResult:
if self.password_field not in request.context:
if (
self.password_field not in request.context
and self.password_field not in request.context.get(PLAN_CONTEXT_PROMPT, {})
):
LOGGER.warning(
"Password field not set in Policy Request",
field=self.password_field,
fields=request.context.keys(),
prompt_fields=request.context.get(PLAN_CONTEXT_PROMPT, {}).keys(),
)
return PolicyResult(False, _("Password not set in context"))
password = request.context[self.password_field]
filter_regex = []
if self.amount_lowercase > 0:
filter_regex.append(r"[a-z]{%d,}" % self.amount_lowercase)
if self.amount_uppercase > 0:
filter_regex.append(r"[A-Z]{%d,}" % self.amount_uppercase)
if self.amount_symbols > 0:
filter_regex.append(r"[%s]{%d,}" % (self.symbol_charset, self.amount_symbols))
full_regex = "|".join(filter_regex)
LOGGER.debug("Built regex", regexp=full_regex)
result = bool(re.compile(full_regex).match(password))
if self.password_field in request.context:
password = request.context[self.password_field]
else:
password = request.context[PLAN_CONTEXT_PROMPT][self.password_field]
result = result and len(password) >= self.length_min
if len(password) < self.length_min:
LOGGER.debug("password failed", reason="length", p=password)
return PolicyResult(False, self.error_message)
if not result:
return PolicyResult(result, self.error_message)
return PolicyResult(result)
if self.amount_lowercase > 0 and len(RE_LOWER.findall(password)) < self.amount_lowercase:
LOGGER.debug("password failed", reason="amount_lowercase", p=password)
return PolicyResult(False, self.error_message)
if self.amount_uppercase > 0 and len(RE_UPPER.findall(password)) < self.amount_lowercase:
LOGGER.debug("password failed", reason="amount_uppercase", p=password)
return PolicyResult(False, self.error_message)
regex = re.compile(r"[%s]" % self.symbol_charset)
if self.amount_symbols > 0 and len(regex.findall(password)) < self.amount_symbols:
LOGGER.debug("password failed", reason="amount_symbols", p=password)
return PolicyResult(False, self.error_message)
return PolicyResult(True)
class Meta:

View File

@ -1,57 +0,0 @@
"""Password Policy tests"""
from django.test import TestCase
from guardian.shortcuts import get_anonymous_user
from authentik.policies.password.models import PasswordPolicy
from authentik.policies.types import PolicyRequest, PolicyResult
class TestPasswordPolicy(TestCase):
"""Test Password Policy"""
def test_invalid(self):
"""Test without password"""
policy = PasswordPolicy.objects.create(
name="test_invalid",
amount_uppercase=1,
amount_lowercase=2,
amount_symbols=3,
length_min=24,
error_message="test message",
)
request = PolicyRequest(get_anonymous_user())
result: PolicyResult = policy.passes(request)
self.assertFalse(result.passing)
self.assertEqual(result.messages[0], "Password not set in context")
def test_false(self):
"""Failing password case"""
policy = PasswordPolicy.objects.create(
name="test_false",
amount_uppercase=1,
amount_lowercase=2,
amount_symbols=3,
length_min=24,
error_message="test message",
)
request = PolicyRequest(get_anonymous_user())
request.context["password"] = "test"
result: PolicyResult = policy.passes(request)
self.assertFalse(result.passing)
self.assertEqual(result.messages, ("test message",))
def test_true(self):
"""Positive password case"""
policy = PasswordPolicy.objects.create(
name="test_true",
amount_uppercase=1,
amount_lowercase=2,
amount_symbols=3,
length_min=3,
error_message="test message",
)
request = PolicyRequest(get_anonymous_user())
request.context["password"] = "Test()!"
result: PolicyResult = policy.passes(request)
self.assertTrue(result.passing)
self.assertEqual(result.messages, tuple())

View File

@ -0,0 +1,80 @@
"""Password flow tests"""
from django.urls.base import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
from authentik.policies.password.models import PasswordPolicy
from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage
class TestPasswordPolicyFlow(APITestCase):
"""Test Password Policy"""
def setUp(self) -> None:
self.user = User.objects.create(username="unittest", email="test@beryju.org")
self.flow = Flow.objects.create(
name="test-prompt",
slug="test-prompt",
designation=FlowDesignation.AUTHENTICATION,
)
password_prompt = Prompt.objects.create(
field_key="password",
label="PASSWORD_LABEL",
type=FieldTypes.PASSWORD,
required=True,
placeholder="PASSWORD_PLACEHOLDER",
)
self.policy = PasswordPolicy.objects.create(
name="test_true",
amount_uppercase=1,
amount_lowercase=2,
amount_symbols=3,
length_min=3,
error_message="test message",
)
stage = PromptStage.objects.create(name="prompt-stage")
stage.validation_policies.set([self.policy])
stage.fields.set(
[
password_prompt,
]
)
FlowStageBinding.objects.create(target=self.flow, stage=stage, order=2)
def test_prompt_data(self):
"""Test policy attached to a prompt stage"""
response = self.client.post(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
{"password": "akadmin"},
)
self.assertEqual(response.status_code, 200)
self.assertJSONEqual(
force_str(response.content),
{
"component": "ak-stage-prompt",
"fields": [
{
"field_key": "password",
"label": "PASSWORD_LABEL",
"order": 0,
"placeholder": "PASSWORD_PLACEHOLDER",
"required": True,
"type": "password",
}
],
"flow_info": {
"background": self.flow.background_url,
"cancel_url": reverse("authentik_flows:cancel"),
"title": "",
},
"response_errors": {
"non_field_errors": [{"code": "invalid", "string": self.policy.error_message}]
},
"type": ChallengeTypes.NATIVE.value,
},
)

View File

@ -0,0 +1,68 @@
"""Password Policy tests"""
from django.test import TestCase
from guardian.shortcuts import get_anonymous_user
from authentik.lib.generators import generate_key
from authentik.policies.password.models import PasswordPolicy
from authentik.policies.types import PolicyRequest, PolicyResult
class TestPasswordPolicy(TestCase):
"""Test Password Policy"""
def setUp(self) -> None:
self.policy = PasswordPolicy.objects.create(
name="test_false",
amount_uppercase=1,
amount_lowercase=2,
amount_symbols=3,
length_min=24,
error_message="test message",
)
def test_invalid(self):
"""Test without password"""
request = PolicyRequest(get_anonymous_user())
result: PolicyResult = self.policy.passes(request)
self.assertFalse(result.passing)
self.assertEqual(result.messages[0], "Password not set in context")
def test_failed_length(self):
"""Password too short"""
request = PolicyRequest(get_anonymous_user())
request.context["password"] = "test"
result: PolicyResult = self.policy.passes(request)
self.assertFalse(result.passing)
self.assertEqual(result.messages, ("test message",))
def test_failed_lowercase(self):
"""not enough lowercase"""
request = PolicyRequest(get_anonymous_user())
request.context["password"] = "TTTTTTTTTTTTTTTTTTTTTTTe"
result: PolicyResult = self.policy.passes(request)
self.assertFalse(result.passing)
self.assertEqual(result.messages, ("test message",))
def test_failed_uppercase(self):
"""not enough uppercase"""
request = PolicyRequest(get_anonymous_user())
request.context["password"] = "tttttttttttttttttttttttE"
result: PolicyResult = self.policy.passes(request)
self.assertFalse(result.passing)
self.assertEqual(result.messages, ("test message",))
def test_failed_symbols(self):
"""not enough uppercase"""
request = PolicyRequest(get_anonymous_user())
request.context["password"] = "TETETETETETETETETETETETETe!!!"
result: PolicyResult = self.policy.passes(request)
self.assertFalse(result.passing)
self.assertEqual(result.messages, ("test message",))
def test_true(self):
"""Positive password case"""
request = PolicyRequest(get_anonymous_user())
request.context["password"] = generate_key() + "ee!!!"
result: PolicyResult = self.policy.passes(request)
self.assertTrue(result.passing)
self.assertEqual(result.messages, tuple())

View File

@ -22,13 +22,13 @@ class ProxyDockerController(DockerController):
for proxy_provider in ProxyProvider.objects.filter(outpost__in=[self.outpost]):
proxy_provider: ProxyProvider
external_host_name = urlparse(proxy_provider.external_host)
hosts.append(f"`{external_host_name}`")
hosts.append(f"`{external_host_name.netloc}`")
traefik_name = f"ak-outpost-{self.outpost.pk.hex}"
return {
"traefik.enable": "true",
f"traefik.http.routers.{traefik_name}-router.rule": f"Host({','.join(hosts)})",
f"traefik.http.routers.{traefik_name}-router.tls": "true",
f"traefik.http.routers.{traefik_name}-router.service": f"{traefik_name}-service",
f"traefik.http.services.{traefik_name}-service.loadbalancer.healthcheck.path": "/",
f"traefik.http.services.{traefik_name}-service.loadbalancer.server.port": "4180",
}
labels = super()._get_labels()
labels["traefik.enable"] = "true"
labels[f"traefik.http.routers.{traefik_name}-router.rule"] = f"Host({','.join(hosts)})"
labels[f"traefik.http.routers.{traefik_name}-router.tls"] = "true"
labels[f"traefik.http.routers.{traefik_name}-router.service"] = f"{traefik_name}-service"
labels[f"traefik.http.services.{traefik_name}-service.loadbalancer.healthcheck.path"] = "/"
labels[f"traefik.http.services.{traefik_name}-service.loadbalancer.server.port"] = "4180"
return labels

View File

@ -61,9 +61,10 @@ class IngressReconciler(KubernetesObjectReconciler[NetworkingV1beta1Ingress]):
have_hosts.sort()
have_hosts_tls = []
for tls_config in current.spec.tls:
if tls_config and tls_config.hosts:
have_hosts_tls += tls_config.hosts
if current.spec.tls:
for tls_config in current.spec.tls:
if tls_config and tls_config.hosts:
have_hosts_tls += tls_config.hosts
have_hosts_tls.sort()
if have_hosts != expected_hosts:

View File

@ -96,6 +96,7 @@ class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware])
def get_reference_object(self) -> TraefikMiddleware:
"""Get deployment object for outpost"""
port = 9000 if self.is_embedded else 4180
return TraefikMiddleware(
apiVersion=f"{CRD_GROUP}/{CRD_VERSION}",
kind="Middleware",
@ -106,7 +107,7 @@ class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware])
),
spec=TraefikMiddlewareSpec(
forwardAuth=TraefikMiddlewareSpecForwardAuth(
address=f"http://{self.name}.{self.namespace}:4180/akprox/auth?traefik",
address=f"http://{self.name}.{self.namespace}:{port}/akprox/auth?traefik",
authResponseHeaders=[
"Set-Cookie",
"X-Auth-Username",

View File

@ -150,9 +150,20 @@ SPECTACULAR_SETTINGS = {
"DESCRIPTION": "Making authentication simple.",
"VERSION": __version__,
"COMPONENT_SPLIT_REQUEST": True,
"SCHEMA_PATH_PREFIX": "/api/v([0-9]+(beta)?)",
"SCHEMA_PATH_PREFIX_TRIM": True,
"SERVERS": [
{
"url": "http://authentik.tld/api/v3/",
},
{
"url": "http://authentik.tld/api/v2beta/",
},
],
"CONTACT": {
"email": "hello@beryju.org",
},
"AUTHENTICATION_WHITELIST": ["authentik.api.authentication.TokenAuthentication"],
"LICENSE": {
"name": "GNU GPLv3",
"url": "https://github.com/goauthentik/authentik/blob/master/LICENSE",
@ -180,6 +191,9 @@ REST_FRAMEWORK = {
"rest_framework.filters.OrderingFilter",
"rest_framework.filters.SearchFilter",
],
"DEFAULT_PARSER_CLASSES": [
"rest_framework.parsers.JSONParser",
],
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.DjangoObjectPermissions",),
"DEFAULT_AUTHENTICATION_CLASSES": (
"authentik.api.authentication.TokenAuthentication",
@ -189,6 +203,7 @@ REST_FRAMEWORK = {
"rest_framework.renderers.JSONRenderer",
],
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"TEST_REQUEST_DEFAULT_FORMAT": "json",
}
REDIS_PROTOCOL_PREFIX = "redis://"
@ -372,6 +387,7 @@ if CONFIG.y("postgresql.s3_backup"):
"default_acl": "private",
"endpoint_url": CONFIG.y("postgresql.s3_backup.host"),
"location": CONFIG.y("postgresql.s3_backup.location", ""),
"verify": not CONFIG.y_bool("postgresql.s3_backup.insecure_skip_verify", False),
}
j_print(
"Database backup to S3 is configured",

View File

@ -2,17 +2,13 @@
from base64 import b64encode
from django.conf import settings
from django.test import Client, TestCase
from django.test import TestCase
from django.urls import reverse
class TestRoot(TestCase):
"""Test root application"""
def setUp(self):
super().setUp()
self.client = Client()
def test_monitoring_error(self):
"""Test monitoring without any credentials"""
response = self.client.get(reverse("metrics"))

View File

@ -1,5 +1,5 @@
"""Twitter Type tests"""
from django.test import Client, TestCase
from django.test import TestCase
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.twitter import TwitterOAuthCallback
@ -92,7 +92,6 @@ class TestTypeGitHub(TestCase):
"""OAuth Source tests"""
def setUp(self):
self.client = Client()
self.source = OAuthSource.objects.create(
name="test",
slug="test",

View File

@ -51,20 +51,30 @@ def get_webauthn_challenge(request: HttpRequest, device: WebAuthnDevice) -> dict
# for the reasons outlined in the comment in webauthn_begin_activate.
request.session["challenge"] = challenge.rstrip("=")
webauthn_user = WebAuthnUser(
device.user.uid,
device.user.username,
device.user.name,
device.user.avatar,
device.credential_id,
device.public_key,
device.sign_count,
device.rp_id,
)
assertion = {}
user = device.user
webauthn_assertion_options = WebAuthnAssertionOptions(webauthn_user, challenge)
# We want all the user's WebAuthn devices and merge their challenges
for user_device in WebAuthnDevice.objects.filter(user=device.user).order_by("name"):
webauthn_user = WebAuthnUser(
user.uid,
user.username,
user.name,
user.avatar,
user_device.credential_id,
user_device.public_key,
user_device.sign_count,
user_device.rp_id,
)
webauthn_assertion_options = WebAuthnAssertionOptions(webauthn_user, challenge)
if assertion == {}:
assertion = webauthn_assertion_options.assertion_dict
else:
assertion["allowCredentials"] += webauthn_assertion_options.assertion_dict.get(
"allowCredentials"
)
return webauthn_assertion_options.assertion_dict
return assertion
def validate_challenge_code(code: str, request: HttpRequest, user: User) -> str:

View File

@ -20,8 +20,6 @@ from authentik.stages.authenticator_validate.models import AuthenticatorValidate
LOGGER = get_logger()
PER_DEVICE_CLASSES = [DeviceClasses.WEBAUTHN]
class AuthenticatorValidationChallenge(WithUserInfoChallenge):
"""Authenticator challenge"""
@ -91,9 +89,9 @@ class AuthenticatorValidateStageView(ChallengeStageView):
if device_class not in stage.device_classes:
LOGGER.debug("device class not allowed", device_class=device_class)
continue
# Ensure only classes in PER_DEVICE_CLASSES are returned per device
# otherwise only return a single challenge
if device_class in seen_classes and device_class not in PER_DEVICE_CLASSES:
# Ensure only one challenge per device class
# WebAuthn does another device loop to find all webuahtn devices
if device_class in seen_classes:
continue
if device_class not in seen_classes:
seen_classes.append(device_class)

View File

@ -1,12 +1,12 @@
"""Test validator stage"""
from unittest.mock import MagicMock, patch
from django.test import TestCase
from django.test.client import RequestFactory
from django.urls.base import reverse
from django.utils.encoding import force_str
from django_otp.plugins.otp_totp.models import TOTPDevice
from rest_framework.exceptions import ValidationError
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -26,7 +26,7 @@ from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
from authentik.stages.identification.models import IdentificationStage, UserFields
class AuthenticatorValidateStageTests(TestCase):
class AuthenticatorValidateStageTests(APITestCase):
"""Test validator stage"""
def setUp(self) -> None:

View File

@ -1,7 +1,7 @@
"""captcha tests"""
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -16,13 +16,12 @@ RECAPTCHA_PUBLIC_KEY = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
RECAPTCHA_PRIVATE_KEY = "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"
class TestCaptchaStage(TestCase):
class TestCaptchaStage(APITestCase):
"""Captcha tests"""
def setUp(self):
super().setUp()
self.user = User.objects.create_user(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-captcha",

View File

@ -1,9 +1,9 @@
"""consent tests"""
from time import sleep
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import Application, User
from authentik.core.tasks import clean_expired_models
@ -15,7 +15,7 @@ from authentik.flows.views import SESSION_KEY_PLAN
from authentik.stages.consent.models import ConsentMode, ConsentStage, UserConsent
class TestConsentStage(TestCase):
class TestConsentStage(APITestCase):
"""Consent tests"""
def setUp(self):
@ -25,7 +25,6 @@ class TestConsentStage(TestCase):
name="test-application",
slug="test-application",
)
self.client = Client()
def test_always_required(self):
"""Test always required consent"""

View File

@ -1,7 +1,7 @@
"""deny tests"""
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -12,13 +12,12 @@ from authentik.flows.views import SESSION_KEY_PLAN
from authentik.stages.deny.models import DenyStage
class TestUserDenyStage(TestCase):
class TestUserDenyStage(APITestCase):
"""Deny tests"""
def setUp(self):
super().setUp()
self.user = User.objects.create(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-logout",

View File

@ -1,7 +1,7 @@
"""dummy tests"""
from django.test import TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -9,7 +9,7 @@ from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
from authentik.stages.dummy.models import DummyStage
class TestDummyStage(TestCase):
class TestDummyStage(APITestCase):
"""Dummy tests"""
def setUp(self):

View File

@ -4,8 +4,8 @@ from unittest.mock import MagicMock, patch
from django.core import mail
from django.core.mail.backends.locmem import EmailBackend
from django.test import Client, TestCase
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.events.models import Event, EventAction
@ -16,13 +16,12 @@ from authentik.flows.views import SESSION_KEY_PLAN
from authentik.stages.email.models import EmailStage
class TestEmailStageSending(TestCase):
class TestEmailStageSending(APITestCase):
"""Email tests"""
def setUp(self):
super().setUp()
self.user = User.objects.create_user(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-email",

View File

@ -2,10 +2,10 @@
from unittest.mock import MagicMock, patch
from django.core import mail
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from django.utils.http import urlencode
from rest_framework.test import APITestCase
from authentik.core.models import Token, User
from authentik.flows.challenge import ChallengeTypes
@ -17,13 +17,12 @@ from authentik.stages.email.models import EmailStage
from authentik.stages.email.stage import QS_KEY_TOKEN
class TestEmailStage(TestCase):
class TestEmailStage(APITestCase):
"""Email tests"""
def setUp(self):
super().setUp()
self.user = User.objects.create_user(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-email",

View File

@ -96,7 +96,9 @@ class IdentificationChallengeResponse(ChallengeResponse):
# No password stage select, don't validate the password
return attrs
password = attrs["password"]
password = attrs.get("password", None)
if not password:
LOGGER.warning("Password not set for ident+auth attempt")
try:
user = authenticate(
self.stage.request,

View File

@ -1,7 +1,7 @@
"""identification tests"""
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -13,7 +13,7 @@ from authentik.stages.password import BACKEND_INBUILT
from authentik.stages.password.models import PasswordStage
class TestIdentificationStage(TestCase):
class TestIdentificationStage(APITestCase):
"""Identification tests"""
def setUp(self):
@ -22,7 +22,6 @@ class TestIdentificationStage(TestCase):
self.user = User.objects.create_user(
username="unittest", email="test@beryju.org", password=self.password
)
self.client = Client()
# OAuthSource for the login view
source = OAuthSource.objects.create(name="test", slug="test")

View File

@ -0,0 +1,25 @@
# Generated by Django 3.2.6 on 2021-09-01 12:11
from django.db import migrations, models
import authentik.core.models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_invitation", "0004_invitation_single_use"),
]
operations = [
migrations.AddField(
model_name="invitation",
name="expiring",
field=models.BooleanField(default=True),
),
migrations.AlterField(
model_name="invitation",
name="expires",
field=models.DateTimeField(default=authentik.core.models.default_token_duration),
),
]

View File

@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
from django.views import View
from rest_framework.serializers import BaseSerializer
from authentik.core.models import User
from authentik.core.models import ExpiringModel, User
from authentik.flows.models import Stage
@ -48,7 +48,7 @@ class InvitationStage(Stage):
verbose_name_plural = _("Invitation Stages")
class Invitation(models.Model):
class Invitation(ExpiringModel):
"""Single-use invitation link"""
invite_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
@ -59,7 +59,6 @@ class Invitation(models.Model):
)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
expires = models.DateTimeField(default=None, blank=True, null=True)
fixed_data = models.JSONField(
default=dict,
blank=True,

View File

@ -1,7 +1,6 @@
"""invitation tests"""
from unittest.mock import MagicMock, patch
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from django.utils.http import urlencode
@ -21,13 +20,12 @@ from authentik.stages.password import BACKEND_INBUILT
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
class TestUserLoginStage(TestCase):
class TestUserLoginStage(APITestCase):
"""Login tests"""
def setUp(self):
super().setUp()
self.user = User.objects.create(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-invitation",

View File

@ -32,9 +32,7 @@ PLAN_CONTEXT_METHOD_ARGS = "auth_method_args"
SESSION_INVALID_TRIES = "user_invalid_tries"
def authenticate(
request: HttpRequest, backends: list[str], **credentials: dict[str, Any]
) -> Optional[User]:
def authenticate(request: HttpRequest, backends: list[str], **credentials: Any) -> Optional[User]:
"""If the given credentials are valid, return a User object.
Customized version of django's authenticate, which accepts a list of backends"""

View File

@ -2,9 +2,9 @@
from unittest.mock import MagicMock, patch
from django.core.exceptions import PermissionDenied
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -20,7 +20,7 @@ from authentik.stages.password.models import PasswordStage
MOCK_BACKEND_AUTHENTICATE = MagicMock(side_effect=PermissionDenied("test"))
class TestPasswordStage(TestCase):
class TestPasswordStage(APITestCase):
"""Password tests"""
def setUp(self):
@ -29,7 +29,6 @@ class TestPasswordStage(TestCase):
self.user = User.objects.create_user(
username="unittest", email="test@beryju.org", password=self.password
)
self.client = Client()
self.flow = Flow.objects.create(
name="test-password",

View File

@ -1,10 +1,10 @@
"""Prompt tests"""
from unittest.mock import MagicMock, patch
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.exceptions import ErrorDetail
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -17,13 +17,12 @@ from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT, PromptChallengeResponse
class TestPromptStage(TestCase):
class TestPromptStage(APITestCase):
"""Prompt tests"""
def setUp(self):
super().setUp()
self.user = User.objects.create(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-prompt",
@ -97,7 +96,6 @@ class TestPromptStage(TestCase):
static_prompt,
]
)
self.stage.save()
self.prompt_data = {
username_prompt.field_key: "test-username",

View File

@ -1,9 +1,9 @@
"""delete tests"""
from unittest.mock import patch
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -15,14 +15,13 @@ from authentik.flows.views import SESSION_KEY_PLAN
from authentik.stages.user_delete.models import UserDeleteStage
class TestUserDeleteStage(TestCase):
class TestUserDeleteStage(APITestCase):
"""Delete tests"""
def setUp(self):
super().setUp()
self.username = "qerqwerqrwqwerwq"
self.user = User.objects.create(username=self.username, email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-delete",

View File

@ -2,9 +2,9 @@
from time import sleep
from unittest.mock import patch
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -16,13 +16,12 @@ from authentik.flows.views import SESSION_KEY_PLAN
from authentik.stages.user_login.models import UserLoginStage
class TestUserLoginStage(TestCase):
class TestUserLoginStage(APITestCase):
"""Login tests"""
def setUp(self):
super().setUp()
self.user = User.objects.create(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-login",

View File

@ -1,7 +1,7 @@
"""logout tests"""
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -14,13 +14,12 @@ from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
from authentik.stages.user_logout.models import UserLogoutStage
class TestUserLogoutStage(TestCase):
class TestUserLogoutStage(APITestCase):
"""Logout tests"""
def setUp(self):
super().setUp()
self.user = User.objects.create(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-logout",

View File

@ -3,9 +3,9 @@ import string
from random import SystemRandom
from unittest.mock import patch
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import USER_ATTRIBUTE_SOURCES, Source, User, UserSourceConnection
from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION
@ -19,13 +19,11 @@ from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
from authentik.stages.user_write.models import UserWriteStage
class TestUserWriteStage(TestCase):
class TestUserWriteStage(APITestCase):
"""Write tests"""
def setUp(self):
super().setUp()
self.client = Client()
self.flow = Flow.objects.create(
name="test-write",
slug="test-write",

View File

@ -1,120 +0,0 @@
trigger:
batch: true
branches:
include:
- master
- next
- version-*
stages:
- stage: generate
jobs:
- job: generate_api
pool:
vmImage: 'ubuntu-latest'
steps:
- task: GoTool@0
inputs:
version: '1.16.3'
- task: CmdLine@2
inputs:
script: make gen-outpost
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'api/'
artifact: 'go_api_client'
publishLocation: 'pipeline'
- stage: lint
jobs:
- job: golint
pool:
vmImage: 'ubuntu-latest'
steps:
- task: GoTool@0
inputs:
version: '1.16.3'
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'go_api_client'
path: "api/"
- task: CmdLine@2
inputs:
script: |
mkdir -p web/dist
mkdir -p website/help
touch web/dist/test website/help/test
docker run \
--rm \
-v $(pwd):/app \
-w /app \
golangci/golangci-lint:v1.39.0 \
golangci-lint run -v --timeout 200s
- stage: build_docker
jobs:
- job: proxy_build_docker
pool:
vmImage: 'ubuntu-latest'
steps:
- task: GoTool@0
inputs:
version: '1.16.3'
- task: Bash@3
inputs:
targetType: 'inline'
script: |
python ./scripts/az_do_set_branch.py
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/outpost-proxy'
command: 'build'
Dockerfile: 'proxy.Dockerfile'
buildContext: '$(Build.SourcesDirectory)'
tags: |
gh-$(branchName)
gh-$(branchName)-$(timestamp)
gh-$(Build.SourceVersion)
arguments: '--build-arg GIT_BUILD_HASH=$(Build.SourceVersion)'
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/outpost-proxy'
command: 'push'
tags: |
gh-$(branchName)
gh-$(branchName)-$(timestamp)
gh-$(Build.SourceVersion)
- job: ldap_build_docker
pool:
vmImage: 'ubuntu-latest'
steps:
- task: GoTool@0
inputs:
version: '1.16.3'
- task: Bash@3
inputs:
targetType: 'inline'
script: |
python ./scripts/az_do_set_branch.py
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/outpost-ldap'
command: 'build'
Dockerfile: 'ldap.Dockerfile'
buildContext: '$(Build.SourcesDirectory)'
tags: |
gh-$(branchName)
gh-$(branchName)-$(timestamp)
gh-$(Build.SourceVersion)
arguments: '--build-arg GIT_BUILD_HASH=$(Build.SourceVersion)'
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/outpost-ldap'
command: 'push'
tags: |
gh-$(branchName)
gh-$(branchName)-$(timestamp)
gh-$(Build.SourceVersion)

View File

@ -1,426 +0,0 @@
trigger:
batch: true
branches:
include:
- master
- next
- version-*
paths:
exclude:
- website
- outpost
resources:
- repo: self
variables:
- name: POSTGRES_DB
value: authentik
- name: POSTGRES_USER
value: authentik
- name: POSTGRES_PASSWORD
value: "EK-5jnKfjrGRm<77"
- group: coverage
stages:
- stage: Lint_and_test
jobs:
- job: pylint
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: DockerCompose@0
displayName: Run services
inputs:
dockerComposeFile: 'scripts/ci.docker-compose.yml'
action: 'Run services'
buildImages: false
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
inputs:
script: |
pipenv run python -m scripts.generate_ci_config
pipenv run pylint authentik tests lifecycle
- job: black
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
inputs:
script: pipenv run black --check authentik tests lifecycle
- job: isort
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
inputs:
script: pipenv run isort --check authentik tests lifecycle
- job: bandit
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
inputs:
script: pipenv run bandit -r authentik tests lifecycle
- job: pyright
pool:
vmImage: ubuntu-latest
steps:
- task: UseNode@1
inputs:
version: '12.x'
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: CmdLine@2
inputs:
script: npm install -g pyright@1.1.136
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
inputs:
script: pipenv run pyright e2e lifecycle
- job: migrations
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: DockerCompose@0
displayName: Run services
inputs:
dockerComposeFile: 'scripts/ci.docker-compose.yml'
action: 'Run services'
buildImages: false
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
inputs:
script: |
pipenv run python -m scripts.generate_ci_config
pipenv run python -m lifecycle.migrate
- job: migrations_from_previous_release
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.8'
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: DockerCompose@0
displayName: Run services
inputs:
dockerComposeFile: 'scripts/ci.docker-compose.yml'
action: 'Run services'
buildImages: false
- task: CmdLine@2
displayName: Prepare Last tagged release
inputs:
script: |
# Copy current, latest config to local
cp authentik/lib/default.yml local.env.yml
git checkout $(git describe --abbrev=0 --match 'version/*')
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
displayName: Migrate to last tagged release
inputs:
script: |
pipenv run python -m scripts.generate_ci_config
pipenv run python -m lifecycle.migrate
- task: CmdLine@2
displayName: Install current branch
inputs:
script: |
set -x
git checkout ${{ variables.branchName }}
pipenv sync --dev
- task: CmdLine@2
displayName: Migrate to current branch
inputs:
script: |
pipenv run python -m scripts.generate_ci_config
pipenv run python -m lifecycle.migrate
- job: coverage_unittest
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: DockerCompose@0
displayName: Run services
inputs:
dockerComposeFile: 'scripts/ci.docker-compose.yml'
action: 'Run services'
buildImages: false
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
displayName: Run full test suite
inputs:
script: |
pipenv run python -m scripts.generate_ci_config
pipenv run make test
- task: CmdLine@2
inputs:
script: |
mkdir output-unittest
mv unittest.xml output-unittest/unittest.xml
mv .coverage output-unittest/coverage
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'output-unittest/'
artifact: 'coverage-unittest'
publishLocation: 'pipeline'
- job: coverage_integration
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: DockerCompose@0
displayName: Run services
inputs:
dockerComposeFile: 'scripts/ci.docker-compose.yml'
action: 'Run services'
buildImages: false
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
- task: CmdLine@2
displayName: Install K3d and prepare
inputs:
script: |
wget -q -O - https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash
k3d cluster create
k3d kubeconfig write -o ~/.kube/config --overwrite
- task: CmdLine@2
displayName: Run full test suite
inputs:
script: |
pipenv run python -m scripts.generate_ci_config
pipenv run make test-integration
- task: CmdLine@2
inputs:
script: |
mkdir output-integration
mv unittest.xml output-integration/unittest.xml
mv .coverage output-integration/coverage
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'output-integration/'
artifact: 'coverage-integration'
publishLocation: 'pipeline'
- job: coverage_e2e
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: NodeTool@0
inputs:
versionSpec: '16.x'
- task: DockerCompose@0
displayName: Run services
inputs:
dockerComposeFile: 'scripts/ci.docker-compose.yml'
action: 'Run services'
buildImages: false
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev --python python3.9
- task: DockerCompose@0
displayName: Run ChromeDriver
inputs:
dockerComposeFile: 'tests/e2e/ci.docker-compose.yml'
action: 'Run a specific service'
serviceName: 'chrome'
- task: CmdLine@2
displayName: Build static files for e2e
inputs:
script: |
cd web
npm i
npm run build
- task: CmdLine@2
displayName: Run full test suite
inputs:
script: |
pipenv run python -m scripts.generate_ci_config
pipenv run make test-e2e
- task: CmdLine@2
condition: always()
displayName: Cleanup
inputs:
script: |
docker stop $(docker ps -aq)
docker container prune -f
- task: CmdLine@2
displayName: Prepare unittests and coverage for upload
inputs:
script: |
mkdir output-e2e
mv unittest.xml output-e2e/unittest.xml
mv .coverage output-e2e/coverage
- task: PublishPipelineArtifact@1
condition: failed()
displayName: Upload screenshots if selenium tests fail
inputs:
targetPath: 'selenium_screenshots/'
artifact: 'selenium screenshots'
publishLocation: 'pipeline'
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'output-e2e/'
artifact: 'coverage-e2e'
publishLocation: 'pipeline'
- stage: test_combine
jobs:
- job: test_coverage_combine
pool:
vmImage: 'ubuntu-latest'
steps:
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'coverage-e2e'
path: "coverage-e2e/"
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'coverage-integration'
path: "coverage-integration/"
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'coverage-unittest'
path: "coverage-unittest/"
- task: UsePythonVersion@0
inputs:
versionSpec: '3.9'
- task: CmdLine@2
inputs:
script: |
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
pipenv run coverage combine coverage-e2e/coverage coverage-unittest/coverage coverage-integration/coverage
pipenv run coverage xml
pipenv run coverage html
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: 'Cobertura'
summaryFileLocation: 'coverage.xml'
pathToSources: '$(System.DefaultWorkingDirectory)'
- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: |
coverage-e2e/unittest.xml
coverage-integration/unittest.xml
coverage-unittest/unittest.xml
mergeTestResults: true
- task: CmdLine@2
inputs:
script: bash <(curl -s https://codecov.io/bash)
- stage: Build
jobs:
- job: build_server
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Bash@3
inputs:
targetType: 'inline'
script: |
python ./scripts/az_do_set_branch.py
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/server'
command: 'build'
Dockerfile: 'Dockerfile'
tags: |
gh-$(branchName)
gh-$(branchName)-$(timestamp)
arguments: '--build-arg GIT_BUILD_HASH=$(Build.SourceVersion)'
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/server'
command: 'push'
tags: |
gh-$(branchName)
gh-$(branchName)-$(timestamp)

View File

@ -60,7 +60,9 @@ func main() {
for {
go attemptStartBackend(g)
ws.Start()
go attemptProxyStart(ws, u)
if !config.G.Web.DisableEmbeddedOutpost {
go attemptProxyStart(ws, u)
}
<-ex
running = false

View File

@ -21,7 +21,7 @@ services:
networks:
- internal
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.8.2}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.8.4}
restart: unless-stopped
command: server
environment:
@ -44,7 +44,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.8.2}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.8.4}
restart: unless-stopped
command: worker
networks:

2
go.mod
View File

@ -10,7 +10,7 @@ require (
github.com/go-ldap/ldap/v3 v3.4.1
github.com/go-openapi/analysis v0.20.1 // indirect
github.com/go-openapi/errors v0.20.0 // indirect
github.com/go-openapi/runtime v0.19.30
github.com/go-openapi/runtime v0.19.31
github.com/go-openapi/strfmt v0.20.2
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-openapi/validate v0.20.2 // indirect

4
go.sum
View File

@ -205,8 +205,8 @@ github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29g
github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98=
github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
github.com/go-openapi/runtime v0.19.30 h1:bVDeSf4HU9EMth+lHD1EthaHe1SFoUVPaUvQtkGS9g8=
github.com/go-openapi/runtime v0.19.30/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
github.com/go-openapi/runtime v0.19.31 h1:GX+MgBxN12s/tQiHNJpvHDIoZiEXAz6j6Rqg0oJcnpg=
github.com/go-openapi/runtime v0.19.31/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=

View File

@ -27,9 +27,10 @@ type RedisConfig struct {
}
type WebConfig struct {
Listen string `yaml:"listen"`
ListenTLS string `yaml:"listen_tls"`
LoadLocalFiles bool `yaml:"load_local_files" env:"AUTHENTIK_WEB_LOAD_LOCAL_FILES"`
Listen string `yaml:"listen"`
ListenTLS string `yaml:"listen_tls"`
LoadLocalFiles bool `yaml:"load_local_files" env:"AUTHENTIK_WEB_LOAD_LOCAL_FILES"`
DisableEmbeddedOutpost bool `yaml:"disable_embedded_outpost" env:"AUTHENTIK_WEB__DISABLE_EMBEDDED_OUTPOST"`
}
type PathsConfig struct {

View File

@ -17,4 +17,4 @@ func OutpostUserAgent() string {
return fmt.Sprintf("authentik-outpost@%s (%s)", VERSION, BUILD())
}
const VERSION = "2021.8.2"
const VERSION = "2021.8.4"

View File

@ -152,7 +152,9 @@ func (fe *FlowExecutor) solveFlowChallenge(depth int) (bool, error) {
responseReq := fe.api.FlowsApi.FlowsExecutorSolve(scsp.Context(), fe.flowSlug).Query(fe.Params.Encode())
switch ch.GetComponent() {
case string(StageIdentification):
responseReq = responseReq.FlowChallengeResponseRequest(api.IdentificationChallengeResponseRequestAsFlowChallengeResponseRequest(api.NewIdentificationChallengeResponseRequest(fe.getAnswer(StageIdentification))))
r := api.NewIdentificationChallengeResponseRequest(fe.getAnswer(StageIdentification))
r.SetPassword(fe.getAnswer(StagePassword))
responseReq = responseReq.FlowChallengeResponseRequest(api.IdentificationChallengeResponseRequestAsFlowChallengeResponseRequest(r))
case string(StagePassword):
responseReq = responseReq.FlowChallengeResponseRequest(api.PasswordChallengeResponseRequestAsFlowChallengeResponseRequest(api.NewPasswordChallengeResponseRequest(fe.getAnswer(StagePassword))))
case string(StageAuthenticatorValidate):

View File

@ -0,0 +1,32 @@
package ldap
import (
"net"
"time"
)
func (ls *LDAPServer) Close(boundDN string, conn net.Conn) error {
for _, p := range ls.providers {
p.delayDeleteUserInfo(boundDN)
}
return nil
}
func (pi *ProviderInstance) delayDeleteUserInfo(dn string) {
ticker := time.NewTicker(30 * time.Second)
quit := make(chan struct{})
go func() {
for {
select {
case <-ticker.C:
pi.boundUsersMutex.Lock()
delete(pi.boundUsers, dn)
pi.boundUsersMutex.Unlock()
close(quit)
case <-quit:
ticker.Stop()
return
}
}
}()
}

View File

@ -4,7 +4,6 @@ import (
"context"
"errors"
"strings"
"time"
"github.com/getsentry/sentry-go"
goldap "github.com/go-ldap/ldap/v3"
@ -83,7 +82,6 @@ func (pi *ProviderInstance) Bind(username string, req BindRequest) (ldap.LDAPRes
}
uisp.Finish()
defer pi.boundUsersMutex.Unlock()
pi.delayDeleteUserInfo(username)
return ldap.LDAPResultSuccess, nil
}
@ -100,25 +98,6 @@ func (pi *ProviderInstance) SearchAccessCheck(user api.UserSelf) *string {
return nil
}
func (pi *ProviderInstance) delayDeleteUserInfo(dn string) {
ticker := time.NewTicker(30 * time.Second)
quit := make(chan struct{})
go func() {
for {
select {
case <-ticker.C:
pi.boundUsersMutex.Lock()
delete(pi.boundUsers, dn)
pi.boundUsersMutex.Unlock()
close(quit)
case <-quit:
ticker.Stop()
return
}
}
}()
}
func (pi *ProviderInstance) TimerFlowCacheExpiry() {
fe := outpost.NewFlowExecutor(context.Background(), pi.flowSlug, pi.s.ac.Client.GetConfig(), log.Fields{})
fe.Params.Add("goauthentik.io/outpost/ldap", "true")

View File

@ -83,5 +83,6 @@ func NewServer(ac *ak.APIController) *LDAPServer {
ls.defaultCert = &defaultCert
s.BindFunc("", ls)
s.SearchFunc("", ls)
s.CloseFunc("", ls)
return ls
}

View File

@ -25,6 +25,7 @@ type providerBundle struct {
Host string
endSessionUrl string
Mode *api.ProxyMode
cert *tls.Certificate
@ -38,8 +39,8 @@ func intToPointer(i int) *int {
func (pb *providerBundle) replaceLocal(url string) string {
if strings.HasPrefix(url, "http://localhost:8000") {
authentikHost, c := pb.s.ak.Outpost.Config["authentik_host"]
if !c {
pb.log.Warning("Outpost has localhost API Connection but no authentik_host is configured.")
if !c || authentikHost == "" {
pb.log.Warning("Outpost has localhost/blank API Connection but no authentik_host is configured.")
return url
}
f := strings.ReplaceAll(url, "http://localhost:8000", authentikHost.(string))
@ -49,6 +50,10 @@ func (pb *providerBundle) replaceLocal(url string) string {
}
func (pb *providerBundle) prepareOpts(provider api.ProxyOutpostConfig) *options.Options {
// We need to save the mode in the bundle
// Since for the embedded outpost we only switch for fully proxy providers
pb.Mode = provider.Mode
externalHost, err := url.Parse(provider.ExternalHost)
if err != nil {
log.WithError(err).Warning("Failed to parse URL, skipping provider")

View File

@ -121,7 +121,7 @@ func NewOAuthProxy(opts *options.Options, provider api.ProxyOutpostConfig, c *ht
redirectURL.Path = fmt.Sprintf("%s/callback", opts.ProxyPrefix)
}
logger.Printf("proxy instance configured for Client ID: %s", opts.ClientID)
logger.WithField("auth_url", opts.GetProvider().Data().LoginURL).WithField("client_id", opts.ClientID).Info("proxy instance configured")
sessionChain := buildSessionChain(opts, sessionStore)

View File

@ -6,6 +6,7 @@ import (
"net/http/httputil"
"net/url"
"goauthentik.io/api"
"goauthentik.io/internal/utils/web"
)
@ -36,10 +37,12 @@ func (ws *WebServer) configureProxy() {
ws.m.PathPrefix("/").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
host := web.GetHost(r)
if ws.ProxyServer != nil {
if _, ok := ws.ProxyServer.Handlers[host]; ok {
ws.log.WithField("host", host).Trace("routing to proxy outpost")
ws.ProxyServer.Handler(rw, r)
return
if p, ok := ws.ProxyServer.Handlers[host]; ok {
if *p.Mode == api.PROXYMODE_PROXY {
ws.log.WithField("host", host).Trace("routing to proxy outpost")
ws.ProxyServer.Handler(rw, r)
return
}
}
}
ws.log.WithField("host", host).Trace("routing to application server")

2251
schema.yml

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
"""Helper script to get the actual branch name, docker safe"""
import os
from time import time
env_pr_branch = "SYSTEM_PULLREQUEST_SOURCEBRANCH"
default_branch = "BUILD_SOURCEBRANCHNAME"
branch_name = os.environ[default_branch]
if env_pr_branch in os.environ:
branch_name = os.environ[env_pr_branch].replace("/", "-")
print("##vso[task.setvariable variable=branchName]%s" % branch_name)
print("##vso[task.setvariable variable=timestamp]%s" % int(time()))

7
scripts/ci_prepare.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
docker-compose -f scripts/ci.docker-compose.yml up -d
sudo apt update
sudo apt install -y libxmlsec1-dev pkg-config
sudo pip install -U wheel pipenv
pipenv install --dev
pipenv run python -m scripts.generate_ci_config

View File

@ -0,0 +1,16 @@
"""Helper script to get the actual branch name, docker safe"""
import os
from time import time
env_pr_branch = "GITHUB_HEAD_REF"
default_branch = "GITHUB_REF"
sha = "GITHUB_SHA"
branch_name = os.environ[default_branch]
if os.environ.get(env_pr_branch, "") != "":
branch_name = os.environ[env_pr_branch]
branch_name = branch_name.replace("refs/heads/", "").replace("/", "-")
print("##[set-output name=branchName]%s" % branch_name)
print("##[set-output name=timestamp]%s" % int(time()))
print("##[set-output name=sha]%s" % os.environ[sha])

View File

@ -6,4 +6,3 @@ dist
coverage
# don't lint generated code
api/
azure-pipelines.yml

View File

@ -1,93 +0,0 @@
trigger:
batch: true
branches:
include:
- master
- next
- version-*
stages:
- stage: lint
jobs:
- job: eslint
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '16.x'
displayName: 'Install Node.js'
- task: Npm@1
inputs:
command: 'install'
workingDir: 'web/'
- task: CmdLine@2
inputs:
script: make gen-web
- task: Npm@1
inputs:
command: 'custom'
workingDir: 'web/'
customCommand: 'run lint'
- job: prettier
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '16.x'
displayName: 'Install Node.js'
- task: Npm@1
inputs:
command: 'install'
workingDir: 'web/'
- task: CmdLine@2
inputs:
script: make gen-web
- task: Npm@1
inputs:
command: 'custom'
workingDir: 'web/'
customCommand: 'run prettier-check'
- job: lit_analyse
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '16.x'
displayName: 'Install Node.js'
- task: Npm@1
inputs:
command: 'install'
workingDir: 'web/'
- task: CmdLine@2
inputs:
script: make gen-web
- task: Npm@1
inputs:
command: 'custom'
workingDir: 'web/'
customCommand: 'run lit-analyse'
- stage: build_local
jobs:
- job: build
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '16.x'
displayName: 'Install Node.js'
- task: Npm@1
inputs:
command: 'install'
workingDir: 'web/'
- task: CmdLine@2
inputs:
script: make gen-web
- task: Npm@1
inputs:
command: 'custom'
workingDir: 'web/'
customCommand: 'run build'

334
web/package-lock.json generated
View File

@ -15,23 +15,23 @@
"@babel/preset-env": "^7.15.0",
"@babel/preset-typescript": "^7.15.0",
"@fortawesome/fontawesome-free": "^5.15.4",
"@goauthentik/api": "^2021.8.1-1629986812",
"@goauthentik/api": "^2021.8.3-1630597235",
"@lingui/cli": "^3.10.2",
"@lingui/core": "^3.10.4",
"@lingui/macro": "^3.10.2",
"@patternfly/patternfly": "^4.125.3",
"@patternfly/patternfly": "^4.132.2",
"@polymer/iron-form": "^3.0.1",
"@polymer/paper-input": "^3.2.1",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-replace": "^3.0.0",
"@rollup/plugin-typescript": "^8.2.5",
"@sentry/browser": "^6.11.0",
"@sentry/tracing": "^6.11.0",
"@sentry/browser": "^6.12.0",
"@sentry/tracing": "^6.12.0",
"@types/chart.js": "^2.9.34",
"@types/codemirror": "5.60.2",
"@types/grecaptcha": "^3.0.3",
"@typescript-eslint/eslint-plugin": "^4.29.3",
"@typescript-eslint/parser": "^4.29.3",
"@typescript-eslint/eslint-plugin": "^4.30.0",
"@typescript-eslint/parser": "^4.30.0",
"@webcomponents/webcomponentsjs": "^2.6.0",
"babel-plugin-macros": "^3.1.0",
"base64-js": "^1.5.1",
@ -59,7 +59,7 @@
"rollup-plugin-terser": "^7.0.2",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.3.1",
"typescript": "^4.3.5",
"typescript": "^4.4.2",
"webcomponent-qr-code": "^1.0.5",
"yaml": "^1.10.2"
}
@ -1689,9 +1689,9 @@
}
},
"node_modules/@goauthentik/api": {
"version": "2021.8.1-1629986812",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2021.8.1-1629986812.tgz",
"integrity": "sha512-/wKkUjm6fTDpjhfp0LJlLA6HIFhMt96BdadMIFPRrRl/DWXcIdPzDJMioiteXRWwrRXC0a9fnxEC/xgFcjz7Bg=="
"version": "2021.8.3-1630597235",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2021.8.3-1630597235.tgz",
"integrity": "sha512-W/AWgWE8WS8pWYPqy9JuzbzdYcTJ7aCjzgcLbOmD4roYTp1vP1znSZKx0zg9ZH7EBskFfDqm2eAueF1ktPC09g=="
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.5.0",
@ -2071,9 +2071,9 @@
}
},
"node_modules/@patternfly/patternfly": {
"version": "4.125.3",
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.125.3.tgz",
"integrity": "sha512-B0L3TFdFYsioV1loCsd3s3Y6eNV/9YjHQIlFnxF1KRgj+eVq0idKi1Mnq28eycKQgFi6ld3tEveMSxBsaw3R9A=="
"version": "4.132.2",
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.132.2.tgz",
"integrity": "sha512-66qBgIpwPPeTUMTUUO6Z73XApvNXxn3uFaXMeVa09viYGDKzEX3L1FIfc4VzVk2okhk/9KJIYYgxofeuGi5v6A=="
},
"node_modules/@polymer/font-roboto": {
"version": "3.0.2",
@ -2276,13 +2276,13 @@
}
},
"node_modules/@sentry/browser": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.11.0.tgz",
"integrity": "sha512-Qr2QRA0t5/S9QQqxzYKvM9W8prvmiWuldfwRX4hubovXzcXLgUi4WK0/H612wSbYZ4dNAEcQbtlxFWJNN4wxdg==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.12.0.tgz",
"integrity": "sha512-wsJi1NLOmfwtPNYxEC50dpDcVY7sdYckzwfqz1/zHrede1mtxpqSw+7iP4bHADOJXuF+ObYYTHND0v38GSXznQ==",
"dependencies": {
"@sentry/core": "6.11.0",
"@sentry/types": "6.11.0",
"@sentry/utils": "6.11.0",
"@sentry/core": "6.12.0",
"@sentry/types": "6.12.0",
"@sentry/utils": "6.12.0",
"tslib": "^1.9.3"
},
"engines": {
@ -2295,14 +2295,14 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/core": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.11.0.tgz",
"integrity": "sha512-09TB+f3pqEq8LFahFWHO6I/4DxHo+NcS52OkbWMDqEi6oNZRD7PhPn3i14LfjsYVv3u3AESU8oxSEGbFrr2UjQ==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.12.0.tgz",
"integrity": "sha512-mU/zdjlzFHzdXDZCPZm8OeCw7c9xsbL49Mq0TrY0KJjLt4CJBkiq5SDTGfRsenBLgTedYhe5Z/J8Z+xVVq+MfQ==",
"dependencies": {
"@sentry/hub": "6.11.0",
"@sentry/minimal": "6.11.0",
"@sentry/types": "6.11.0",
"@sentry/utils": "6.11.0",
"@sentry/hub": "6.12.0",
"@sentry/minimal": "6.12.0",
"@sentry/types": "6.12.0",
"@sentry/utils": "6.12.0",
"tslib": "^1.9.3"
},
"engines": {
@ -2315,12 +2315,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/hub": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.11.0.tgz",
"integrity": "sha512-pT9hf+ZJfVFpoZopoC+yJmFNclr4NPqPcl2cgguqCHb69DklD1NxgBNWK8D6X05qjnNFDF991U6t1mxP9HrGuw==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.12.0.tgz",
"integrity": "sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg==",
"dependencies": {
"@sentry/types": "6.11.0",
"@sentry/utils": "6.11.0",
"@sentry/types": "6.12.0",
"@sentry/utils": "6.12.0",
"tslib": "^1.9.3"
},
"engines": {
@ -2333,12 +2333,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/minimal": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.11.0.tgz",
"integrity": "sha512-XkZ7qrdlGp4IM/gjGxf1Q575yIbl5RvPbg+WFeekpo16Ufvzx37Mr8c2xsZaWosISVyE6eyFpooORjUlzy8EDw==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.12.0.tgz",
"integrity": "sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw==",
"dependencies": {
"@sentry/hub": "6.11.0",
"@sentry/types": "6.11.0",
"@sentry/hub": "6.12.0",
"@sentry/types": "6.12.0",
"tslib": "^1.9.3"
},
"engines": {
@ -2351,14 +2351,14 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/tracing": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.11.0.tgz",
"integrity": "sha512-9VA1/SY++WeoMQI4K6n/sYgIdRtCu9NLWqmGqu/5kbOtESYFgAt1DqSyqGCr00ZjQiC2s7tkDkTNZb38K6KytQ==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.12.0.tgz",
"integrity": "sha512-u10QHNknPBzbWSUUNMkvuH53sQd5NaBo6YdNPj4p5b7sE7445Sh0PwBpRbY3ZiUUiwyxV59fx9UQ4yVnPGxZQA==",
"dependencies": {
"@sentry/hub": "6.11.0",
"@sentry/minimal": "6.11.0",
"@sentry/types": "6.11.0",
"@sentry/utils": "6.11.0",
"@sentry/hub": "6.12.0",
"@sentry/minimal": "6.12.0",
"@sentry/types": "6.12.0",
"@sentry/utils": "6.12.0",
"tslib": "^1.9.3"
},
"engines": {
@ -2371,19 +2371,19 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/types": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.11.0.tgz",
"integrity": "sha512-gm5H9eZhL6bsIy/h3T+/Fzzz2vINhHhqd92CjHle3w7uXdTdFV98i2pDpErBGNTSNzbntqOMifYEB5ENtZAvcg==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz",
"integrity": "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA==",
"engines": {
"node": ">=6"
}
},
"node_modules/@sentry/utils": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.11.0.tgz",
"integrity": "sha512-IOvyFHcnbRQxa++jO+ZUzRvFHEJ1cZjrBIQaNVc0IYF0twUOB5PTP6joTcix38ldaLeapaPZ9LGfudbvYvxkdg==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz",
"integrity": "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==",
"dependencies": {
"@sentry/types": "6.11.0",
"@sentry/types": "6.12.0",
"tslib": "^1.9.3"
},
"engines": {
@ -2557,12 +2557,12 @@
"integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw=="
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.3.tgz",
"integrity": "sha512-tBgfA3K/3TsZY46ROGvoRxQr1wBkclbVqRQep97MjVHJzcRBURRY3sNFqLk0/Xr//BY5hM9H2p/kp+6qim85SA==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.30.0.tgz",
"integrity": "sha512-NgAnqk55RQ/SD+tZFD9aPwNSeHmDHHe5rtUyhIq0ZeCWZEvo4DK9rYz7v9HDuQZFvn320Ot+AikaCKMFKLlD0g==",
"dependencies": {
"@typescript-eslint/experimental-utils": "4.29.3",
"@typescript-eslint/scope-manager": "4.29.3",
"@typescript-eslint/experimental-utils": "4.30.0",
"@typescript-eslint/scope-manager": "4.30.0",
"debug": "^4.3.1",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.1.0",
@ -2601,14 +2601,14 @@
}
},
"node_modules/@typescript-eslint/experimental-utils": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.3.tgz",
"integrity": "sha512-ffIvbytTVWz+3keg+Sy94FG1QeOvmV9dP2YSdLFHw/ieLXWCa3U1TYu8IRCOpMv2/SPS8XqhM1+ou1YHsdzKrg==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.30.0.tgz",
"integrity": "sha512-K8RNIX9GnBsv5v4TjtwkKtqMSzYpjqAQg/oSphtxf3xxdt6T0owqnpojztjjTcatSteH3hLj3t/kklKx87NPqw==",
"dependencies": {
"@types/json-schema": "^7.0.7",
"@typescript-eslint/scope-manager": "4.29.3",
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/typescript-estree": "4.29.3",
"@typescript-eslint/scope-manager": "4.30.0",
"@typescript-eslint/types": "4.30.0",
"@typescript-eslint/typescript-estree": "4.30.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
@ -2624,13 +2624,13 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.3.tgz",
"integrity": "sha512-jrHOV5g2u8ROghmspKoW7pN8T/qUzk0+DITun0MELptvngtMrwUJ1tv5zMI04CYVEUsSrN4jV7AKSv+I0y0EfQ==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.30.0.tgz",
"integrity": "sha512-HJ0XuluSZSxeboLU7Q2VQ6eLlCwXPBOGnA7CqgBnz2Db3JRQYyBDJgQnop6TZ+rsbSx5gEdWhw4rE4mDa1FnZg==",
"dependencies": {
"@typescript-eslint/scope-manager": "4.29.3",
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/typescript-estree": "4.29.3",
"@typescript-eslint/scope-manager": "4.30.0",
"@typescript-eslint/types": "4.30.0",
"@typescript-eslint/typescript-estree": "4.30.0",
"debug": "^4.3.1"
},
"engines": {
@ -2650,12 +2650,12 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.3.tgz",
"integrity": "sha512-x+w8BLXO7iWPkG5mEy9bA1iFRnk36p/goVlYobVWHyDw69YmaH9q6eA+Fgl7kYHmFvWlebUTUfhtIg4zbbl8PA==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.30.0.tgz",
"integrity": "sha512-VJ/jAXovxNh7rIXCQbYhkyV2Y3Ac/0cVHP/FruTJSAUUm4Oacmn/nkN5zfWmWFEanN4ggP0vJSHOeajtHq3f8A==",
"dependencies": {
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/visitor-keys": "4.29.3"
"@typescript-eslint/types": "4.30.0",
"@typescript-eslint/visitor-keys": "4.30.0"
},
"engines": {
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
@ -2666,9 +2666,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.3.tgz",
"integrity": "sha512-s1eV1lKNgoIYLAl1JUba8NhULmf+jOmmeFO1G5MN/RBCyyzg4TIOfIOICVNC06lor+Xmy4FypIIhFiJXOknhIg==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.30.0.tgz",
"integrity": "sha512-YKldqbNU9K4WpTNwBqtAerQKLLW/X2A/j4yw92e3ZJYLx+BpKLeheyzoPfzIXHfM8BXfoleTdiYwpsvVPvHrDw==",
"engines": {
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
},
@ -2678,12 +2678,12 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.3.tgz",
"integrity": "sha512-45oQJA0bxna4O5TMwz55/TpgjX1YrAPOI/rb6kPgmdnemRZx/dB0rsx+Ku8jpDvqTxcE1C/qEbVHbS3h0hflag==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.30.0.tgz",
"integrity": "sha512-6WN7UFYvykr/U0Qgy4kz48iGPWILvYL34xXJxvDQeiRE018B7POspNRVtAZscWntEPZpFCx4hcz/XBT+erenfg==",
"dependencies": {
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/visitor-keys": "4.29.3",
"@typescript-eslint/types": "4.30.0",
"@typescript-eslint/visitor-keys": "4.30.0",
"debug": "^4.3.1",
"globby": "^11.0.3",
"is-glob": "^4.0.1",
@ -2718,11 +2718,11 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.3.tgz",
"integrity": "sha512-MGGfJvXT4asUTeVs0Q2m+sY63UsfnA+C/FDgBKV3itLBmM9H0u+URcneePtkd0at1YELmZK6HSolCqM4Fzs6yA==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.30.0.tgz",
"integrity": "sha512-pNaaxDt/Ol/+JZwzP7MqWc8PJQTUhZwoee/PVlQ+iYoYhagccvoHnC9e4l+C/krQYYkENxznhVSDwClIbZVxRw==",
"dependencies": {
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/types": "4.30.0",
"eslint-visitor-keys": "^2.0.0"
},
"engines": {
@ -8021,9 +8021,9 @@
}
},
"node_modules/typescript": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz",
"integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -9566,9 +9566,9 @@
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg=="
},
"@goauthentik/api": {
"version": "2021.8.1-1629986812",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2021.8.1-1629986812.tgz",
"integrity": "sha512-/wKkUjm6fTDpjhfp0LJlLA6HIFhMt96BdadMIFPRrRl/DWXcIdPzDJMioiteXRWwrRXC0a9fnxEC/xgFcjz7Bg=="
"version": "2021.8.3-1630597235",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2021.8.3-1630597235.tgz",
"integrity": "sha512-W/AWgWE8WS8pWYPqy9JuzbzdYcTJ7aCjzgcLbOmD4roYTp1vP1znSZKx0zg9ZH7EBskFfDqm2eAueF1ktPC09g=="
},
"@humanwhocodes/config-array": {
"version": "0.5.0",
@ -9847,9 +9847,9 @@
}
},
"@patternfly/patternfly": {
"version": "4.125.3",
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.125.3.tgz",
"integrity": "sha512-B0L3TFdFYsioV1loCsd3s3Y6eNV/9YjHQIlFnxF1KRgj+eVq0idKi1Mnq28eycKQgFi6ld3tEveMSxBsaw3R9A=="
"version": "4.132.2",
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.132.2.tgz",
"integrity": "sha512-66qBgIpwPPeTUMTUUO6Z73XApvNXxn3uFaXMeVa09viYGDKzEX3L1FIfc4VzVk2okhk/9KJIYYgxofeuGi5v6A=="
},
"@polymer/font-roboto": {
"version": "3.0.2",
@ -10022,13 +10022,13 @@
}
},
"@sentry/browser": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.11.0.tgz",
"integrity": "sha512-Qr2QRA0t5/S9QQqxzYKvM9W8prvmiWuldfwRX4hubovXzcXLgUi4WK0/H612wSbYZ4dNAEcQbtlxFWJNN4wxdg==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.12.0.tgz",
"integrity": "sha512-wsJi1NLOmfwtPNYxEC50dpDcVY7sdYckzwfqz1/zHrede1mtxpqSw+7iP4bHADOJXuF+ObYYTHND0v38GSXznQ==",
"requires": {
"@sentry/core": "6.11.0",
"@sentry/types": "6.11.0",
"@sentry/utils": "6.11.0",
"@sentry/core": "6.12.0",
"@sentry/types": "6.12.0",
"@sentry/utils": "6.12.0",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10040,14 +10040,14 @@
}
},
"@sentry/core": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.11.0.tgz",
"integrity": "sha512-09TB+f3pqEq8LFahFWHO6I/4DxHo+NcS52OkbWMDqEi6oNZRD7PhPn3i14LfjsYVv3u3AESU8oxSEGbFrr2UjQ==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.12.0.tgz",
"integrity": "sha512-mU/zdjlzFHzdXDZCPZm8OeCw7c9xsbL49Mq0TrY0KJjLt4CJBkiq5SDTGfRsenBLgTedYhe5Z/J8Z+xVVq+MfQ==",
"requires": {
"@sentry/hub": "6.11.0",
"@sentry/minimal": "6.11.0",
"@sentry/types": "6.11.0",
"@sentry/utils": "6.11.0",
"@sentry/hub": "6.12.0",
"@sentry/minimal": "6.12.0",
"@sentry/types": "6.12.0",
"@sentry/utils": "6.12.0",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10059,12 +10059,12 @@
}
},
"@sentry/hub": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.11.0.tgz",
"integrity": "sha512-pT9hf+ZJfVFpoZopoC+yJmFNclr4NPqPcl2cgguqCHb69DklD1NxgBNWK8D6X05qjnNFDF991U6t1mxP9HrGuw==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.12.0.tgz",
"integrity": "sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg==",
"requires": {
"@sentry/types": "6.11.0",
"@sentry/utils": "6.11.0",
"@sentry/types": "6.12.0",
"@sentry/utils": "6.12.0",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10076,12 +10076,12 @@
}
},
"@sentry/minimal": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.11.0.tgz",
"integrity": "sha512-XkZ7qrdlGp4IM/gjGxf1Q575yIbl5RvPbg+WFeekpo16Ufvzx37Mr8c2xsZaWosISVyE6eyFpooORjUlzy8EDw==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.12.0.tgz",
"integrity": "sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw==",
"requires": {
"@sentry/hub": "6.11.0",
"@sentry/types": "6.11.0",
"@sentry/hub": "6.12.0",
"@sentry/types": "6.12.0",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10093,14 +10093,14 @@
}
},
"@sentry/tracing": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.11.0.tgz",
"integrity": "sha512-9VA1/SY++WeoMQI4K6n/sYgIdRtCu9NLWqmGqu/5kbOtESYFgAt1DqSyqGCr00ZjQiC2s7tkDkTNZb38K6KytQ==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.12.0.tgz",
"integrity": "sha512-u10QHNknPBzbWSUUNMkvuH53sQd5NaBo6YdNPj4p5b7sE7445Sh0PwBpRbY3ZiUUiwyxV59fx9UQ4yVnPGxZQA==",
"requires": {
"@sentry/hub": "6.11.0",
"@sentry/minimal": "6.11.0",
"@sentry/types": "6.11.0",
"@sentry/utils": "6.11.0",
"@sentry/hub": "6.12.0",
"@sentry/minimal": "6.12.0",
"@sentry/types": "6.12.0",
"@sentry/utils": "6.12.0",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10112,16 +10112,16 @@
}
},
"@sentry/types": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.11.0.tgz",
"integrity": "sha512-gm5H9eZhL6bsIy/h3T+/Fzzz2vINhHhqd92CjHle3w7uXdTdFV98i2pDpErBGNTSNzbntqOMifYEB5ENtZAvcg=="
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz",
"integrity": "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA=="
},
"@sentry/utils": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.11.0.tgz",
"integrity": "sha512-IOvyFHcnbRQxa++jO+ZUzRvFHEJ1cZjrBIQaNVc0IYF0twUOB5PTP6joTcix38ldaLeapaPZ9LGfudbvYvxkdg==",
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz",
"integrity": "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==",
"requires": {
"@sentry/types": "6.11.0",
"@sentry/types": "6.12.0",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10292,12 +10292,12 @@
"integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw=="
},
"@typescript-eslint/eslint-plugin": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.3.tgz",
"integrity": "sha512-tBgfA3K/3TsZY46ROGvoRxQr1wBkclbVqRQep97MjVHJzcRBURRY3sNFqLk0/Xr//BY5hM9H2p/kp+6qim85SA==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.30.0.tgz",
"integrity": "sha512-NgAnqk55RQ/SD+tZFD9aPwNSeHmDHHe5rtUyhIq0ZeCWZEvo4DK9rYz7v9HDuQZFvn320Ot+AikaCKMFKLlD0g==",
"requires": {
"@typescript-eslint/experimental-utils": "4.29.3",
"@typescript-eslint/scope-manager": "4.29.3",
"@typescript-eslint/experimental-utils": "4.30.0",
"@typescript-eslint/scope-manager": "4.30.0",
"debug": "^4.3.1",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.1.0",
@ -10316,50 +10316,50 @@
}
},
"@typescript-eslint/experimental-utils": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.3.tgz",
"integrity": "sha512-ffIvbytTVWz+3keg+Sy94FG1QeOvmV9dP2YSdLFHw/ieLXWCa3U1TYu8IRCOpMv2/SPS8XqhM1+ou1YHsdzKrg==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.30.0.tgz",
"integrity": "sha512-K8RNIX9GnBsv5v4TjtwkKtqMSzYpjqAQg/oSphtxf3xxdt6T0owqnpojztjjTcatSteH3hLj3t/kklKx87NPqw==",
"requires": {
"@types/json-schema": "^7.0.7",
"@typescript-eslint/scope-manager": "4.29.3",
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/typescript-estree": "4.29.3",
"@typescript-eslint/scope-manager": "4.30.0",
"@typescript-eslint/types": "4.30.0",
"@typescript-eslint/typescript-estree": "4.30.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
}
},
"@typescript-eslint/parser": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.3.tgz",
"integrity": "sha512-jrHOV5g2u8ROghmspKoW7pN8T/qUzk0+DITun0MELptvngtMrwUJ1tv5zMI04CYVEUsSrN4jV7AKSv+I0y0EfQ==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.30.0.tgz",
"integrity": "sha512-HJ0XuluSZSxeboLU7Q2VQ6eLlCwXPBOGnA7CqgBnz2Db3JRQYyBDJgQnop6TZ+rsbSx5gEdWhw4rE4mDa1FnZg==",
"requires": {
"@typescript-eslint/scope-manager": "4.29.3",
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/typescript-estree": "4.29.3",
"@typescript-eslint/scope-manager": "4.30.0",
"@typescript-eslint/types": "4.30.0",
"@typescript-eslint/typescript-estree": "4.30.0",
"debug": "^4.3.1"
}
},
"@typescript-eslint/scope-manager": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.3.tgz",
"integrity": "sha512-x+w8BLXO7iWPkG5mEy9bA1iFRnk36p/goVlYobVWHyDw69YmaH9q6eA+Fgl7kYHmFvWlebUTUfhtIg4zbbl8PA==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.30.0.tgz",
"integrity": "sha512-VJ/jAXovxNh7rIXCQbYhkyV2Y3Ac/0cVHP/FruTJSAUUm4Oacmn/nkN5zfWmWFEanN4ggP0vJSHOeajtHq3f8A==",
"requires": {
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/visitor-keys": "4.29.3"
"@typescript-eslint/types": "4.30.0",
"@typescript-eslint/visitor-keys": "4.30.0"
}
},
"@typescript-eslint/types": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.3.tgz",
"integrity": "sha512-s1eV1lKNgoIYLAl1JUba8NhULmf+jOmmeFO1G5MN/RBCyyzg4TIOfIOICVNC06lor+Xmy4FypIIhFiJXOknhIg=="
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.30.0.tgz",
"integrity": "sha512-YKldqbNU9K4WpTNwBqtAerQKLLW/X2A/j4yw92e3ZJYLx+BpKLeheyzoPfzIXHfM8BXfoleTdiYwpsvVPvHrDw=="
},
"@typescript-eslint/typescript-estree": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.3.tgz",
"integrity": "sha512-45oQJA0bxna4O5TMwz55/TpgjX1YrAPOI/rb6kPgmdnemRZx/dB0rsx+Ku8jpDvqTxcE1C/qEbVHbS3h0hflag==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.30.0.tgz",
"integrity": "sha512-6WN7UFYvykr/U0Qgy4kz48iGPWILvYL34xXJxvDQeiRE018B7POspNRVtAZscWntEPZpFCx4hcz/XBT+erenfg==",
"requires": {
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/visitor-keys": "4.29.3",
"@typescript-eslint/types": "4.30.0",
"@typescript-eslint/visitor-keys": "4.30.0",
"debug": "^4.3.1",
"globby": "^11.0.3",
"is-glob": "^4.0.1",
@ -10378,11 +10378,11 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "4.29.3",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.3.tgz",
"integrity": "sha512-MGGfJvXT4asUTeVs0Q2m+sY63UsfnA+C/FDgBKV3itLBmM9H0u+URcneePtkd0at1YELmZK6HSolCqM4Fzs6yA==",
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.30.0.tgz",
"integrity": "sha512-pNaaxDt/Ol/+JZwzP7MqWc8PJQTUhZwoee/PVlQ+iYoYhagccvoHnC9e4l+C/krQYYkENxznhVSDwClIbZVxRw==",
"requires": {
"@typescript-eslint/types": "4.29.3",
"@typescript-eslint/types": "4.30.0",
"eslint-visitor-keys": "^2.0.0"
}
},
@ -14339,9 +14339,9 @@
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="
},
"typescript": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA=="
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz",
"integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ=="
},
"uglify-js": {
"version": "3.14.1",

View File

@ -46,23 +46,23 @@
"@babel/preset-env": "^7.15.0",
"@babel/preset-typescript": "^7.15.0",
"@fortawesome/fontawesome-free": "^5.15.4",
"@goauthentik/api": "^2021.8.1-1629986812",
"@goauthentik/api": "^2021.8.3-1630597235",
"@lingui/cli": "^3.10.2",
"@lingui/core": "^3.10.4",
"@lingui/macro": "^3.10.2",
"@patternfly/patternfly": "^4.125.3",
"@patternfly/patternfly": "^4.132.2",
"@polymer/iron-form": "^3.0.1",
"@polymer/paper-input": "^3.2.1",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-replace": "^3.0.0",
"@rollup/plugin-typescript": "^8.2.5",
"@sentry/browser": "^6.11.0",
"@sentry/tracing": "^6.11.0",
"@sentry/browser": "^6.12.0",
"@sentry/tracing": "^6.12.0",
"@types/chart.js": "^2.9.34",
"@types/codemirror": "5.60.2",
"@types/grecaptcha": "^3.0.3",
"@typescript-eslint/eslint-plugin": "^4.29.3",
"@typescript-eslint/parser": "^4.29.3",
"@typescript-eslint/eslint-plugin": "^4.30.0",
"@typescript-eslint/parser": "^4.30.0",
"@webcomponents/webcomponentsjs": "^2.6.0",
"babel-plugin-macros": "^3.1.0",
"base64-js": "^1.5.1",
@ -90,7 +90,7 @@
"rollup-plugin-terser": "^7.0.2",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.3.1",
"typescript": "^4.3.5",
"typescript": "^4.4.2",
"webcomponent-qr-code": "^1.0.5",
"yaml": "^1.10.2"
}

View File

@ -2,6 +2,7 @@ import { Config, Configuration, CoreApi, CurrentTenant, Middleware, ResponseCont
import { getCookie } from "../utils";
import { APIMiddleware } from "../elements/notifications/APIDrawer";
import { MessageMiddleware } from "../elements/messages/Middleware";
import { VERSION } from "../constants";
export class LoggingMiddleware implements Middleware {
@ -49,7 +50,7 @@ export function tenant(): Promise<CurrentTenant> {
}
export const DEFAULT_CONFIG = new Configuration({
basePath: "",
basePath: "/api/v3",
headers: {
"X-CSRFToken": getCookie("authentik_csrf"),
},
@ -59,3 +60,5 @@ export const DEFAULT_CONFIG = new Configuration({
new LoggingMiddleware(),
],
});
console.debug(`authentik(early): version ${VERSION}`);

View File

@ -15,7 +15,7 @@ export function configureSentry(canDoPpi: boolean = false): Promise<Config> {
Sentry.init({
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
release: `authentik@${VERSION}`,
tunnel: "/api/v2beta/sentry/",
tunnel: "/api/v3/sentry/",
integrations: [
new Integrations.BrowserTracing({
tracingOrigins: [window.location.host, "localhost"],

View File

@ -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.8.2";
export const VERSION = "2021.8.4";
export const PAGE_SIZE = 20;
export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";";

View File

@ -224,9 +224,15 @@ export class Form<T> extends LitElement {
throw ex;
})
.catch((ex: Error) => {
let msg = ex.toString();
// Only change the message when we have `detail`.
// Everything else is handled in the form.
if (ex instanceof APIError && "detail" in ex.response) {
msg = ex.response.detail;
}
// error is local or not from rest_framework
showMessage({
message: ex.toString(),
message: msg,
level: MessageLevel.error,
});
// rethrow the error so the form doesn't close

View File

@ -55,8 +55,34 @@ import { WebsocketClient } from "../common/ws";
export class FlowExecutor extends LitElement implements StageHost {
flowSlug: string;
private _challenge?: ChallengeTypes;
@property({ attribute: false })
challenge?: ChallengeTypes;
set challenge(value: ChallengeTypes | undefined) {
this._challenge = value;
// Assign the location as soon as we get the challenge and *not* in the render function
// as the render function might be called multiple times, which will navigate multiple
// times and can invalidate oauth codes
if (value?.type === ChallengeChoices.Redirect) {
console.debug(
"authentik/flows: redirecting to url from server",
(value as RedirectChallenge).to,
);
window.location.assign((value as RedirectChallenge).to);
}
tenant().then((tenant) => {
if (value?.flowInfo?.title) {
document.title = `${value.flowInfo?.title} - ${tenant.brandingTitle}`;
} else {
document.title = tenant.brandingTitle || TITLE_DEFAULT;
}
});
this.requestUpdate();
}
get challenge(): ChallengeTypes | undefined {
return this._challenge;
}
@property({ type: Boolean })
loading = false;
@ -95,16 +121,6 @@ export class FlowExecutor extends LitElement implements StageHost {
});
}
private postUpdate(): void {
tenant().then((tenant) => {
if (this.challenge?.flowInfo?.title) {
document.title = `${this.challenge.flowInfo?.title} - ${tenant.brandingTitle}`;
} else {
document.title = tenant.brandingTitle || TITLE_DEFAULT;
}
});
}
submit(payload?: FlowChallengeResponseRequest): Promise<void> {
if (!payload) return Promise.reject();
if (!this.challenge) return Promise.reject();
@ -119,7 +135,6 @@ export class FlowExecutor extends LitElement implements StageHost {
})
.then((data) => {
this.challenge = data;
this.postUpdate();
})
.catch((e: Error | Response) => {
this.errorMessage(e);
@ -144,7 +159,6 @@ export class FlowExecutor extends LitElement implements StageHost {
if (this.challenge?.flowInfo?.background) {
this.setBackground(this.challenge.flowInfo.background);
}
this.postUpdate();
})
.catch((e: Error | Response) => {
// Catch JSON or Update errors
@ -189,11 +203,6 @@ export class FlowExecutor extends LitElement implements StageHost {
}
switch (this.challenge.type) {
case ChallengeChoices.Redirect:
console.debug(
"authentik/flows: redirecting to url from server",
(this.challenge as RedirectChallenge).to,
);
window.location.assign((this.challenge as RedirectChallenge).to);
return html`<ak-empty-state ?loading=${true} header=${t`Loading`}>
</ak-empty-state>`;
case ChallengeChoices.Shell:

View File

@ -180,7 +180,7 @@ export class AuthenticatorValidateStage
${this.selectedDeviceChallenge
? ""
: html`<p class="pf-c-login__main-header-desc">
${t`Select an identification method.`}
${t`Select an authentication method.`}
</p>`}
</header>
${this.selectedDeviceChallenge

View File

@ -64,13 +64,6 @@ export class PromptStage extends BaseStage<PromptChallenge, PromptChallengeRespo
placeholder="${prompt.placeholder}"
class="pf-c-form-control"
?required=${prompt.required}>`;
case "checkbox":
return `<input
type="checkbox"
name="${prompt.fieldKey}"
placeholder="${prompt.placeholder}"
class="pf-c-form-control"
?required=${prompt.required}>`;
case "date":
return `<input
type="date"
@ -115,6 +108,22 @@ export class PromptStage extends BaseStage<PromptChallenge, PromptChallengeRespo
}}
>
${this.challenge.fields.map((prompt) => {
// Checkbox is rendered differently
if (prompt.type === "checkbox") {
return html`<div class="pf-c-check">
<input
type="checkbox"
class="pf-c-check__input"
name="${prompt.fieldKey}"
?checked=${prompt.placeholder !== ""}
?required=${prompt.required}
/>
<label class="pf-c-check__label">${prompt.label}</label>
${prompt.required
? html`<p class="pf-c-form__helper-text">${t`Required.`}</p>`
: html``}
</div>`;
}
// Special types that aren't rendered in a wrapper
if (
prompt.type === "static" ||

View File

@ -3370,6 +3370,10 @@ msgstr "Request token URL"
msgid "Required"
msgstr "Required"
#: src/flows/stages/prompt/PromptStage.ts
msgid "Required."
msgstr "Required."
#: src/pages/user-settings/UserSelfForm.ts
#: src/pages/users/ServiceAccountForm.ts
#: src/pages/users/UserForm.ts
@ -3524,13 +3528,17 @@ msgstr "Select a provider that this application should use. Alternatively, creat
msgid "Select all rows"
msgstr "Select all rows"
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
msgid "Select an authentication method."
msgstr "Select an authentication method."
#: src/pages/stages/invitation/InvitationListLink.ts
msgid "Select an enrollment flow"
msgstr "Select an enrollment flow"
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
msgid "Select an identification method."
msgstr "Select an identification method."
#:
#~ msgid "Select an identification method."
#~ msgstr "Select an identification method."
#: src/pages/users/GroupSelectModal.ts
msgid "Select groups to add user to"
@ -3757,9 +3765,13 @@ msgstr "Source(s)"
msgid "Sources"
msgstr "Sources"
#:
#~ msgid "Sources of identities, which can either be synced into authentik's database, like LDAP, or can be used by users to authenticate and enroll themselves, like OAuth and social logins"
#~ msgstr "Sources of identities, which can either be synced into authentik's database, like LDAP, or can be used by users to authenticate and enroll themselves, like OAuth and social logins"
#: src/pages/sources/SourcesListPage.ts
msgid "Sources of identities, which can either be synced into authentik's database, like LDAP, or can be used by users to authenticate and enroll themselves, like OAuth and social logins"
msgstr "Sources of identities, which can either be synced into authentik's database, like LDAP, or can be used by users to authenticate and enroll themselves, like OAuth and social logins"
msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves."
msgstr "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves."
#: src/pages/flows/BoundStagesList.ts
#: src/pages/flows/StageBindingForm.ts

View File

@ -3362,6 +3362,10 @@ msgstr ""
msgid "Required"
msgstr ""
#: src/flows/stages/prompt/PromptStage.ts
msgid "Required."
msgstr ""
#: src/pages/user-settings/UserSelfForm.ts
#: src/pages/users/ServiceAccountForm.ts
#: src/pages/users/UserForm.ts
@ -3516,13 +3520,17 @@ msgstr ""
msgid "Select all rows"
msgstr ""
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
msgid "Select an authentication method."
msgstr ""
#: src/pages/stages/invitation/InvitationListLink.ts
msgid "Select an enrollment flow"
msgstr ""
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
msgid "Select an identification method."
msgstr ""
#:
#~ msgid "Select an identification method."
#~ msgstr ""
#: src/pages/users/GroupSelectModal.ts
msgid "Select groups to add user to"
@ -3749,8 +3757,12 @@ msgstr ""
msgid "Sources"
msgstr ""
#:
#~ msgid "Sources of identities, which can either be synced into authentik's database, like LDAP, or can be used by users to authenticate and enroll themselves, like OAuth and social logins"
#~ msgstr ""
#: src/pages/sources/SourcesListPage.ts
msgid "Sources of identities, which can either be synced into authentik's database, like LDAP, or can be used by users to authenticate and enroll themselves, like OAuth and social logins"
msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves."
msgstr ""
#: src/pages/flows/BoundStagesList.ts

View File

@ -32,7 +32,6 @@ export class SystemStatusCard extends AdminStatusCard<System> {
});
}
const timeDiff = value.serverTime.getTime() - (this.now || new Date()).getTime();
console.log(`authentik/: timediff ${timeDiff}`);
if (timeDiff > 5000 || timeDiff < -5000) {
this.header = t`Warning`;
return Promise.resolve<AdminStatus>({

View File

@ -243,7 +243,7 @@ export class FlowForm extends ModelForm<Flow, string> {
<input
type="checkbox"
class="pf-c-check__input"
?checked=${first(this.instance?.compatibilityMode, true)}
?checked=${first(this.instance?.compatibilityMode, false)}
/>
<label class="pf-c-check__label"> ${t`Compatibility mode`} </label>
</div>

View File

@ -101,9 +101,7 @@ export class FlowListPage extends TablePage<Flow> {
slug: item.slug,
})
.then((link) => {
window.location.assign(
`${link.link}?next=/%23${window.location.href}`,
);
window.open(`${link.link}?next=/%23${window.location.href}`);
});
}}
>

View File

@ -25,7 +25,7 @@ export class SourceListPage extends TablePage<Source> {
return t`Sources`;
}
pageDescription(): string | undefined {
return t`Sources of identities, which can either be synced into authentik's database, like LDAP, or can be used by users to authenticate and enroll themselves, like OAuth and social logins`;
return t`Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves.`;
}
pageIcon(): string {
return "pf-icon pf-icon-middleware";

View File

@ -48,6 +48,9 @@ export class InvitationListLink extends LitElement {
designation: FlowsInstancesListDesignationEnum.Enrollment,
})
.then((flows) => {
if (!this.selectedFlow && flows.results.length > 0) {
this.selectedFlow = flows.results[0].slug;
}
return flows.results.map((flow) => {
return html`<option
value=${flow.slug}

View File

@ -157,7 +157,7 @@ export class PromptForm extends ModelForm<Prompt, string> {
<ak-form-element-horizontal label=${t`Order`} ?required=${true} name="order">
<input
type="number"
value="${ifDefined(this.instance?.order)}"
value="${first(this.instance?.order, 0)}"
class="pf-c-form-control"
required
/>

View File

@ -103,7 +103,7 @@ export class TokenListPage extends TablePage<Token> {
row(item: Token): TemplateResult[] {
return [
html`${item.identifier}`,
html`${item.userObj?.username}`,
html`<a href="#/identity/users/${item.userObj?.pk}">${item.userObj?.username}</a>`,
html`${item.expiring ? t`Yes` : t`No`}`,
html`${item.expiring ? item.expires?.toLocaleString() : "-"}`,
html`${IntentToLabel(item.intent || IntentEnum.Api)}`,

View File

@ -51,10 +51,14 @@ export class UserSettingsAuthenticatorWebAuthn extends BaseUserSettings {
slot="form"
successMessage=${t`Successfully updated device.`}
.send=${(data: unknown) => {
return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsWebauthnUpdate({
id: device.pk || 0,
webAuthnDeviceRequest: data as WebAuthnDevice,
});
return new AuthenticatorsApi(DEFAULT_CONFIG)
.authenticatorsWebauthnUpdate({
id: device.pk || 0,
webAuthnDeviceRequest: data as WebAuthnDevice,
})
.then(() => {
this.requestUpdate();
});
}}
>
<form class="pf-c-form pf-m-horizontal">

View File

@ -2,9 +2,9 @@
title: API
---
Starting with 2021.3.5, every authentik instance has a built-in API browser, which can be accessed at https://authentik.company/api/v2beta/.
Starting with 2021.3.5, every authentik instance has a built-in API browser, which can be accessed at https://authentik.company/api/v3/.
To generate an API client, you can use the OpenAPI v3 schema at https://authentik.company/api/v2beta/schema/.
To generate an API client, you can use the OpenAPI v3 schema at https://authentik.company/api/v3/schema/.
While testing, the API requests are authenticated by your browser session.

View File

@ -10,13 +10,13 @@ However, any flow can be executed via an API from anywhere, in fact that is what
Because the flow executor stores its state in the HTTP Session, so you need to ensure cookies between flow executor requests are persisted.
:::
The main endpoint for flow execution is `/api/v2beta/flows/executor/:slug`.
The main endpoint for flow execution is `/api/v3/flows/executor/:slug`.
This endpoint accepts a query parameter called `query`, in which the flow executor sends the full Query-string.
To initiate a new flow, execute a GET request.
## `GET /api/v2beta/flows/executor/test-flow/`
## `GET /api/v3/flows/executor/test-flow/`
Below is the response, for example for an Identification stage.
@ -45,7 +45,7 @@ Below is the response, for example for an Identification stage.
To respond to this challenge, send a response:
## `POST /api/v2beta/flows/executor/test-flow/`
## `POST /api/v3/flows/executor/test-flow/`
With this body
@ -63,7 +63,7 @@ Depending on the flow, you'll either get a 200 Response with another challenge,
Depending also on the stage, a response might take longer to be returned (especially with the Duo Authenticator validation).
To see the data layout for every stage possible, see the [API Browser](https://goauthentik.io/api/#get-/api/v2beta/flows/executor/-flow_slug-/)
To see the data layout for every stage possible, see the [API Browser](https://goauthentik.io/api/#get-/api/v3/flows/executor/-flow_slug-/)
## Result

Some files were not shown because too many files have changed in this diff Show More