Compare commits

..

473 Commits

Author SHA1 Message Date
8543e140ef stages/consent: fix error when requests with identical empty permissions
closes #3280

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-08-01 20:58:25 +02:00
e2cf578afd root: use updated schema
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-08-01 10:11:06 +02:00
0ce9fd9b2e web: fix updates
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-08-01 09:59:57 +02:00
d17ad65435 web: bump api client to match
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-31 23:54:29 +02:00
01529d3894 flows/stages/consent: fix for post requests (#3339)
add unique token to consent stage to ensure it is shown

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-31 23:53:06 +02:00
dae6493a3e release: 2022.7.3 2022-07-20 09:37:43 +02:00
ad07984158 website/docs: prepare 2022.7.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-19 21:40:56 +02:00
f909b86338 stages/consent: fix permimssions for consent API (allow owner to delete) 2022-07-19 16:41:34 +00:00
327df6529b sources/oauth: use oidc preferred_username if set, otherwise nickname 2022-07-19 16:41:10 +00:00
658dc63c4c lifecycle: revert waiting for lock, launch managed reconcile on app import
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-19 12:06:57 +02:00
4edec5f666 lifecycle: connect to database first
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-19 10:54:56 +02:00
d150a0c135 web: bump @typescript-eslint/eslint-plugin from 5.30.6 to 5.30.7 in /web (#3278) 2022-07-19 08:48:26 +02:00
d4242781a0 web: bump @babel/plugin-transform-runtime from 7.18.6 to 7.18.9 in /web (#3277) 2022-07-19 08:48:09 +02:00
7369ca0b25 web: bump @babel/plugin-proposal-decorators from 7.18.6 to 7.18.9 in /web (#3273) 2022-07-19 08:46:24 +02:00
561f427cc5 web: bump @typescript-eslint/parser from 5.30.6 to 5.30.7 in /web (#3274) 2022-07-19 08:46:14 +02:00
8049ab703a web: bump @trivago/prettier-plugin-sort-imports from 3.2.0 to 3.3.0 in /web (#3275) 2022-07-19 08:46:02 +02:00
9c2a97263a web: bump @babel/core from 7.18.6 to 7.18.9 in /web (#3276) 2022-07-19 08:45:35 +02:00
345504c1a4 web: bump @babel/preset-env from 7.18.6 to 7.18.9 in /web (#3279) 2022-07-19 08:45:00 +02:00
549f6f2077 providers/oauth2: correctly log authenticated user for OAuth views using protected_resource_view
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-18 22:20:09 +02:00
35c6decc75 web: bump @sentry/tracing from 7.6.0 to 7.7.0 in /web (#3266)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 7.6.0 to 7.7.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/7.6.0...7.7.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>
2022-07-18 10:49:46 +02:00
b3abeb78ff website: bump react-toggle from 4.1.2 to 4.1.3 in /website (#3263)
Bumps [react-toggle](https://github.com/aaronshaf/react-toggle) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/aaronshaf/react-toggle/releases)
- [Changelog](https://github.com/aaronshaf/react-toggle/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aaronshaf/react-toggle/commits)

---
updated-dependencies:
- dependency-name: react-toggle
  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>
2022-07-18 10:48:59 +02:00
0562a1ad42 web: bump @sentry/browser from 7.6.0 to 7.7.0 in /web (#3264)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 7.6.0 to 7.7.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/7.6.0...7.7.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  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>
2022-07-18 10:48:50 +02:00
febb0920fd web: bump rollup from 2.76.0 to 2.77.0 in /web (#3265)
Bumps [rollup](https://github.com/rollup/rollup) from 2.76.0 to 2.77.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.76.0...v2.77.0)

---
updated-dependencies:
- dependency-name: rollup
  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>
2022-07-18 10:48:40 +02:00
549662beb0 web: bump eslint from 8.19.0 to 8.20.0 in /web (#3267)
Bumps [eslint](https://github.com/eslint/eslint) from 8.19.0 to 8.20.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.19.0...v8.20.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2022-07-18 10:48:28 +02:00
1ea4440c5d core: bump sentry-sdk from 1.7.1 to 1.7.2 (#3268)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.7.1 to 1.7.2.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.7.1...1.7.2)

---
updated-dependencies:
- dependency-name: sentry-sdk
  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>
2022-07-18 10:48:19 +02:00
787abdff5b core: bump pylint from 2.14.4 to 2.14.5 (#3269)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.14.4 to 2.14.5.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.14.4...v2.14.5)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  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>
2022-07-18 09:29:57 +02:00
2237807241 core: bump github.com/go-openapi/strfmt from 0.21.2 to 0.21.3 (#3270)
Bumps [github.com/go-openapi/strfmt](https://github.com/go-openapi/strfmt) from 0.21.2 to 0.21.3.
- [Release notes](https://github.com/go-openapi/strfmt/releases)
- [Commits](https://github.com/go-openapi/strfmt/compare/v0.21.2...v0.21.3)

---
updated-dependencies:
- dependency-name: github.com/go-openapi/strfmt
  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>
2022-07-18 09:29:43 +02:00
e9d9d658c4 lifecycle: make worker wait for migrations to be done (#3254)
* lifecycle: make worker wait for migrations to be done

* retry managed reconcile task
2022-07-15 19:44:45 +02:00
e704092d19 website: bump @docusaurus/plugin-client-redirects from 2.0.0-beta.22 to 2.0.0-rc.1 in /website (#3260)
website: bump @docusaurus/plugin-client-redirects in /website

Bumps [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) from 2.0.0-beta.22 to 2.0.0-rc.1.
- [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-rc.1/packages/docusaurus-plugin-client-redirects)

---
updated-dependencies:
- dependency-name: "@docusaurus/plugin-client-redirects"
  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>
2022-07-15 09:16:08 +02:00
305f72c197 website: bump @docusaurus/preset-classic from 2.0.0-beta.22 to 2.0.0-rc.1 in /website (#3259) 2022-07-15 09:01:28 +02:00
fb6b6b4476 ci: bump actions/setup-node from 3.4.0 to 3.4.1 (#3261) 2022-07-15 09:00:44 +02:00
791cc74dbb core: bump golang from 1.18.3-bullseye to 1.18.4-bullseye (#3255)
Bumps golang from 1.18.3-bullseye to 1.18.4-bullseye.

---
updated-dependencies:
- dependency-name: golang
  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>
2022-07-14 10:17:48 +02:00
41f139589c core: bump webauthn from 1.5.2 to 1.6.0 (#3256)
Bumps [webauthn](https://github.com/duo-labs/py_webauthn) from 1.5.2 to 1.6.0.
- [Release notes](https://github.com/duo-labs/py_webauthn/releases)
- [Changelog](https://github.com/duo-labs/py_webauthn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/duo-labs/py_webauthn/compare/v1.5.2...v1.6.0)

---
updated-dependencies:
- dependency-name: webauthn
  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>
2022-07-14 10:16:14 +02:00
df24e3020b core: bump sentry-sdk from 1.7.0 to 1.7.1 (#3257) 2022-07-14 09:12:58 +02:00
e44c716cbe website/integrations: add note for rancher idp initiated
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-13 23:14:01 +02:00
d35302923d core: bump coverage from 6.4.1 to 6.4.2 (#3251)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 6.4.1 to 6.4.2.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/6.4.1...6.4.2)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:development
  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>
2022-07-13 21:06:06 +02:00
4d928368bc core: bump channels-redis from 3.4.0 to 3.4.1 (#3252)
Bumps [channels-redis](https://github.com/django/channels_redis) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/django/channels_redis/releases)
- [Changelog](https://github.com/django/channels_redis/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels_redis/compare/3.4.0...3.4.1)

---
updated-dependencies:
- dependency-name: channels-redis
  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>
2022-07-13 09:59:52 +02:00
c055d7a470 web: bump @typescript-eslint/parser from 5.30.5 to 5.30.6 in /web (#3244) 2022-07-12 09:22:46 +02:00
9e1b49e181 web: bump @typescript-eslint/eslint-plugin from 5.30.5 to 5.30.6 in /web (#3245) 2022-07-12 09:21:29 +02:00
db6a9ede1b ci: bump actions/setup-node from 3.3.0 to 3.4.0 (#3247) 2022-07-12 09:21:16 +02:00
86df0a448e core: bump sentry-sdk from 1.6.0 to 1.7.0 (#3246) 2022-07-12 09:20:42 +02:00
5ec052bd92 website/integrations: Node-Red integration with openidconnect (#3221)
* add Node-Red integration doc

* Node-Red Protocol settings + linting fixes
2022-07-11 10:59:57 +02:00
6f7984d05a website: bump @docusaurus/plugin-client-redirects from 2.0.0-beta.21 to 2.0.0-beta.22 in /website (#3239)
website: bump @docusaurus/plugin-client-redirects in /website

Bumps [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) from 2.0.0-beta.21 to 2.0.0-beta.22.
- [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.22/packages/docusaurus-plugin-client-redirects)

---
updated-dependencies:
- dependency-name: "@docusaurus/plugin-client-redirects"
  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>
2022-07-11 09:35:15 +02:00
f6d64d1d4b website: bump @docusaurus/preset-classic from 2.0.0-beta.21 to 2.0.0-beta.22 in /website (#3242)
website: bump @docusaurus/preset-classic in /website

Bumps [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) from 2.0.0-beta.21 to 2.0.0-beta.22.
- [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.22/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>
2022-07-11 09:34:12 +02:00
ef0c7a5a57 web: bump @sentry/browser from 7.5.1 to 7.6.0 in /web (#3238)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 7.5.1 to 7.6.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/7.5.1...7.6.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  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>
2022-07-11 09:33:52 +02:00
34dfbf8e9e web: bump @sentry/tracing from 7.5.1 to 7.6.0 in /web (#3240)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 7.5.1 to 7.6.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/7.5.1...7.6.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>
2022-07-11 09:31:41 +02:00
71d38e6fd0 web: bump rollup from 2.75.7 to 2.76.0 in /web (#3241) 2022-07-11 09:27:53 +02:00
9a9ba2560b core: delete expired models when filtering instead of excluding them
closes #3233

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-09 13:40:39 +02:00
2432e51970 web/elements: improve contrast for codemirror backgrounds
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-08 22:58:39 +02:00
47434cd62d stages/prompt: try to base64 decode file, fallback to keeping value as-is
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-08 22:45:31 +02:00
ff500b44a6 stages/prompt: force required to false when using readonlyfield
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-08 22:38:37 +02:00
4c14c7f3a4 web: bump @sentry/browser from 7.5.0 to 7.5.1 in /web (#3230) 2022-07-07 09:44:22 +02:00
019c4bf182 web: bump @sentry/tracing from 7.5.0 to 7.5.1 in /web (#3231) 2022-07-07 09:27:17 +02:00
2cbc291f04 core: bump goauthentik.io/api/v3 from 3.2022071.2 to 3.2022072.1 (#3232) 2022-07-07 09:27:01 +02:00
5197a3a461 web: bump moment from 2.29.3 to 2.29.4 in /web (#3226)
Bumps [moment](https://github.com/moment/moment) from 2.29.3 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.3...2.29.4)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-06 22:18:05 +02:00
52be87785f web: Update Web API Client version (#3227)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-07-06 22:07:21 +02:00
8e19fb3a8c release: 2022.7.2 2022-07-06 20:31:48 +02:00
0448dcf655 website/docs: prepare 2022.7.2
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-06 19:17:15 +02:00
b8f74ab9e7 website: bump clsx from 1.2.0 to 1.2.1 in /website (#3222)
Bumps [clsx](https://github.com/lukeed/clsx) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/lukeed/clsx/releases)
- [Commits](https://github.com/lukeed/clsx/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: clsx
  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>
2022-07-06 09:54:12 +02:00
501ce5cebb core: bump goauthentik.io/api/v3 from 3.2022071.1 to 3.2022071.2 (#3223)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2022071.1 to 3.2022071.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2022071.1...v3.2022071.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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>
2022-07-06 09:54:02 +02:00
b896ca7ef6 web: fix locale erroring with no pre-hydrated locale setting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-06 09:53:46 +02:00
d497db3010 flows: fix OOB flow incorrectly setting pending user
closes #3224

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-06 09:51:20 +02:00
24f95fdeaa tenants: fix tests for current tenant
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-05 23:47:49 +02:00
d1c4818724 policies: improve api test coverage
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-05 23:20:48 +02:00
9f736a9d99 web: Update Web API Client version (#3220)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-07-05 23:13:56 +02:00
49cce6a968 stages/prompt: add basic file field (#3156)
add basic file field

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-05 23:09:41 +02:00
713337130b web: Update Web API Client version (#3219)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-07-05 23:08:14 +02:00
0a73e7ac9f tenants: add default_locale read only field, pre-hydrate in flows and read in autodetect as first choice
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-05 23:04:25 +02:00
3344af72c2 outposts: cleanup user handling
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-05 22:41:19 +02:00
41eb44137e internal: remove pkg/errors 2022-07-05 20:26:33 +00:00
94a9667d86 web: bump @formatjs/intl-listformat from 7.0.2 to 7.0.3 in /web (#3216) 2022-07-05 09:09:49 +02:00
8b56a7defb core: bump django-silk from 5.0.0 to 5.0.1 (#3217) 2022-07-05 09:09:36 +02:00
5a4b9b4239 core: bump goauthentik.io/api/v3 from 3.2022063.5 to 3.2022071.1 (#3218) 2022-07-05 09:09:24 +02:00
f37308461c web: bump @typescript-eslint/eslint-plugin from 5.30.4 to 5.30.5 in /web (#3213)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.30.4 to 5.30.5.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.5/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-07-04 22:00:37 +02:00
9721098178 web: bump @sentry/browser from 7.4.1 to 7.5.0 in /web (#3215)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 7.4.1 to 7.5.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/7.4.1...7.5.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  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>
2022-07-04 22:00:24 +02:00
0ca5e67dad web: bump rapidoc from 9.3.2 to 9.3.3 in /web (#3212)
Bumps [rapidoc](https://github.com/rapi-doc/RapiDoc) from 9.3.2 to 9.3.3.
- [Release notes](https://github.com/rapi-doc/RapiDoc/releases)
- [Commits](https://github.com/rapi-doc/RapiDoc/compare/v9.3.2...v9.3.3)

---
updated-dependencies:
- dependency-name: rapidoc
  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>
2022-07-04 22:00:11 +02:00
da94564d5e web: bump @jackfranklin/rollup-plugin-markdown from 0.3.0 to 0.4.0 in /web (#3209)
web: bump @jackfranklin/rollup-plugin-markdown in /web

Bumps @jackfranklin/rollup-plugin-markdown from 0.3.0 to 0.4.0.

---
updated-dependencies:
- dependency-name: "@jackfranklin/rollup-plugin-markdown"
  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>
2022-07-04 21:59:57 +02:00
1f33237659 web: bump @typescript-eslint/parser from 5.30.4 to 5.30.5 in /web (#3214)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.30.4 to 5.30.5.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.5/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-07-04 21:59:27 +02:00
62e5979c13 web: bump @sentry/tracing from 7.4.1 to 7.5.0 in /web (#3208)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 7.4.1 to 7.5.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/7.4.1...7.5.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>
2022-07-04 21:59:10 +02:00
8a1e18e087 website: bump rapidoc from 9.3.2 to 9.3.3 in /website (#3210)
Bumps [rapidoc](https://github.com/rapi-doc/RapiDoc) from 9.3.2 to 9.3.3.
- [Release notes](https://github.com/rapi-doc/RapiDoc/releases)
- [Commits](https://github.com/rapi-doc/RapiDoc/compare/v9.3.2...v9.3.3)

---
updated-dependencies:
- dependency-name: rapidoc
  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>
2022-07-04 21:58:19 +02:00
a951daddce web: Update Web API Client version (#3211)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-07-04 21:58:06 +02:00
690f6d444a Merge branch 'version-2022.7' 2022-07-04 21:26:47 +02:00
b733930745 website/docs: add 2022.7 to sidebar
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-04 21:14:49 +02:00
f316a3000b release: 2022.7.1 2022-07-04 21:10:20 +02:00
ddae9dc6e1 Revert "web: manage version via package.json"
This reverts commit 022401b60e.

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

# Conflicts:
#	web/src/api/Sentry.ts
#	web/src/api/Users.ts
2022-07-04 21:10:16 +02:00
0348d6558a web: Update Web API Client version (#3207)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-07-04 20:15:28 +02:00
6a497b32f6 core: use Exception for fallback case in flow_manager
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-04 20:05:03 +02:00
47acc0ea90 core: bump django from 4.0.5 to 4.0.6 (#3206)
Bumps [django](https://github.com/django/django) from 4.0.5 to 4.0.6.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/4.0.5...4.0.6)

---
updated-dependencies:
- dependency-name: django
  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>
2022-07-04 12:47:58 +00:00
967c952a4a web: bump @typescript-eslint/eslint-plugin from 5.30.0 to 5.30.4 in /web (#3200)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.30.0 to 5.30.4.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.4/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-07-04 09:40:16 +02:00
b648d159dd website: bump clsx from 1.1.1 to 1.2.0 in /website (#3199)
Bumps [clsx](https://github.com/lukeed/clsx) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/lukeed/clsx/releases)
- [Commits](https://github.com/lukeed/clsx/compare/v1.1.1...v1.2.0)

---
updated-dependencies:
- dependency-name: clsx
  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>
2022-07-04 09:39:14 +02:00
aecd9387d9 web: bump @typescript-eslint/parser from 5.30.0 to 5.30.4 in /web (#3201)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.30.0 to 5.30.4.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.4/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-07-04 09:38:51 +02:00
6e8a5e1426 web: bump eslint from 8.18.0 to 8.19.0 in /web (#3202)
Bumps [eslint](https://github.com/eslint/eslint) from 8.18.0 to 8.19.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.18.0...v8.19.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2022-07-04 09:38:38 +02:00
607899be56 core: bump goauthentik.io/api/v3 from 3.2022063.4 to 3.2022063.5 (#3204)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2022063.4 to 3.2022063.5.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2022063.4...v3.2022063.5)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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>
2022-07-04 09:38:30 +02:00
5a92a8639a core: bump lxml from 4.9.0 to 4.9.1 (#3203)
Bumps [lxml](https://github.com/lxml/lxml) from 4.9.0 to 4.9.1.
- [Release notes](https://github.com/lxml/lxml/releases)
- [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt)
- [Commits](https://github.com/lxml/lxml/compare/lxml-4.9.0...lxml-4.9.1)

---
updated-dependencies:
- dependency-name: lxml
  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>
2022-07-04 09:38:14 +02:00
4cd629b5fc core: handle FlowNonApplicableException correctly in source flow_manager
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-03 22:03:03 +02:00
6020736430 website/docs: update 2022.7
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-03 21:39:59 +02:00
14a4047bdd flows: show messages from ak_message when flow is denied
fallback to same generic message

closes #3197

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-03 21:36:13 +02:00
23c1e22a04 web/elements: auto-switch themes for codemirror
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-02 23:07:09 +02:00
2a2ae4bc4f web/admin: default to users path in sidebar link
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-02 22:53:16 +02:00
5f4812e1d0 website/docs: fix Minor typo (#3196)
Signed-off-by: Stratos Gerakakis <stratos@gerakakis.net>
2022-07-02 19:48:53 +02:00
3ab475d916 website/docs: add snippet to skip authenticated flow
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-02 18:41:16 +02:00
453d64eea5 web: Update Web API Client version (#3195) 2022-07-02 17:44:59 +02:00
17d33f4b19 flows: denied action (#3194) 2022-07-02 17:37:57 +02:00
c39a5933e1 core: create FlowToken instead of regular token for generated recovery links (#3193)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2749
2022-07-02 14:17:41 +02:00
a9636b5727 website/docs: fix configuration item headers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-02 13:01:40 +02:00
5e3f44dd87 flows: add shortcut to redirect current flow (#3192) 2022-07-01 23:19:41 +02:00
1c64616ebd sources/ldap: add configuration for LDAP Source ciphers
closes #3110

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 19:53:49 +02:00
23273f53cc providers/oauth2: if no scopes are sent in authorize request, select all configured scopes
closes #3112

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 19:45:26 +02:00
d11ce0a86e providers/proxy: set default scopes based on managed attribute
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 18:26:49 +02:00
766ceda57a core: re-create anonymous user when repairing permissions
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 17:20:06 +02:00
eb633c607e internal: fix nil pointer reference
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 17:02:53 +02:00
c72d56d02d web: use full import paths for dynamic imports
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 16:56:23 +02:00
e758c434ea web: ignore module load errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 16:49:37 +02:00
90e3ae9457 *: define prometheus metrics in apps to prevent re-import
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 16:49:24 +02:00
0e825ffcfd root: add vscode tasks
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 16:10:08 +02:00
8a19c71f62 web: bump @sentry/browser from 7.3.1 to 7.4.1 in /web (#3191)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 7.3.1 to 7.4.1.
- [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/7.3.1...7.4.1)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  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>
2022-07-01 16:04:03 +02:00
5a7eff041a web: bump @sentry/tracing from 7.3.1 to 7.4.1 in /web (#3190)
* ci: add custom dependabot commit messages

* web: bump @sentry/tracing from 7.3.1 to 7.4.1 in /web

Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 7.3.1 to 7.4.1.
- [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/7.3.1...7.4.1)

---
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: Jens Langhammer <jens.langhammer@beryju.org>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-01 16:02:23 +02:00
552459834a ci: add custom dependabot commit messages
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 15:50:37 +02:00
cc6325bf6a build(deps): bump codemirror from 5.65.6 to 6.0.1 in /web (#3188)
* build(deps): bump codemirror from 5.65.6 to 6.0.1 in /web

Bumps [codemirror](https://github.com/codemirror/basic-setup) from 5.65.6 to 6.0.1.
- [Release notes](https://github.com/codemirror/basic-setup/releases)
- [Changelog](https://github.com/codemirror/basic-setup/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/basic-setup/commits/6.0.1)

---
updated-dependencies:
- dependency-name: codemirror
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

* upgrade

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 15:46:27 +02:00
9597ea9e1f build(deps): bump @patternfly/patternfly from 4.196.7 to 4.202.1 in /web (#3187)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-07-01 09:42:52 +02:00
69b5670659 build(deps): bump goauthentik.io/api/v3 from 3.2022063.3 to 3.2022063.4 (#3189) 2022-07-01 09:20:39 +02:00
56fd436e5d web: fix redirect when accessing authentik URLs authenticated
closes #3174

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-30 23:04:39 +02:00
b7558ae28c web: Update Web API Client version (#3186)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-30 22:26:52 +02:00
ea60c389be providers/saml: include SSO Binding URLs in Provider API
closes #3179

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-30 22:18:21 +02:00
f6042f29f6 website/docs: add notice to use in-cluster service for nginx forward auth
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-30 21:33:47 +02:00
983882f5a0 providers/oauth2: ensure refresh tokens are URL safe
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#3185
2022-06-30 12:43:08 +02:00
a6d3fd92df web/elements: fix ak-wizard-page-form not setting valid
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-30 12:37:10 +02:00
96f39904b8 build(deps): bump lit from 2.2.6 to 2.2.7 in /web (#3181)
Bumps [lit](https://github.com/lit/lit/tree/HEAD/packages/lit) from 2.2.6 to 2.2.7.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/lit/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/lit@2.2.7/packages/lit)

---
updated-dependencies:
- dependency-name: lit
  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>
2022-06-30 10:08:29 +02:00
ee347aa7ef build(deps-dev): bump pylint from 2.14.3 to 2.14.4 (#3182)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.14.3 to 2.14.4.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.14.3...v2.14.4)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  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>
2022-06-30 10:08:13 +02:00
6437334e67 build(deps): bump github.com/stretchr/testify from 1.7.5 to 1.8.0 (#3183)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.7.5 to 1.8.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.7.5...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  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>
2022-06-30 10:05:46 +02:00
2f57d7f427 web/admin: fix wizard type selection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-29 21:45:38 +02:00
sev
db07f564aa website/docs: expand nginx reverse-proxy setup (#3079)
* website/docs: expand nginx reverse-proxy setup

* website/docs: simplify reverse-proxy config

Combine location blocks and remove documentstion links, they were not doing much.
2022-06-29 15:02:59 +00:00
d1479a1b16 web: improve detection for locales
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#3163
2022-06-29 11:15:44 +02:00
4d80e207da build(deps): bump @sentry/browser from 7.3.0 to 7.3.1 in /web (#3176) 2022-06-29 09:20:48 +02:00
e7be7ac9b4 build(deps): bump @sentry/tracing from 7.3.0 to 7.3.1 in /web (#3177) 2022-06-29 09:11:37 +02:00
e0954c0f89 build(deps): bump ua-parser from 0.10.0 to 0.15.0 (#3178) 2022-06-29 09:11:22 +02:00
7ae061909c build(deps): bump @babel/preset-env from 7.18.2 to 7.18.6 in /web (#3170)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.18.2 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  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>
2022-06-28 09:29:19 +02:00
45a806f46b build(deps): bump @babel/plugin-proposal-decorators from 7.18.2 to 7.18.6 in /web (#3166)
build(deps): bump @babel/plugin-proposal-decorators in /web

Bumps [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) from 7.18.2 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-proposal-decorators)

---
updated-dependencies:
- dependency-name: "@babel/plugin-proposal-decorators"
  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>
2022-06-28 09:28:46 +02:00
feb6b07657 build(deps): bump @babel/plugin-transform-runtime from 7.18.5 to 7.18.6 in /web (#3169)
build(deps): bump @babel/plugin-transform-runtime in /web

Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.18.5 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  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>
2022-06-28 09:28:05 +02:00
1d98582d29 build(deps): bump @babel/preset-typescript from 7.17.12 to 7.18.6 in /web (#3168)
build(deps): bump @babel/preset-typescript in /web

Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.17.12 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  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>
2022-06-28 09:27:57 +02:00
06663edba2 build(deps): bump @babel/core from 7.18.5 to 7.18.6 in /web (#3165)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.5 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  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>
2022-06-28 09:27:47 +02:00
de0d1dc94d build(deps): bump @typescript-eslint/parser from 5.29.0 to 5.30.0 in /web (#3167)
build(deps): bump @typescript-eslint/parser in /web

Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.29.0 to 5.30.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-06-28 09:27:37 +02:00
1652ea25e4 build(deps): bump @typescript-eslint/eslint-plugin from 5.29.0 to 5.30.0 in /web (#3164) 2022-06-28 09:00:22 +02:00
d794e3055c build(deps-dev): bump django-silk from 4.4.0 to 5.0.0 (#3171) 2022-06-28 08:58:47 +02:00
a92c68ac85 build(deps-dev): bump black from 22.3.0 to 22.6.0 (#3172) 2022-06-28 08:58:26 +02:00
dd41789230 build(deps): bump uvicorn from 0.18.1 to 0.18.2 (#3173) 2022-06-28 08:57:35 +02:00
022401b60e web: manage version via package.json
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-27 21:31:54 +02:00
ef218ff1ff website/docs: update 2022.7 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-27 21:12:36 +02:00
f933bf2f40 build(deps): bump @sentry/browser from 7.2.0 to 7.3.0 in /web (#3157) 2022-06-27 09:02:32 +02:00
4fc761adea build(deps): bump @rollup/plugin-commonjs from 22.0.0 to 22.0.1 in /web (#3159) 2022-06-27 09:01:52 +02:00
d11c214d32 build(deps): bump goauthentik.io/api/v3 from 3.2022063.1 to 3.2022063.3 (#3162) 2022-06-27 09:01:36 +02:00
ffbbe5ca5f build(deps): bump @sentry/tracing from 7.2.0 to 7.3.0 in /web (#3158) 2022-06-27 09:01:03 +02:00
8582091219 build(deps): bump channels from 3.0.4 to 3.0.5 (#3160) 2022-06-27 09:00:37 +02:00
28c8eb3ee6 build(deps-dev): bump importlib-metadata from 4.11.4 to 4.12.0 (#3161) 2022-06-27 09:00:26 +02:00
3a00a5ac3d website/docs: cleanup vikunja docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-26 18:29:17 +02:00
20035e0f1b ci: only hash web source
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-26 18:18:36 +02:00
67021b0e7c web: Update Web API Client version (#3155)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-26 17:55:46 +02:00
c5a2831665 api: add basic jwt support with required scope (#2624)
* api: add basic jwt support with required scope

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

* api: only set auth_via when actually authenticating via token

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

* save consented permissions in user consent, re-prompt when new permissions are required

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

* update locale

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

* translate special scope map

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

* more api auth tests

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

* add docs

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

* build web api in e2e tests

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

* link generated client instead of copying

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-26 17:51:15 +02:00
768f073e49 web: Update Web API Client version (#3152)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-26 00:51:38 +02:00
504338ea66 web/admin: application wizard (part 1) (#2745)
* initial

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

* remove log

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

* start oauth

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

* use form for all type wizard pages

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

* more oauth

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

* basic wizard actions

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

* make resets work

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

* add hint in provider wizard

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

* render correct icon in empty state in table page

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

* improve empty state

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

* more

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

* add more pages

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

* fix

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

* add group PK to service account creation response

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

* use wizard-level isValid prop

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

* re-add old buttons

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-26 00:46:40 +02:00
a8c04f96d2 web: use absolute imports with path rewrite instead of relative imports (#3149) 2022-06-25 17:44:17 +02:00
340faf5341 lifecycle: Update postgres healthcheck for compose with user information (#3143)
Update postgres healthcheck with user information
2022-06-24 12:02:05 +02:00
a76c39aff9 build(deps-dev): bump selenium from 4.2.0 to 4.3.0 (#3144) 2022-06-24 08:19:42 +02:00
bb728a53cc build(deps): bump uvicorn from 0.17.6 to 0.18.1 (#3145) 2022-06-24 08:19:31 +02:00
5c28a7dd44 build(deps): bump github.com/stretchr/testify from 1.7.4 to 1.7.5 (#3146) 2022-06-24 07:59:51 +02:00
e1efb47543 web/flows: statically import webauthn-related stages for safari issues
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-23 19:26:31 +02:00
e50a296a18 build(deps): bump @lingui/core from 3.13.3 to 3.14.0 in /web (#3136)
Bumps [@lingui/core](https://github.com/lingui/js-lingui) from 3.13.3 to 3.14.0.
- [Release notes](https://github.com/lingui/js-lingui/releases)
- [Changelog](https://github.com/lingui/js-lingui/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lingui/js-lingui/compare/v3.13.3...v3.14.0)

---
updated-dependencies:
- dependency-name: "@lingui/core"
  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>
2022-06-23 09:48:02 +02:00
e211265c30 build(deps): bump @lingui/cli from 3.13.3 to 3.14.0 in /web (#3137)
Bumps [@lingui/cli](https://github.com/lingui/js-lingui) from 3.13.3 to 3.14.0.
- [Release notes](https://github.com/lingui/js-lingui/releases)
- [Changelog](https://github.com/lingui/js-lingui/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lingui/js-lingui/compare/v3.13.3...v3.14.0)

---
updated-dependencies:
- dependency-name: "@lingui/cli"
  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>
2022-06-23 09:46:23 +02:00
1f143a24db build(deps): bump @lingui/macro from 3.13.3 to 3.14.0 in /web (#3138)
Bumps [@lingui/macro](https://github.com/lingui/js-lingui) from 3.13.3 to 3.14.0.
- [Release notes](https://github.com/lingui/js-lingui/releases)
- [Changelog](https://github.com/lingui/js-lingui/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lingui/js-lingui/compare/v3.13.3...v3.14.0)

---
updated-dependencies:
- dependency-name: "@lingui/macro"
  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>
2022-06-23 09:46:07 +02:00
48f490b810 build(deps): bump sentry-sdk from 1.5.12 to 1.6.0 (#3140)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.5.12 to 1.6.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.5.12...1.6.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  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>
2022-06-23 09:45:39 +02:00
aed382de0c build(deps): bump pycryptodome from 3.14.1 to 3.15.0 (#3141)
Bumps [pycryptodome](https://github.com/Legrandin/pycryptodome) from 3.14.1 to 3.15.0.
- [Release notes](https://github.com/Legrandin/pycryptodome/releases)
- [Changelog](https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst)
- [Commits](https://github.com/Legrandin/pycryptodome/compare/v3.14.1...v3.15.0)

---
updated-dependencies:
- dependency-name: pycryptodome
  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>
2022-06-23 09:45:27 +02:00
8ecf40a58b build(deps): bump kubernetes from 23.6.0 to 24.2.0 (#3142)
Bumps [kubernetes](https://github.com/kubernetes-client/python) from 23.6.0 to 24.2.0.
- [Release notes](https://github.com/kubernetes-client/python/releases)
- [Changelog](https://github.com/kubernetes-client/python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes-client/python/compare/v23.6.0...v24.2.0)

---
updated-dependencies:
- dependency-name: kubernetes
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-23 09:45:10 +02:00
aca3c75e17 build(deps): bump @lingui/detect-locale from 3.13.3 to 3.14.0 in /web (#3139)
Bumps [@lingui/detect-locale](https://github.com/lingui/js-lingui) from 3.13.3 to 3.14.0.
- [Release notes](https://github.com/lingui/js-lingui/releases)
- [Changelog](https://github.com/lingui/js-lingui/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lingui/js-lingui/compare/v3.13.3...v3.14.0)

---
updated-dependencies:
- dependency-name: "@lingui/detect-locale"
  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>
2022-06-23 09:44:51 +02:00
f28509608b core: mark session as modified instead of saving it directly to bump expiry
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-22 08:48:14 +02:00
ff6c508de7 build(deps): bump geoip2 from 4.5.0 to 4.6.0 (#3133)
Bumps [geoip2](https://github.com/maxmind/GeoIP2-python) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/maxmind/GeoIP2-python/releases)
- [Changelog](https://github.com/maxmind/GeoIP2-python/blob/v4.6.0/HISTORY.rst)
- [Commits](https://github.com/maxmind/GeoIP2-python/compare/v4.5.0...v4.6.0)

---
updated-dependencies:
- dependency-name: geoip2
  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>
2022-06-22 08:32:01 +02:00
7319ea2dcf ci: add version family (#3059)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-21 23:31:27 +02:00
6a4efaecb0 website/docs: start troubleshooting page for forward auth
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-21 22:26:17 +02:00
29b0eae43f web/admin: only pre-select oauth2 provider key if creating a new instance
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-21 19:51:24 +02:00
9f3e742fb1 build(deps): bump github.com/stretchr/testify from 1.7.2 to 1.7.4 (#3132) 2022-06-21 06:51:55 +02:00
c8e09fea33 build(deps): bump @typescript-eslint/eslint-plugin from 5.28.0 to 5.29.0 in /web (#3128) 2022-06-21 06:45:13 +02:00
437e932471 build(deps): bump goauthentik.io/api/v3 from 3.2022062.3 to 3.2022063.1 (#3131) 2022-06-21 06:44:54 +02:00
ce07d71d23 build(deps): bump codemirror from 5.65.5 to 5.65.6 in /web (#3126) 2022-06-21 06:44:31 +02:00
9815c591e0 build(deps): bump rollup from 2.75.6 to 2.75.7 in /web (#3127) 2022-06-21 06:42:43 +02:00
db7a3ab630 build(deps): bump @typescript-eslint/parser from 5.28.0 to 5.29.0 in /web (#3129) 2022-06-21 06:42:27 +02:00
3fa772c32e build(deps-dev): bump django-silk from 4.3.0 to 4.4.0 (#3130) 2022-06-21 06:42:10 +02:00
6c9dc7a15b providers/oauth2: fix OAuth form_post response mode for code response_type
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#3113
2022-06-20 21:52:36 +02:00
ece0429ea8 internal: failback with self-signed cert if cert for tenant fails to load
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-20 21:26:34 +02:00
d56ddb16b1 lifecycle: fix confusing success messages in startup healthiness check
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-20 21:26:21 +02:00
b6267fdf28 *: add versioned user agent to sentry
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-20 11:54:10 +02:00
1f190a9255 web: Update Web API Client version (#3124)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-20 10:38:37 +02:00
1f0fc0a6a2 Merge branch 'version-2022.6' 2022-06-20 10:19:25 +02:00
3ba678851e build(deps): bump @sentry/browser from 7.1.1 to 7.2.0 in /web (#3118)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 7.1.1 to 7.2.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/7.1.1...7.2.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  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>
2022-06-20 10:18:52 +02:00
0869ef3d0d build(deps): bump @sentry/tracing from 7.1.1 to 7.2.0 in /web (#3119)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 7.1.1 to 7.2.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/7.1.1...7.2.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>
2022-06-20 10:11:28 +02:00
91100ce1e2 build(deps): bump eslint from 8.17.0 to 8.18.0 in /web (#3120)
Bumps [eslint](https://github.com/eslint/eslint) from 8.17.0 to 8.18.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.17.0...v8.18.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2022-06-20 10:06:34 +02:00
a65ce47736 build(deps): bump typescript from 4.7.3 to 4.7.4 in /web (#3121)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.7.3 to 4.7.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.7.3...v4.7.4)

---
updated-dependencies:
- dependency-name: typescript
  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>
2022-06-20 10:05:53 +02:00
def17bbc1e build(deps-dev): bump pylint from 2.14.2 to 2.14.3 (#3122)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.14.2 to 2.14.3.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.14.2...v2.14.3)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  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>
2022-06-20 10:05:43 +02:00
eb7da8f414 build(deps): bump django-filter from 21.1 to 22.1 (#3123)
Bumps [django-filter](https://github.com/carltongibson/django-filter) from 21.1 to 22.1.
- [Release notes](https://github.com/carltongibson/django-filter/releases)
- [Changelog](https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst)
- [Commits](https://github.com/carltongibson/django-filter/compare/21.1...22.1)

---
updated-dependencies:
- dependency-name: django-filter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-20 10:05:26 +02:00
9201fc1834 release: 2022.6.3 2022-06-19 22:01:06 +02:00
5385feb428 website/docs: add 2022.6.3 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:41:36 +02:00
c6f29d9eb4 website/docs: add 2022.6.3 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:41:22 +02:00
db557401aa web/admin: lint bound group under policies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:37:28 +02:00
c824af5bc3 web/elements: add spinner when loading dynamic routes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:37:22 +02:00
1faba11a57 providers/oauth2: add test to ensure capitalised redirect_uri isn't changed
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#3114
2022-06-19 21:37:20 +02:00
9p4
f0c72e8536 providers/oauth2: dont lowercase URL for token requests (#3114)
this was a leftover from before the migration regex checking for redirect URIs

closes #3076 and #3083
2022-06-19 21:37:17 +02:00
91f91b08e5 core: fix migrations when creating bootstrap token
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:37:14 +02:00
8faa909c32 internal: fix routing to embedded outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:37:03 +02:00
49142fa80b internal: dont sample gunicorn proxied requests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:57 +02:00
2a6fccd22a providers/proxy: only send misconfiguration event once
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:50 +02:00
1d10afa209 website/docs: add version dropdown for subdomains
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:45 +02:00
4b7c3c38cd website/docs: support levels (#3103)
* website/docs: add badges for integration level

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

* add badge for sources

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:42 +02:00
440cacbafe webiste/docs: use autogenerated pages and categories (#3102)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:39 +02:00
b33bff92ee web/flows: fix error when webauthn operations failed and user retries
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:28 +02:00
caed306346 providers/oauth2: if a redirect_uri cannot be parsed as regex, compare strict (#3070)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:19 +02:00
d0eb6af7e9 web/admin: remove invalid requirement for usernames
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:15 +02:00
ec5ed67f6c web/flows: add divider to identification stage for security key
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:36:08 +02:00
59b899ddff internal: skip tracing for go healthcheck and metrics endpoints
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:35:48 +02:00
85784f796c root: ignore healthcheck routes in sentry tracing
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:35:46 +02:00
4c0e19cbea web/flows: remove autofocus from password field of identifications tage
closes #2561

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:35:43 +02:00
b42eb9464f lifecycle: run bootstrap tasks inline when using automated install
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:35:33 +02:00
6559fdee15 stages/authenticator_validate: add webauthn tests (#3069)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:35:23 +02:00
3455bf3d27 policies: consolidate log user and application
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:35:04 +02:00
0d96e68c1e core: add limit of 20 to group recursion
closes #3116

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:24:57 +02:00
29d3db5112 web/admin: lint bound group under policies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-19 21:22:47 +02:00
cdf88e4477 web/elements: add spinner when loading dynamic routes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-18 13:36:18 +02:00
7caac1d0c7 providers/oauth2: add test to ensure capitalised redirect_uri isn't changed
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#3114
2022-06-18 13:13:36 +02:00
9p4
45364d6553 providers/oauth2: dont lowercase URL for token requests (#3114)
this was a leftover from before the migration regex checking for redirect URIs

closes #3076 and #3083
2022-06-18 13:08:15 +02:00
2298eb124f core: fix migrations when creating bootstrap token
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-17 10:10:04 +02:00
6dff1f8e5e build(deps-dev): bump prettier from 2.7.0 to 2.7.1 in /website (#3107)
Bumps [prettier](https://github.com/prettier/prettier) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.7.0...2.7.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  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>
2022-06-17 09:38:57 +02:00
a944701f3a build(deps): bump prettier from 2.7.0 to 2.7.1 in /web (#3108)
Bumps [prettier](https://github.com/prettier/prettier) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.7.0...2.7.1)

---
updated-dependencies:
- dependency-name: prettier
  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>
2022-06-17 09:38:46 +02:00
23866fe459 build(deps): bump colorama from 0.4.4 to 0.4.5 (#3109)
Bumps [colorama](https://github.com/tartley/colorama) from 0.4.4 to 0.4.5.
- [Release notes](https://github.com/tartley/colorama/releases)
- [Changelog](https://github.com/tartley/colorama/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tartley/colorama/compare/0.4.4...0.4.5)

---
updated-dependencies:
- dependency-name: colorama
  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>
2022-06-17 09:38:37 +02:00
0a83b04419 internal: fix routing to embedded outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-16 17:05:27 +02:00
e6ecdf8b1d website/admin: add missing description for user_write path
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-16 16:59:56 +02:00
2d48fe42f4 internal: dont sample gunicorn proxied requests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-16 11:32:21 +02:00
5894ccdaf2 build(deps): bump goauthentik.io/api/v3 from 3.2022062.2 to 3.2022062.3 (#3106)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2022062.2 to 3.2022062.3.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2022062.2...v3.2022062.3)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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>
2022-06-16 10:36:50 +02:00
79bec6f6b2 providers/proxy: only send misconfiguration event once
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-16 10:32:34 +02:00
9610f96c11 build(deps-dev): bump pylint from 2.14.1 to 2.14.2 (#3105) 2022-06-16 09:58:29 +02:00
36a326cd81 website/docs: add version dropdown for subdomains
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-15 21:43:44 +02:00
c0c222a0b8 website/docs: support levels (#3103)
* website/docs: add badges for integration level

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

* add badge for sources

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-15 21:31:34 +02:00
e17f7020e6 webiste/docs: use autogenerated pages and categories (#3102)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-15 20:56:27 +02:00
6d9579d3e6 web/elements: rework treeview parents
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-15 20:06:01 +02:00
9f15ee8cb8 web/elements: fix child items not having a parent set causing wrong paths
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-15 14:25:01 +02:00
e892ed14da providers/oauth2: include source's user path in M2M created users
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-15 14:07:28 +02:00
093a67525a web: Update Web API Client version (#3101)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-15 12:24:22 +02:00
1c62a3db6e core: user paths (#3085)
* init

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

* add user_path_template

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

* add to sources and flow

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

* add outposts & api

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

* dark theme for treeview

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

* add search

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

* add docs and tests for validation

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

* add to user write stage

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

* add web ui

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

* web: improve error handling

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-15 12:12:26 +02:00
c4b4c7134d build(deps): bump lit from 2.2.5 to 2.2.6 in /web (#3095)
Bumps [lit](https://github.com/lit/lit/tree/HEAD/packages/lit) from 2.2.5 to 2.2.6.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/lit/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/lit@2.2.6/packages/lit)

---
updated-dependencies:
- dependency-name: lit
  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>
2022-06-15 09:45:27 +02:00
82cb6d41b8 build(deps): bump prettier from 2.6.2 to 2.7.0 in /web (#3097)
Bumps [prettier](https://github.com/prettier/prettier) from 2.6.2 to 2.7.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.6.2...2.7.0)

---
updated-dependencies:
- dependency-name: prettier
  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>
2022-06-15 09:45:18 +02:00
423380d987 build(deps-dev): bump prettier from 2.6.2 to 2.7.0 in /website (#3096)
Bumps [prettier](https://github.com/prettier/prettier) from 2.6.2 to 2.7.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.6.2...2.7.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  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>
2022-06-15 09:45:11 +02:00
175d97fdcf build(deps): bump helm/kind-action from 1.2.0 to 1.3.0 (#3098)
Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.2.0 to 1.3.0.
- [Release notes](https://github.com/helm/kind-action/releases)
- [Commits](https://github.com/helm/kind-action/compare/v1.2.0...v1.3.0)

---
updated-dependencies:
- dependency-name: helm/kind-action
  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>
2022-06-15 09:45:01 +02:00
5dbbf970b0 build(deps): bump @typescript-eslint/eslint-plugin from 5.27.1 to 5.28.0 in /web (#3089)
build(deps): bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.27.1 to 5.28.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.28.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-06-14 09:50:03 +02:00
1541d477af build(deps): bump @babel/plugin-transform-runtime from 7.18.2 to 7.18.5 in /web (#3088)
build(deps): bump @babel/plugin-transform-runtime in /web

Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.18.2 to 7.18.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.5/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  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>
2022-06-14 09:48:51 +02:00
d745331654 build(deps): bump @babel/core from 7.18.2 to 7.18.5 in /web (#3090)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.2 to 7.18.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.5/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  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>
2022-06-14 09:48:37 +02:00
defbdc5068 build(deps): bump @typescript-eslint/parser from 5.27.1 to 5.28.0 in /web (#3091)
build(deps): bump @typescript-eslint/parser in /web

Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.27.1 to 5.28.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.28.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-06-14 09:48:28 +02:00
350f0d8365 build(deps): bump goauthentik.io/api/v3 from 3.2022062.1 to 3.2022062.2 (#3082)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2022062.1 to 3.2022062.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2022062.1...v3.2022062.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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>
2022-06-13 09:35:15 +02:00
b5c93fb3e3 build(deps): bump @rollup/plugin-typescript from 8.3.2 to 8.3.3 in /web (#3081)
Bumps [@rollup/plugin-typescript](https://github.com/rollup/plugins/tree/HEAD/packages/typescript) from 8.3.2 to 8.3.3.
- [Release notes](https://github.com/rollup/plugins/releases)
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/typescript/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/typescript-v8.3.3/packages/typescript)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-typescript"
  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>
2022-06-13 09:35:05 +02:00
5be45ebf8e web/flows: fix error when webauthn operations failed and user retries
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-12 17:42:23 +02:00
ad8fe9fe81 website/integrations: add Sonarr Proxy Setup (#3067)
I was stuck after setting up as the guide never actually mentions you need to make the change to your reverse proxy

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-11 19:52:22 +02:00
c2f7edaa42 web: Update Web API Client version (#3078)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-11 19:51:05 +02:00
6821402fef providers/oauth2: remove deprecated verification_keys (#3071)
remove verification_keys

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-11 19:48:07 +02:00
8dbb0bd2c6 providers/oauth2: token revoke (#3077) 2022-06-11 18:49:16 +02:00
24a21c1761 web/flows: update default flow background
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-10 23:33:17 +02:00
0cad56ec73 providers/oauth2: if a redirect_uri cannot be parsed as regex, compare strict (#3070)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-10 23:32:57 +02:00
4d8021c403 web/admin: remove invalid requirement for usernames
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-10 22:59:59 +02:00
6573cbb16c web/flows: add divider to identification stage for security key
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-10 22:50:40 +02:00
bdf76bb4b7 internal: skip tracing for go healthcheck and metrics endpoints
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-10 22:21:11 +02:00
74ce9cc6fd root: ignore healthcheck routes in sentry tracing
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-10 20:10:27 +02:00
070a6d866e web/flows: remove autofocus from password field of identifications tage
closes #2561

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-10 20:02:48 +02:00
5e2d647a6c core: trigger bootstrap tasks in server if we're debugging
closes #3040

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-09 20:21:31 +02:00
7beebe030d lifecycle: run bootstrap tasks inline when using automated install
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-09 20:09:55 +02:00
66f4a31b4c stages/authenticator_validate: add webauthn tests (#3069)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-08 20:50:48 +02:00
beddd6a460 web: update sentry and remove rollup-plugin-sourcemaps
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-08 20:32:56 +02:00
faec866581 build(deps): bump python from 3.10.4-slim-bullseye to 3.10.5-slim-bullseye (#3062)
build(deps): bump python

Bumps python from 3.10.4-slim-bullseye to 3.10.5-slim-bullseye.

---
updated-dependencies:
- dependency-name: python
  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>
2022-06-08 09:46:58 +02:00
effed50cc1 build(deps): bump rollup from 2.75.5 to 2.75.6 in /web (#3064) 2022-06-08 09:29:15 +02:00
38ad6096ad build(deps): bump goauthentik.io/api/v3 from 3.2022061.3 to 3.2022062.1 (#3066) 2022-06-08 09:28:38 +02:00
bd53042553 web: Update Web API Client version (#3061)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-07 22:30:36 +02:00
039d896dee policies: consolidate log user and application
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-07 22:26:01 +02:00
ff2baf502b release: 2022.6.2 2022-06-07 21:36:18 +02:00
3b182ca223 website/docs: add 2022.6.2 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-07 20:37:34 +02:00
8da8890a8e web: Update Web API Client version (#3058)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-07 20:20:03 +02:00
23023ec727 providers/oauth2: add JWKS URL to OAuth2ProviderSetupURLs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-07 20:17:06 +02:00
7d84a71a01 stages/authenticator_validate: fix double-negation of password-less check
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-07 09:52:10 +02:00
192001f193 build(deps): bump @typescript-eslint/parser from 5.27.0 to 5.27.1 in /web (#3052)
build(deps): bump @typescript-eslint/parser in /web

Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.27.0 to 5.27.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.27.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-06-07 09:28:39 +02:00
63734682d2 build(deps): bump @typescript-eslint/eslint-plugin from 5.27.0 to 5.27.1 in /web (#3053)
build(deps): bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.27.0 to 5.27.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.27.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-06-07 09:26:44 +02:00
a0cd2d55f8 build(deps): bump @patternfly/patternfly from 4.194.4 to 4.196.7 in /web (#3054)
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.194.4 to 4.196.7.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/main/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.194.4...prerelease-v4.196.7)

---
updated-dependencies:
- dependency-name: "@patternfly/patternfly"
  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>
2022-06-07 09:23:15 +02:00
a72c7adfc0 build(deps): bump actions/setup-node from 3.2.0 to 3.3.0 (#3055)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.2.0...v3.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  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>
2022-06-07 09:23:06 +02:00
e88e02ec85 build(deps-dev): bump pylint from 2.14.0 to 2.14.1 (#3056)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.14.0 to 2.14.1.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.14.0...v2.14.1)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  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>
2022-06-07 09:22:58 +02:00
f7661c8bbd build(deps): bump github.com/stretchr/testify from 1.7.1 to 1.7.2 (#3057)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.7.1 to 1.7.2.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.7.1...v1.7.2)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  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>
2022-06-07 09:22:46 +02:00
9add8479ca stages/authenticator_validate: fix error in passwordless webauthn
closes #3050

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-06 13:50:11 +02:00
4c39e08dd4 website/docs: fix incorrect oauth end-session URL
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-06 12:48:06 +02:00
44ce2ebece build(deps): bump typescript from 4.7.2 to 4.7.3 in /web (#3046) 2022-06-06 10:55:42 +02:00
f5a8859d00 build(deps): bump @formatjs/intl-listformat from 7.0.1 to 7.0.2 in /web (#3047) 2022-06-06 10:55:29 +02:00
9ef0e8bc5f build(deps): bump eslint from 8.16.0 to 8.17.0 in /web (#3048) 2022-06-06 10:55:13 +02:00
60eeafd111 build(deps): bump goauthentik.io/api/v3 from 3.2022053.4 to 3.2022061.3 (#3049) 2022-06-06 10:54:57 +02:00
6f3d6efa22 webiste/docs: Improve clarity of dev environment setup doc (#3045)
* Improve clarity of dev environment setup doc

* Requested changes and further small improvements

* I actually read the makefile this time

* Add makefile entry for building ui

* Comments

* Add documentation setup

* Move documentation setup

* Formatting
2022-06-05 23:26:08 +02:00
8d3275817b providers/ldap: fix existing binder not being carried forward correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-05 18:51:01 +02:00
ca40d31dac *: make user logging more consistent
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-05 18:50:44 +02:00
438aac8879 web: Update Web API Client version (#3043)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-05 14:37:17 +02:00
2dfa6c2c82 core: add setting to open application launch URL in a new browser tab (#3037)
* core: add setting to open application launch URL in a new browser tab

* core: fix failing applications unit tests

* core: fix formatting

* core: include models only generated when debug mode is enabled
2022-06-05 14:32:22 +02:00
c11435780d sources/oauth: fix twitter client missing basic auth
closes #3038

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-05 14:21:32 +02:00
ee54328589 web: Update Web API Client version (#3042) 2022-06-05 01:01:30 +02:00
817d538b8f core: add additional filters to source viewset
https://github.com/goauthentik/terraform-provider-authentik/issues/184
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-05 00:56:46 +02:00
210775776f core: add slug to built-in source
https://github.com/goauthentik/terraform-provider-authentik/issues/184
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-05 00:50:10 +02:00
2a4ce75bc4 web/elements: add error handler when table fails to fetch objects
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-05 00:46:25 +02:00
b26111fb42 events: fix error when attempting to create event with GeoIP City in context
closes #2709

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-05 00:16:07 +02:00
e30103aa9f providers/proxy: use same redirect-save code for all modes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-04 23:25:47 +02:00
dc9203789e web: Update Web API Client version (#3041) 2022-06-04 22:54:07 +02:00
d70ce2776f Merge branch 'version-2022.6' 2022-06-04 22:43:48 +02:00
ad7d65e903 website/docs: add 2022.6 to sidebar
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-04 22:29:59 +02:00
67d54c5209 release: 2022.6.1 2022-06-04 21:23:33 +02:00
bb244b8338 providers/ldap: fix session cache being lost on provider refresh
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-04 18:03:00 +02:00
fa04883ac1 events: use custom login failed signal, also send for mfa errors, add stage and more to context (#3039)
* use custom login failed signal, also send for mfa errors, add stage and more to context

closes #3027

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

* include device class in event

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

* update tests

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-04 15:30:56 +02:00
6739ded5a9 root: remove flower dependency
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-04 14:22:25 +02:00
9a7e5d934e root: always set AUTHENTIK_DEBUG when generating schema
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#3037
2022-06-04 14:18:04 +02:00
6dc6d19d2d web: Update Web API Client version (#3036)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-06-03 19:42:42 +02:00
36cbc44ed6 migrate to main (#3035)
closes #3032

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-03 19:40:09 +02:00
0c591a50e3 *: don't dispatch tasks on startup of server (#3033)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-03 18:29:24 +02:00
7ee655a318 core: add bootstrap variables with authentik prefix for helm charts (#3031)
https://github.com/goauthentik/helm/pull/72
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-03 15:22:56 +02:00
8447e9b9c2 providers/proxy: envoy v2 (#3029)
* add path prefix

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

* use prefix correctly

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

* only set redirect if session doesn't have a redirect yet

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-03 10:32:52 +02:00
09f92e5bad build(deps-dev): bump coverage from 6.4 to 6.4.1 (#3028)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 6.4 to 6.4.1.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/6.4...6.4.1)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:development
  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>
2022-06-03 09:53:42 +02:00
f9a419107a outposts/proxyv2: add basic envoy support (#3026)
* outposts/proxyv2: add basic envoy support

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

* don't crash when backend is not available

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

* add envoy tests and docs

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-03 00:06:09 +02:00
8f0572d11e outposts/ldap: add correct group objectClass (#3023)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2861
2022-06-02 18:48:07 +02:00
7ebf793953 Translate '/web/src/locales/en.po' in 'zh_CN' (#3024)
Translate /web/src/locales/en.po in zh_CN

translation completed for the source file '/web/src/locales/en.po'
on the 'zh_CN' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-06-02 18:30:38 +02:00
63783ee77b Translate '/web/src/locales/en.po' in 'zh-Hans' (#3025)
Translate /web/src/locales/en.po in zh-Hans

translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-06-02 18:30:29 +02:00
eba339ba27 core: improve loading speed of flow background
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-02 14:20:23 +02:00
0adb5a79f6 root: update supported versions
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-02 14:08:02 +02:00
fa81adf254 website/docs: Add warning for timezone mounts (#3022)
Improve documentation: #3005
2022-06-02 14:02:01 +02:00
558c7bba2a lib: add lxml wrapper
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-02 13:25:24 +02:00
8cd1a42fb9 *: fix linting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-02 11:50:10 +02:00
8cf0e78aa0 Translate '/locale/en/LC_MESSAGES/django.po' in 'ko_KR' (#3014)
Apply translations in ko_KR

translation completed for the source file '/locale/en/LC_MESSAGES/django.po'
on the 'ko_KR' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-06-02 11:16:41 +02:00
3f69a57013 Translate '/web/src/locales/en.po' in 'zh_CN' (#3017)
Translate /web/src/locales/en.po in zh_CN

translation completed for the source file '/web/src/locales/en.po'
on the 'zh_CN' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-06-02 11:13:45 +02:00
f7f12cab10 Translate '/web/src/locales/en.po' in 'zh-Hans' (#3018)
Translate /web/src/locales/en.po in zh-Hans

translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-06-02 11:13:37 +02:00
cacaa378c8 build(deps): bump django from 4.0.4 to 4.0.5 (#3019)
Bumps [django](https://github.com/django/django) from 4.0.4 to 4.0.5.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/4.0.4...4.0.5)

---
updated-dependencies:
- dependency-name: django
  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>
2022-06-02 11:13:24 +02:00
33fe85eb96 build(deps): bump golang from 1.18.2-bullseye to 1.18.3-bullseye (#3015)
Bumps golang from 1.18.2-bullseye to 1.18.3-bullseye.

---
updated-dependencies:
- dependency-name: golang
  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>
2022-06-02 11:13:17 +02:00
a9744cbf48 build(deps-dev): bump pylint from 2.13.9 to 2.14.0 (#3020)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.13.9 to 2.14.0.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.13.9...v2.14.0)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  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>
2022-06-02 11:12:56 +02:00
b91d8a676c build(deps): bump goauthentik.io/api/v3 from 3.2022053.3 to 3.2022053.4 (#3021)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2022053.3 to 3.2022053.4.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2022053.3...v3.2022053.4)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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>
2022-06-02 11:12:45 +02:00
f19cd1c003 build(deps): bump rollup from 2.75.4 to 2.75.5 in /web (#3016)
Bumps [rollup](https://github.com/rollup/rollup) from 2.75.4 to 2.75.5.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.75.4...v2.75.5)

---
updated-dependencies:
- dependency-name: rollup
  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>
2022-06-02 11:11:22 +02:00
65341cecd0 web: Update Web API Client version (#3013) 2022-06-01 23:23:31 +02:00
c0cb891078 stages/authenticator_sms: verify-only (#3011) 2022-06-01 23:16:28 +02:00
fc1c1a849a stages/*: use bound logger (#3012)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-06-01 23:01:58 +02:00
5a81ae956f build(deps): bump @sentry/browser from 6.19.4 to 7.0.0 in /web (#3008) 2022-06-01 11:15:52 +02:00
0cac034512 build(deps): bump goauthentik.io/api/v3 from 3.2022053.2 to 3.2022053.3 (#3010) 2022-06-01 09:30:54 +02:00
5666995a15 build(deps): bump country-flag-icons from 1.5.4 to 1.5.5 in /web (#3004) 2022-06-01 09:29:05 +02:00
8d3059e4f3 build(deps): bump rollup from 2.75.3 to 2.75.4 in /web (#3007) 2022-06-01 09:28:53 +02:00
a90dc34494 build(deps): bump lxml from 4.8.0 to 4.9.0 (#3009) 2022-06-01 09:28:44 +02:00
2c6d82593e root: cleanup session keys to use common format (#3003)
cleanup session keys to use common format

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-31 21:53:23 +02:00
34bcc2df1a root: disable session_save_every_request as it overwrites the session with old data
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2991
2022-05-31 20:46:27 +02:00
c00f2907ea web/elements: fix top-right dialog close button not resetting form
closes #2990

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-31 19:28:18 +02:00
b4d528a789 policies: fix incorrect bound_to count
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-31 10:16:09 +02:00
d9172cb296 Revert "build(deps): bump @sentry/browser from 6.19.4 to 7.0.0 in /web (#3002)"
This reverts commit 9c6be60ad9.
2022-05-31 10:10:57 +02:00
bee36cde59 Revert "build(deps): bump @sentry/tracing from 6.19.4 to 7.0.0 in /web (#2997)"
This reverts commit 7171706d7f.
2022-05-31 10:10:54 +02:00
d4e7d9d64a Translate '/web/src/locales/en.po' in 'zh_CN' (#2995)
Translate /web/src/locales/en.po in zh_CN

translation completed for the source file '/web/src/locales/en.po'
on the 'zh_CN' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-05-31 09:53:15 +02:00
7b0265207a Translate '/web/src/locales/en.po' in 'zh-Hans' (#2996)
Translate /web/src/locales/en.po in zh-Hans

translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-05-31 09:53:05 +02:00
7c076579fd build(deps): bump @typescript-eslint/parser from 5.26.0 to 5.27.0 in /web (#3000)
build(deps): bump @typescript-eslint/parser in /web

Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.26.0 to 5.27.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.27.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-05-31 09:50:32 +02:00
7171706d7f build(deps): bump @sentry/tracing from 6.19.4 to 7.0.0 in /web (#2997)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.19.4 to 7.0.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.19.4...7.0.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-31 09:50:20 +02:00
9cd46ecbeb build(deps): bump codemirror from 5.65.4 to 5.65.5 in /web (#2998)
Bumps [codemirror](https://github.com/codemirror/CodeMirror) from 5.65.4 to 5.65.5.
- [Release notes](https://github.com/codemirror/CodeMirror/releases)
- [Changelog](https://github.com/codemirror/CodeMirror/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codemirror/CodeMirror/compare/5.65.4...5.65.5)

---
updated-dependencies:
- dependency-name: codemirror
  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>
2022-05-31 09:50:06 +02:00
5f09ba675d build(deps): bump react-feather from 2.0.9 to 2.0.10 in /website (#2999)
Bumps [react-feather](https://github.com/feathericons/react-feather) from 2.0.9 to 2.0.10.
- [Release notes](https://github.com/feathericons/react-feather/releases)
- [Commits](https://github.com/feathericons/react-feather/commits)

---
updated-dependencies:
- dependency-name: react-feather
  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>
2022-05-31 09:48:32 +02:00
630b926e2a build(deps): bump @typescript-eslint/eslint-plugin from 5.26.0 to 5.27.0 in /web (#3001)
build(deps): bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.26.0 to 5.27.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.27.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-05-31 09:48:12 +02:00
9c6be60ad9 build(deps): bump @sentry/browser from 6.19.4 to 7.0.0 in /web (#3002)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 6.19.4 to 7.0.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.19.4...7.0.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-31 09:48:04 +02:00
a0397fdcf4 events: set default transport mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-30 21:32:48 +02:00
59e13e8026 website/docs: update docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-30 21:26:29 +02:00
374b51e956 web: Update Web API Client version (#2993)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-05-30 20:58:21 +02:00
8faa1bf865 events: add local transport mode (#2992)
* events: add local transport mode

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

* add default local transport

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-30 20:55:05 +02:00
fc75867218 events: ignore session model
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-30 20:23:07 +02:00
6d94c2c925 build(deps): bump @docusaurus/preset-classic from 2.0.0-beta.20 to 2.0.0-beta.21 in /website (#2983)
build(deps): bump @docusaurus/preset-classic in /website

Bumps [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) from 2.0.0-beta.20 to 2.0.0-beta.21.
- [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.21/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>
2022-05-30 09:58:59 +02:00
eb51dd1379 build(deps): bump rollup from 2.74.1 to 2.75.3 in /web (#2981)
Bumps [rollup](https://github.com/rollup/rollup) from 2.74.1 to 2.75.3.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.74.1...v2.75.3)

---
updated-dependencies:
- dependency-name: rollup
  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>
2022-05-30 09:51:43 +02:00
13a4559c37 build(deps): bump yaml from 2.1.0 to 2.1.1 in /web (#2982)
Bumps [yaml](https://github.com/eemeli/yaml) from 2.1.0 to 2.1.1.
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](https://github.com/eemeli/yaml/compare/v2.1.0...v2.1.1)

---
updated-dependencies:
- dependency-name: yaml
  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>
2022-05-30 09:51:33 +02:00
4fcf7285d7 build(deps): bump @docusaurus/plugin-client-redirects from 2.0.0-beta.20 to 2.0.0-beta.21 in /website (#2984)
build(deps): bump @docusaurus/plugin-client-redirects in /website

Bumps [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) from 2.0.0-beta.20 to 2.0.0-beta.21.
- [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.21/packages/docusaurus-plugin-client-redirects)

---
updated-dependencies:
- dependency-name: "@docusaurus/plugin-client-redirects"
  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>
2022-05-30 09:51:20 +02:00
0ba9f25155 build(deps-dev): bump selenium from 4.1.5 to 4.2.0 (#2985)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.1.5 to 4.2.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/commits/selenium-4.2.0)

---
updated-dependencies:
- dependency-name: selenium
  dependency-type: direct:development
  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>
2022-05-30 09:51:11 +02:00
453c751c7f build(deps): bump celery from 5.2.6 to 5.2.7 (#2986)
Bumps [celery](https://github.com/celery/celery) from 5.2.6 to 5.2.7.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/master/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.2.6...v5.2.7)

---
updated-dependencies:
- dependency-name: celery
  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>
2022-05-30 09:51:02 +02:00
d1eaaef254 build(deps): bump goauthentik.io/api/v3 from 3.2022052.6 to 3.2022053.2 (#2987)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2022052.6 to 3.2022053.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2022052.6...v3.2022053.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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>
2022-05-30 09:49:18 +02:00
3eb466ff4b lifecycle: cleanup prometheus (#2972)
* remove high cardinality labels

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

* retry worker number for prometheus multiprocess id

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

* revert to pid, use subdirectories

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

* cleanup more

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

* use worker id based off of https://github.com/benoitc/gunicorn/issues/1352

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

* fix missing app label

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

* tests/e2e: remove static names

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

* fix

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-29 21:45:25 +02:00
9f2529c886 stages/authentiactor_validate: cookies (#2978)
* stages/authenticator_validate: rewrite to use signed jwt cookie + expiry as MFA threshold

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

* add more tests

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

* add more tests

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-29 19:47:34 +02:00
fb25b28976 core: db sessions (#2979)
* use db session backend

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

* root: wrap session cookie in JWT and add useful claims

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

* fix compatibility with tests

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

* use standard session key for writing in sessions too

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-29 18:58:54 +02:00
612163b82f Translate '/web/src/locales/en.po' in 'zh_CN' (#2976)
Translate /web/src/locales/en.po in zh_CN

translation completed for the source file '/web/src/locales/en.po'
on the 'zh_CN' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-05-28 23:27:58 +02:00
3c43690a96 Translate '/web/src/locales/en.po' in 'zh-Hans' (#2977)
Translate /web/src/locales/en.po in zh-Hans

translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-05-28 23:27:45 +02:00
dd74565c7b web: Update Web API Client version (#2975)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-05-28 21:32:01 +02:00
fb69f67f47 *: cleanup vendor
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-28 21:26:33 +02:00
18b48684eb providers/oauth2: add configuration error event when wrong redirect uri is used in token request
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-28 21:15:58 +02:00
098b0aef6e *: use create_test_admin_user for all unittests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-28 21:13:16 +02:00
4ed8171130 web/user: fix static prompt fields being rendered with label
closes #2584

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-28 20:05:43 +02:00
335131affc web/user: improve ux for restarting user settings flow
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-28 19:07:49 +02:00
bba17a8a67 web: Update Web API Client version (#2974)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-05-28 13:23:01 +02:00
082df0ec51 Merge branch 'version-2022.5'
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	authentik/providers/oauth2/views/token.py
#	web/src/locales/zh-Hans.po
2022-05-28 13:19:58 +02:00
1883402b3d release: 2022.5.3 2022-05-28 12:04:26 +02:00
88a8b7d2fa outposts/ldap: fix type assertion after upgrading to new API Client
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-27 21:43:58 +02:00
987f03c4be website/docs: Update flow to run only during Github logins (#2959) 2022-05-27 21:43:55 +02:00
1b3aacfa1d providers/oauth2: add migration from "*" to ".*"
closes #2970

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-27 21:43:51 +02:00
a03dde8a90 outposts/ldap: fix type assertion after upgrading to new API Client
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-27 16:36:15 +02:00
5f04a187ea website/docs: Update flow to run only during Github logins (#2959) 2022-05-27 16:07:33 +02:00
2b68363452 providers/oauth2: add migration from "*" to ".*"
closes #2970

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-27 10:23:13 +02:00
3a994ab2a4 website/docs: prepare 2022.5.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 22:18:02 +02:00
d7713357f4 api: migrate to openapi generator v6 (#2968)
* migrate to openapi generator v6

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

* bump api

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
# Conflicts:
#	go.mod
#	go.sum
2022-05-26 22:17:57 +02:00
e7c03fdb14 web/admin: add note that regex is used for redirect URIs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 22:17:37 +02:00
6105956847 providers/oauth2: regex-escape URLs when set to blank
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 22:17:34 +02:00
89028f175a website/docs: Fix misconfiguration causing POST requests behing Nginx to timeout (#2967)
* Update _nginx_proxy_manager.md

* Update _nginx_standalone.md
2022-05-26 22:17:31 +02:00
f121098957 root: Add docker-compose postgresql and redis healthchecks (#2958)
* Add healthchecks to docker compose

Add healthchecks for postgresql and redis, see als #2519

* bump docker-compose version to 3.4
2022-05-26 22:17:10 +02:00
4ff32af343 flows: fix flakiness in tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 22:17:03 +02:00
972868c15c providers/oauth2: only set expiry on user when it was freshly created
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 22:16:55 +02:00
0bc57f571b api: update API browser to match admin UI and auto-switch theme
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 22:16:34 +02:00
9de5b6f93e build(deps): bump rapidoc from 9.2.0 to 9.3.2 in /web (#2957)
Bumps [rapidoc](https://github.com/rapi-doc/RapiDoc) from 9.2.0 to 9.3.2.
- [Release notes](https://github.com/rapi-doc/RapiDoc/releases)
- [Commits](https://github.com/rapi-doc/RapiDoc/compare/v9.2.0...v9.3.2)

---
updated-dependencies:
- dependency-name: rapidoc
  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>
2022-05-26 22:16:34 +02:00
acf1ded1d4 website/docs: prepare 2022.5.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 22:16:07 +02:00
a286f999e2 api: migrate to openapi generator v6 (#2968)
* migrate to openapi generator v6

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

* bump api

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 15:15:30 +02:00
4b6c1da51d web/admin: add note that regex is used for redirect URIs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 12:52:56 +02:00
a81d5a3d41 providers/oauth2: regex-escape URLs when set to blank
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 12:52:56 +02:00
4d17111233 website/docs: Fix misconfiguration causing POST requests behing Nginx to timeout (#2967)
* Update _nginx_proxy_manager.md

* Update _nginx_standalone.md
2022-05-26 11:52:57 +02:00
64cb9812e0 build(deps): bump @babel/plugin-transform-runtime from 7.18.0 to 7.18.2 in /web (#2962)
build(deps): bump @babel/plugin-transform-runtime in /web

Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.18.0 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  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>
2022-05-26 09:56:20 +02:00
ed037b2e3a build(deps): bump @babel/core from 7.18.0 to 7.18.2 in /web (#2963)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.0 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  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>
2022-05-26 09:56:10 +02:00
d2be6a8e3a root: Add docker-compose postgresql and redis healthchecks (#2958)
* Add healthchecks to docker compose

Add healthchecks for postgresql and redis, see als #2519

* bump docker-compose version to 3.4
2022-05-26 09:56:00 +02:00
a9667eb0f4 build(deps): bump chart.js from 3.7.1 to 3.8.0 in /web (#2960)
Bumps [chart.js](https://github.com/chartjs/Chart.js) from 3.7.1 to 3.8.0.
- [Release notes](https://github.com/chartjs/Chart.js/releases)
- [Commits](https://github.com/chartjs/Chart.js/compare/v3.7.1...v3.8.0)

---
updated-dependencies:
- dependency-name: chart.js
  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>
2022-05-26 09:54:33 +02:00
7f3988f3c9 build(deps): bump @babel/preset-env from 7.18.0 to 7.18.2 in /web (#2961)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.18.0 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  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>
2022-05-26 09:54:23 +02:00
4c095a6f2a build(deps): bump lit from 2.2.4 to 2.2.5 in /web (#2964)
Bumps [lit](https://github.com/lit/lit/tree/HEAD/packages/lit) from 2.2.4 to 2.2.5.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/lit/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/lit@2.2.5/packages/lit)

---
updated-dependencies:
- dependency-name: lit
  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>
2022-05-26 09:54:07 +02:00
c10b5c3c8c build(deps): bump @babel/plugin-proposal-decorators from 7.17.12 to 7.18.2 in /web (#2965)
build(deps): bump @babel/plugin-proposal-decorators in /web

Bumps [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) from 7.17.12 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/packages/babel-plugin-proposal-decorators)

---
updated-dependencies:
- dependency-name: "@babel/plugin-proposal-decorators"
  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>
2022-05-26 09:54:00 +02:00
9d920580a1 build(deps): bump github.com/imdario/mergo from 0.3.12 to 0.3.13 (#2966)
Bumps [github.com/imdario/mergo](https://github.com/imdario/mergo) from 0.3.12 to 0.3.13.
- [Release notes](https://github.com/imdario/mergo/releases)
- [Commits](https://github.com/imdario/mergo/compare/0.3.12...v0.3.13)

---
updated-dependencies:
- dependency-name: github.com/imdario/mergo
  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>
2022-05-26 09:53:51 +02:00
34ef4af799 flows: fix flakiness in tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-26 09:53:40 +02:00
5da47b69dd providers/oauth2: only set expiry on user when it was freshly created
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-25 23:02:33 +02:00
0e0dd2437b providers/oauth2: handle attribute errors when validation JWK contains private key
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-25 22:23:05 +02:00
e42386b150 api: update API browser to match admin UI and auto-switch theme
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-25 20:09:29 +02:00
f21f81022e build(deps): bump rapidoc from 9.2.0 to 9.3.2 in /web (#2957)
Bumps [rapidoc](https://github.com/rapi-doc/RapiDoc) from 9.2.0 to 9.3.2.
- [Release notes](https://github.com/rapi-doc/RapiDoc/releases)
- [Commits](https://github.com/rapi-doc/RapiDoc/compare/v9.2.0...v9.3.2)

---
updated-dependencies:
- dependency-name: rapidoc
  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>
2022-05-25 10:47:58 +02:00
e73a468921 build(deps): bump rapidoc from 9.2.0 to 9.3.2 in /website (#2956)
Bumps [rapidoc](https://github.com/rapi-doc/RapiDoc) from 9.2.0 to 9.3.2.
- [Release notes](https://github.com/rapi-doc/RapiDoc/releases)
- [Commits](https://github.com/rapi-doc/RapiDoc/compare/v9.2.0...v9.3.2)

---
updated-dependencies:
- dependency-name: rapidoc
  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>
2022-05-25 10:47:49 +02:00
c0ac053380 Translate '/web/src/locales/en.po' in 'zh_CN' (#2949)
Translate /web/src/locales/en.po in zh_CN

translation completed for the source file '/web/src/locales/en.po'
on the 'zh_CN' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-05-25 10:05:33 +02:00
4e670295d1 Translate '/web/src/locales/en.po' in 'zh-Hans' (#2950)
Translate /web/src/locales/en.po in zh-Hans

translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-05-25 10:05:24 +02:00
8d7d8d613c build(deps): bump typescript from 4.6.4 to 4.7.2 in /web (#2953)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.6.4 to 4.7.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.6.4...v4.7.2)

---
updated-dependencies:
- dependency-name: typescript
  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>
2022-05-25 10:04:22 +02:00
4d632a8679 build(deps): bump goauthentik.io/api/v3 from 3.2022052.2 to 3.2022052.5 (#2954)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2022052.2 to 3.2022052.5.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2022052.2...v3.2022052.5)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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>
2022-05-25 10:04:11 +02:00
ef219198d4 flows: fix lint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-25 00:05:04 +02:00
cc744dc581 flows: fix lint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-25 00:04:58 +02:00
47006fc9d2 website/docs: fix formatting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 23:38:15 +02:00
ada53362d5 website/docs: fix formatting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 23:38:02 +02:00
a03e48c5ce website/docs: prepare 2022.5.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 23:35:09 +02:00
816b0c7d83 flows: fix re-imports of entries with identical PK re-creating objects
closes #2941

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 23:35:06 +02:00
a6398f46da website/docs: prepare 2022.5.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 23:34:51 +02:00
56babb2649 flows: fix re-imports of entries with identical PK re-creating objects
closes #2941

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 23:32:08 +02:00
0edf4296c4 web/elements: fix used_by refreshing for all elements when using DeleteBulkForm
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 22:14:29 +02:00
b8fdda50ec ensure all viewsets have filter and search and add tests (#2946)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 22:13:59 +02:00
d25a051eae web/elements: fix used_by refreshing for all elements when using DeleteBulkForm
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 22:12:35 +02:00
4a9b788703 providers/oauth2: set related_name for many-to-many so used by detects the connection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 22:12:35 +02:00
d4ef321ac2 web: Update Web API Client version (#2948)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-05-24 22:03:17 +02:00
80c1dbdfbb ensure all viewsets have filter and search and add tests (#2946)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 22:01:18 +02:00
b0af062d74 web: Update Web API Client version (#2945)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-05-24 21:04:58 +02:00
b4e75218f5 sources/oauth: OIDC well-known and JWKS (#2936)
* add initial

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

* add provider

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

* include source and jwk key id in event

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

* add more docs

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

* add tests for source

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

* fix web formatting

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

* add provider tests

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

* fix lint error

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 21:02:50 +02:00
ab1840dd66 web: Update Web API Client version (#2944) 2022-05-24 20:05:06 +02:00
482491e93c core: fix username validator not allowing changes that can be done via flows
closes #2755

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-24 19:40:54 +02:00
2ca991ba3d website/docs: fix grammar (#2943) 2022-05-24 13:56:19 +02:00
b20c384f5a build(deps): bump @typescript-eslint/parser from 5.25.0 to 5.26.0 in /web (#2937)
build(deps): bump @typescript-eslint/parser in /web

Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.25.0 to 5.26.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.26.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-05-24 10:29:21 +02:00
9ce8edbcd6 build(deps): bump country-flag-icons from 1.5.2 to 1.5.4 in /web (#2938)
Bumps [country-flag-icons](https://gitlab.com/catamphetamine/country-flag-icons) from 1.5.2 to 1.5.4.
- [Release notes](https://gitlab.com/catamphetamine/country-flag-icons/tags)
- [Changelog](https://gitlab.com/catamphetamine/country-flag-icons/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/catamphetamine/country-flag-icons/compare/v1.5.2...v1.5.4)

---
updated-dependencies:
- dependency-name: country-flag-icons
  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>
2022-05-24 10:27:25 +02:00
cb5b2148a3 build(deps): bump @typescript-eslint/eslint-plugin from 5.25.0 to 5.26.0 in /web (#2939)
build(deps): bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.25.0 to 5.26.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.26.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-05-24 10:27:14 +02:00
d5702c6282 web/admin: fix broken flow execute link (#2940) 2022-05-24 10:26:58 +02:00
61a876b582 providers/saml: handle parse error
AUTHENTIK-1K5

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 22:03:12 +02:00
8c9748e4a0 providers/oauth2: improve error handling for invalid regular expressions
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 20:47:36 +02:00
6460245d5e website/docs: add missing docs for #2828
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 20:42:00 +02:00
b7979ad48e Revert "events: ignore silk SQLQuery object"
This reverts commit a26f25ccd6.

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 20:29:05 +02:00
cbd95848e7 web: decrease elements that refresh on global refresh signal
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 20:26:33 +02:00
4704de937a stages/user_write: fix typo in request context variable
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 20:18:37 +02:00
394d8e99a4 policies: improve error logging
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 20:18:00 +02:00
a26f25ccd6 events: ignore silk SQLQuery object
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 20:17:52 +02:00
94257e0f50 web/admin: refactor table refresh to preserve selected/expanded elements correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 20:07:56 +02:00
b2a42a68a4 web/admin: fix flow diagram not updating on flow changes
closes #2932

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-23 19:48:33 +02:00
7895d59da3 Translate '/web/src/locales/en.po' in 'zh_CN' (#2934)
Translate /web/src/locales/en.po in zh_CN

translation completed for the source file '/web/src/locales/en.po'
on the 'zh_CN' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-05-23 14:13:17 +02:00
b54c60d7af Translate '/web/src/locales/en.po' in 'zh-Hans' (#2935)
Translate /web/src/locales/en.po in zh-Hans

translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-05-23 14:13:08 +02:00
6bab3bf68e web/elements: fix missing click handler on wizard close button
closes #2931
2022-05-23 09:33:16 +00:00
fdc09c658a web/admin: fix phrasing on LDAP provider form for bind mode 2022-05-23 09:28:22 +00:00
a690a02f99 web/admin: fix display of LDAP bind mode
closes #2930
2022-05-23 09:24:57 +00:00
0e912fd647 build(deps): bump codemirror from 5.65.3 to 5.65.4 in /web (#2923) 2022-05-23 09:11:23 +02:00
27af330932 build(deps): bump eslint from 8.15.0 to 8.16.0 in /web (#2924) 2022-05-23 09:11:12 +02:00
7187d28905 build(deps): bump country-flag-icons from 1.4.26 to 1.5.2 in /web (#2925) 2022-05-23 09:10:18 +02:00
ca832b6090 build(deps-dev): bump importlib-metadata from 4.11.3 to 4.11.4 (#2926) 2022-05-23 09:10:03 +02:00
53bd6bf06e build(deps-dev): bump coverage from 6.3.3 to 6.4 (#2927) 2022-05-23 09:09:49 +02:00
813f271bdd build(deps): bump goauthentik.io/api/v3 from 3.2022041.10 to 3.2022052.2 (#2928) 2022-05-23 09:09:31 +02:00
63dc8fe7dc crypto: set SAN in default generated Certificate to semi-random domain
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2462
2022-05-22 23:22:06 +02:00
383f4e4dcf root: exempt question for stale
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-22 22:56:29 +02:00
2896652fef web: Update Web API Client version (#2922)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-05-22 19:36:17 +02:00
cfe2648b62 events: fix transport not allowing blank values
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-22 19:32:58 +02:00
8d49705c87 web/admin: add set password button to user view page
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-22 16:46:38 +02:00
c99e6d8f2c website: fix typo in title
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-05-21 19:10:16 +02:00
0996bb500c web: Update Web API Client version (#2920) 2022-05-21 18:07:18 +02:00
699 changed files with 22917 additions and 10555 deletions

View File

@ -1,30 +1,18 @@
[bumpversion] [bumpversion]
current_version = 2022.5.2 current_version = 2022.7.3
tag = True tag = True
commit = True commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*) parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
serialize = serialize = {major}.{minor}.{patch}
{major}.{minor}.{patch}-{release}
{major}.{minor}.{patch}
message = release: {new_version} message = release: {new_version}
tag_name = version/{new_version} tag_name = version/{new_version}
[bumpversion:part:release]
optional_value = stable
first_value = beta
values =
alpha
beta
stable
[bumpversion:file:pyproject.toml] [bumpversion:file:pyproject.toml]
[bumpversion:file:docker-compose.yml] [bumpversion:file:docker-compose.yml]
[bumpversion:file:schema.yml] [bumpversion:file:schema.yml]
[bumpversion:file:.github/workflows/release-publish.yml]
[bumpversion:file:authentik/__init__.py] [bumpversion:file:authentik/__init__.py]
[bumpversion:file:internal/constants/constants.go] [bumpversion:file:internal/constants/constants.go]

View File

@ -17,6 +17,12 @@ outputs:
sha: sha:
description: "sha" description: "sha"
value: ${{ steps.ev.outputs.sha }} value: ${{ steps.ev.outputs.sha }}
version:
description: "version"
value: ${{ steps.ev.outputs.version }}
versionFamily:
description: "versionFamily"
value: ${{ steps.ev.outputs.versionFamily }}
runs: runs:
using: "composite" using: "composite"
@ -47,3 +53,11 @@ runs:
print("##[set-output name=timestamp]%s" % int(time())) print("##[set-output name=timestamp]%s" % int(time()))
print("##[set-output name=sha]%s" % os.environ[sha]) print("##[set-output name=sha]%s" % os.environ[sha])
print("##[set-output name=shouldBuild]%s" % should_build) print("##[set-output name=shouldBuild]%s" % should_build)
import configparser
parser = configparser.ConfigParser()
parser.read(".bumpversion.cfg")
version = parser.get("bumpversion", "current_version")
version_family = ".".join(version.split(".")[:-1])
print("##[set-output name=version]%s" % version)
print("##[set-output name=versionFamily]%s" % version_family)

108
.github/dependabot.yml vendored
View File

@ -1,50 +1,62 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/" directory: "/"
schedule: schedule:
interval: daily interval: daily
time: "04:00" time: "04:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10
assignees: reviewers:
- BeryJu - "@goauthentik/core"
- package-ecosystem: gomod commit-message:
directory: "/" prefix: "ci:"
schedule: - package-ecosystem: gomod
interval: daily directory: "/"
time: "04:00" schedule:
open-pull-requests-limit: 10 interval: daily
assignees: time: "04:00"
- BeryJu open-pull-requests-limit: 10
- package-ecosystem: npm reviewers:
directory: "/web" - "@goauthentik/core"
schedule: commit-message:
interval: daily prefix: "core:"
time: "04:00" - package-ecosystem: npm
open-pull-requests-limit: 10 directory: "/web"
assignees: schedule:
- BeryJu interval: daily
- package-ecosystem: npm time: "04:00"
directory: "/website" open-pull-requests-limit: 10
schedule: reviewers:
interval: daily - "@goauthentik/core"
time: "04:00" commit-message:
open-pull-requests-limit: 10 prefix: "web:"
assignees: - package-ecosystem: npm
- BeryJu directory: "/website"
- package-ecosystem: pip schedule:
directory: "/" interval: daily
schedule: time: "04:00"
interval: daily open-pull-requests-limit: 10
time: "04:00" reviewers:
open-pull-requests-limit: 10 - "@goauthentik/core"
assignees: commit-message:
- BeryJu prefix: "website:"
- package-ecosystem: docker - package-ecosystem: pip
directory: "/" directory: "/"
schedule: schedule:
interval: daily interval: daily
time: "04:00" time: "04:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10
assignees: reviewers:
- BeryJu - "@goauthentik/core"
commit-message:
prefix: "core:"
- package-ecosystem: docker
directory: "/"
schedule:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
reviewers:
- "@goauthentik/core"
commit-message:
prefix: "core:"

View File

@ -1,7 +1,7 @@
<!-- <!--
👋 Hello there! Welcome. 👋 Hello there! Welcome.
Please check the [Contributing guidelines](https://github.com/goauthentik/authentik/blob/master/CONTRIBUTING.md#how-can-i-contribute). Please check the [Contributing guidelines](https://github.com/goauthentik/authentik/blob/main/CONTRIBUTING.md#how-can-i-contribute).
--> -->
# Details # Details

1
.github/stale.yml vendored
View File

@ -10,6 +10,7 @@ exemptLabels:
- enhancement - enhancement
- bug/confirmed - bug/confirmed
- enhancement/confirmed - enhancement/confirmed
- question
# Comment to post when marking an issue as stale. Set to `false` to disable # Comment to post when marking an issue as stale. Set to `false` to disable
markComment: > markComment: >
This issue has been automatically marked as stale because it has not had This issue has been automatically marked as stale because it has not had

View File

@ -3,14 +3,14 @@ name: authentik-ci-main
on: on:
push: push:
branches: branches:
- master - main
- next - next
- version-* - version-*
paths-ignore: paths-ignore:
- website - website
pull_request: pull_request:
branches: branches:
- master - main
env: env:
POSTGRES_DB: authentik POSTGRES_DB: authentik
@ -106,7 +106,7 @@ jobs:
with: with:
domain: ${{github.repository_owner}} domain: ${{github.repository_owner}}
- name: Create k8s Kind Cluster - name: Create k8s Kind Cluster
uses: helm/kind-action@v1.2.0 uses: helm/kind-action@v1.3.0
- name: run integration - name: run integration
run: | run: |
poetry run make test-integration poetry run make test-integration
@ -133,12 +133,13 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: web/dist path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/**') }} key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**') }}
- name: prepare web ui - name: prepare web ui
if: steps.cache-web.outputs.cache-hit != 'true' if: steps.cache-web.outputs.cache-hit != 'true'
working-directory: web working-directory: web
run: | run: |
npm ci npm ci
make -C .. gen-client-web
npm run build npm run build
- name: run e2e - name: run e2e
run: | run: |
@ -166,12 +167,13 @@ jobs:
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: web/dist path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/**') }} key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**') }}
- name: prepare web ui - name: prepare web ui
if: steps.cache-web.outputs.cache-hit != 'true' if: steps.cache-web.outputs.cache-hit != 'true'
working-directory: web/ working-directory: web/
run: | run: |
npm ci npm ci
make -C .. gen-client-web
npm run build npm run build
- name: run e2e - name: run e2e
run: | run: |
@ -211,10 +213,10 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: prepare variables - name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev id: ev
env: env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
uses: ./.github/actions/docker-setup
- name: Login to Container Registry - name: Login to Container Registry
uses: docker/login-action@v2 uses: docker/login-action@v2
if: ${{ steps.ev.outputs.shouldBuild == 'true' }} if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
@ -231,4 +233,5 @@ jobs:
ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.sha }} ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.sha }}
build-args: | build-args: |
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }} GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
platforms: ${{ matrix.arch }} platforms: ${{ matrix.arch }}

View File

@ -3,12 +3,12 @@ name: authentik-ci-outpost
on: on:
push: push:
branches: branches:
- master - main
- next - next
- version-* - version-*
pull_request: pull_request:
branches: branches:
- master - main
jobs: jobs:
lint-golint: lint-golint:
@ -67,8 +67,8 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: prepare variables - name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev id: ev
uses: ./.github/actions/docker-setup
env: env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
- name: Login to Container Registry - name: Login to Container Registry
@ -91,6 +91,7 @@ jobs:
file: ${{ matrix.type }}.Dockerfile file: ${{ matrix.type }}.Dockerfile
build-args: | build-args: |
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }} GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
platforms: ${{ matrix.arch }} platforms: ${{ matrix.arch }}
build-outpost-binary: build-outpost-binary:
timeout-minutes: 120 timeout-minutes: 120
@ -110,7 +111,7 @@ jobs:
- uses: actions/setup-go@v3 - uses: actions/setup-go@v3
with: with:
go-version: "^1.17" go-version: "^1.17"
- uses: actions/setup-node@v3.2.0 - uses: actions/setup-node@v3.4.1
with: with:
node-version: '16' node-version: '16'
cache: 'npm' cache: 'npm'

View File

@ -3,19 +3,19 @@ name: authentik-ci-web
on: on:
push: push:
branches: branches:
- master - main
- next - next
- version-* - version-*
pull_request: pull_request:
branches: branches:
- master - main
jobs: jobs:
lint-eslint: lint-eslint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v3.2.0 - uses: actions/setup-node@v3.4.1
with: with:
node-version: '16' node-version: '16'
cache: 'npm' cache: 'npm'
@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v3.2.0 - uses: actions/setup-node@v3.4.1
with: with:
node-version: '16' node-version: '16'
cache: 'npm' cache: 'npm'
@ -47,13 +47,18 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v3.2.0 - uses: actions/setup-node@v3.4.1
with: with:
node-version: '16' node-version: '16'
cache: 'npm' cache: 'npm'
cache-dependency-path: web/package-lock.json cache-dependency-path: web/package-lock.json
- working-directory: web/ - working-directory: web/
run: npm ci run: |
npm ci
# lit-analyse doesn't understand path rewrites, so make it
# belive it's an actual module
cd node_modules/@goauthentik
ln -s ../../src/ web
- name: Generate API - name: Generate API
run: make gen-client-web run: make gen-client-web
- name: lit-analyse - name: lit-analyse
@ -73,7 +78,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v3.2.0 - uses: actions/setup-node@v3.4.1
with: with:
node-version: '16' node-version: '16'
cache: 'npm' cache: 'npm'

View File

@ -3,19 +3,19 @@ name: authentik-ci-website
on: on:
push: push:
branches: branches:
- master - main
- next - next
- version-* - version-*
pull_request: pull_request:
branches: branches:
- master - main
jobs: jobs:
lint-prettier: lint-prettier:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v3.2.0 - uses: actions/setup-node@v3.4.1
with: with:
node-version: '16' node-version: '16'
cache: 'npm' cache: 'npm'

View File

@ -2,10 +2,10 @@ name: "CodeQL"
on: on:
push: push:
branches: [ master, '*', next, version* ] branches: [ main, '*', next, version* ]
pull_request: pull_request:
# The branches below must be a subset of the branches above # The branches below must be a subset of the branches above
branches: [ master ] branches: [ main ]
schedule: schedule:
- cron: '30 6 * * 5' - cron: '30 6 * * 5'

View File

@ -19,4 +19,4 @@ jobs:
org-name: goauthentik org-name: goauthentik
untagged-only: false untagged-only: false
token: ${{ secrets.GHCR_CLEANUP_TOKEN }} token: ${{ secrets.GHCR_CLEANUP_TOKEN }}
skip-tags: gh-next,gh-master skip-tags: gh-next,gh-main

View File

@ -5,7 +5,6 @@ on:
types: [published, created] types: [published, created]
jobs: jobs:
# Build
build-server: build-server:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -14,6 +13,9 @@ jobs:
uses: docker/setup-qemu-action@v2.0.0 uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
- name: Docker Login Registry - name: Docker Login Registry
uses: docker/login-action@v2 uses: docker/login-action@v2
with: with:
@ -30,9 +32,11 @@ jobs:
with: with:
push: ${{ github.event_name == 'release' }} push: ${{ github.event_name == 'release' }}
tags: | tags: |
beryju/authentik:2022.5.2, beryju/authentik:${{ steps.ev.outputs.version }},
beryju/authentik:${{ steps.ev.outputs.versionFamily }},
beryju/authentik:latest, beryju/authentik:latest,
ghcr.io/goauthentik/server:2022.5.2, ghcr.io/goauthentik/server:${{ steps.ev.outputs.version }},
ghcr.io/goauthentik/server:${{ steps.ev.outputs.versionFamily }},
ghcr.io/goauthentik/server:latest ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
context: . context: .
@ -53,6 +57,9 @@ jobs:
uses: docker/setup-qemu-action@v2.0.0 uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
- name: Docker Login Registry - name: Docker Login Registry
uses: docker/login-action@v2 uses: docker/login-action@v2
with: with:
@ -69,9 +76,11 @@ jobs:
with: with:
push: ${{ github.event_name == 'release' }} push: ${{ github.event_name == 'release' }}
tags: | tags: |
beryju/authentik-${{ matrix.type }}:2022.5.2, beryju/authentik-${{ matrix.type }}:${{ steps.ev.outputs.version }},
beryju/authentik-${{ matrix.type }}:${{ steps.ev.outputs.versionFamily }},
beryju/authentik-${{ matrix.type }}:latest, beryju/authentik-${{ matrix.type }}:latest,
ghcr.io/goauthentik/${{ matrix.type }}:2022.5.2, ghcr.io/goauthentik/${{ matrix.type }}:${{ steps.ev.outputs.version }},
ghcr.io/goauthentik/${{ matrix.type }}:${{ steps.ev.outputs.versionFamily }},
ghcr.io/goauthentik/${{ matrix.type }}:latest ghcr.io/goauthentik/${{ matrix.type }}:latest
file: ${{ matrix.type }}.Dockerfile file: ${{ matrix.type }}.Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
@ -91,7 +100,7 @@ jobs:
- uses: actions/setup-go@v3 - uses: actions/setup-go@v3
with: with:
go-version: "^1.17" go-version: "^1.17"
- uses: actions/setup-node@v3.2.0 - uses: actions/setup-node@v3.4.1
with: with:
node-version: '16' node-version: '16'
cache: 'npm' cache: 'npm'
@ -138,6 +147,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: prepare variables
uses: ./.github/actions/docker-push-variables
id: ev
- name: Get static files from docker image - name: Get static files from docker image
run: | run: |
docker pull ghcr.io/goauthentik/server:latest docker pull ghcr.io/goauthentik/server:latest
@ -152,7 +164,7 @@ jobs:
SENTRY_PROJECT: authentik SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org SENTRY_URL: https://sentry.beryju.org
with: with:
version: authentik@2022.5.2 version: authentik@${{ steps.ev.outputs.version }}
environment: beryjuorg-prod environment: beryjuorg-prod
sourcemaps: './web/dist' sourcemaps: './web/dist'
url_prefix: '~/static/dist' url_prefix: '~/static/dist'

View File

@ -1,7 +1,7 @@
name: authentik-backend-translate-compile name: authentik-backend-translate-compile
on: on:
push: push:
branches: [ master ] branches: [ main ]
paths: paths:
- '/locale/' - '/locale/'
pull_request: pull_request:

View File

@ -1,7 +1,7 @@
name: authentik-web-api-publish name: authentik-web-api-publish
on: on:
push: push:
branches: [ master ] branches: [ main ]
paths: paths:
- 'schema.yml' - 'schema.yml'
workflow_dispatch: workflow_dispatch:
@ -11,7 +11,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
# Setup .npmrc file to publish to npm # Setup .npmrc file to publish to npm
- uses: actions/setup-node@v3.2.0 - uses: actions/setup-node@v3.4.1
with: with:
node-version: '16' node-version: '16'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'

1
.gitignore vendored
View File

@ -193,7 +193,6 @@ pip-selfcheck.json
# End of https://www.gitignore.io/api/python,django # End of https://www.gitignore.io/api/python,django
/static/ /static/
local.env.yml local.env.yml
.vscode/
# Selenium Screenshots # Selenium Screenshots
selenium_screenshots/ selenium_screenshots/

View File

@ -1,5 +1,6 @@
{ {
"cSpell.words": [ "cSpell.words": [
"akadmin",
"asgi", "asgi",
"authentik", "authentik",
"authn", "authn",
@ -21,5 +22,9 @@
"python.formatting.provider": "black", "python.formatting.provider": "black",
"files.associations": { "files.associations": {
"*.akflow": "json" "*.akflow": "json"
} },
"typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifierEnding": "index",
"typescript.tsdk": "./web/node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
} }

86
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,86 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "authentik[core]: format & test",
"command": "poetry",
"args": [
"run",
"make"
],
"group": "build",
},
{
"label": "authentik[core]: run",
"command": "poetry",
"args": [
"run",
"make",
"run",
],
"group": "build",
"presentation": {
"panel": "dedicated",
"group": "running"
},
},
{
"label": "authentik[web]: format",
"command": "make",
"args": ["web"],
"group": "build",
},
{
"label": "authentik[web]: watch",
"command": "make",
"args": ["web-watch"],
"group": "build",
"presentation": {
"panel": "dedicated",
"group": "running"
},
},
{
"label": "authentik: install",
"command": "make",
"args": ["install"],
"group": "build",
},
{
"label": "authentik: i18n-extract",
"command": "poetry",
"args": [
"run",
"make",
"i18n-extract"
],
"group": "build",
},
{
"label": "authentik[website]: format",
"command": "make",
"args": ["website"],
"group": "build",
},
{
"label": "authentik[website]: watch",
"command": "make",
"args": ["website-watch"],
"group": "build",
"presentation": {
"panel": "dedicated",
"group": "running"
},
},
{
"label": "authentik[api]: generate",
"command": "poetry",
"args": [
"run",
"make",
"gen"
],
"group": "build"
},
]
}

View File

@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement at
hello@beryju.org. hello@goauthentik.io.
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the

View File

@ -18,7 +18,7 @@ WORKDIR /work/web
RUN npm ci && npm run build RUN npm ci && npm run build
# Stage 3: Poetry to requirements.txt export # Stage 3: Poetry to requirements.txt export
FROM docker.io/python:3.10.4-slim-bullseye AS poetry-locker FROM docker.io/python:3.10.5-slim-bullseye AS poetry-locker
WORKDIR /work WORKDIR /work
COPY ./pyproject.toml /work COPY ./pyproject.toml /work
@ -29,7 +29,7 @@ RUN pip install --no-cache-dir poetry && \
poetry export -f requirements.txt --dev --output requirements-dev.txt poetry export -f requirements.txt --dev --output requirements-dev.txt
# Stage 4: Build go proxy # Stage 4: Build go proxy
FROM docker.io/golang:1.18.2-bullseye AS builder FROM docker.io/golang:1.18.4-bullseye AS builder
WORKDIR /work WORKDIR /work
@ -45,7 +45,7 @@ COPY ./go.sum /work/go.sum
RUN go build -o /work/authentik ./cmd/server/main.go RUN go build -o /work/authentik ./cmd/server/main.go
# Stage 5: Run # Stage 5: Run
FROM docker.io/python:3.10.4-slim-bullseye FROM docker.io/python:3.10.5-slim-bullseye
LABEL org.opencontainers.image.url https://goauthentik.io LABEL org.opencontainers.image.url https://goauthentik.io
LABEL org.opencontainers.image.description goauthentik.io Main server image, see https://goauthentik.io for more info. LABEL org.opencontainers.image.description goauthentik.io Main server image, see https://goauthentik.io for more info.

View File

@ -45,8 +45,8 @@ lint-fix:
website/developer-docs website/developer-docs
lint: lint:
bandit -r authentik tests lifecycle -x node_modules
pylint authentik tests lifecycle pylint authentik tests lifecycle
bandit -r authentik tests lifecycle -x node_modules
golangci-lint run -v golangci-lint run -v
i18n-extract: i18n-extract-core web-extract i18n-extract: i18n-extract-core web-extract
@ -55,7 +55,7 @@ i18n-extract-core:
./manage.py makemessages --ignore web --ignore internal --ignore web --ignore web-api --ignore website -l en ./manage.py makemessages --ignore web --ignore internal --ignore web --ignore web-api --ignore website -l en
gen-build: gen-build:
./manage.py spectacular --file schema.yml AUTHENTIK_DEBUG=true ./manage.py spectacular --file schema.yml
gen-clean: gen-clean:
rm -rf web/api/src/ rm -rf web/api/src/
@ -65,7 +65,7 @@ gen-client-web:
docker run \ docker run \
--rm -v ${PWD}:/local \ --rm -v ${PWD}:/local \
--user ${UID}:${GID} \ --user ${UID}:${GID} \
openapitools/openapi-generator-cli:v6.0.0-beta generate \ openapitools/openapi-generator-cli:v6.0.0 generate \
-i /local/schema.yml \ -i /local/schema.yml \
-g typescript-fetch \ -g typescript-fetch \
-o /local/gen-ts-api \ -o /local/gen-ts-api \
@ -83,7 +83,7 @@ gen-client-go:
docker run \ docker run \
--rm -v ${PWD}:/local \ --rm -v ${PWD}:/local \
--user ${UID}:${GID} \ --user ${UID}:${GID} \
openapitools/openapi-generator-cli:v5.2.1 generate \ openapitools/openapi-generator-cli:v6.0.0 generate \
-i /local/schema.yml \ -i /local/schema.yml \
-g go \ -g go \
-o /local/gen-go-api \ -o /local/gen-go-api \
@ -103,12 +103,18 @@ run:
## Web ## Web
######################### #########################
web: web-lint-fix web-lint web-extract web-build: web-install
cd web && npm run build
web: web-lint-fix web-lint
web-install: web-install:
cd web && npm ci cd web && npm ci
web-watch: web-watch:
rm -rf web/dist/
mkdir web/dist/
touch web/dist/.gitkeep
cd web && npm run watch cd web && npm run watch
web-lint-fix: web-lint-fix:
@ -163,8 +169,3 @@ ci-pending-migrations: ci--meta-debug
install: web-install website-install install: web-install website-install
poetry install poetry install
a: install
tmux \
new-session 'make run' \; \
split-window 'make web-watch'

View File

@ -9,7 +9,7 @@
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-outpost?label=outpost%20build&style=for-the-badge)](https://github.com/goauthentik/authentik/actions/workflows/ci-outpost.yml) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-outpost?label=outpost%20build&style=for-the-badge)](https://github.com/goauthentik/authentik/actions/workflows/ci-outpost.yml)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-web?label=web%20build&style=for-the-badge)](https://github.com/goauthentik/authentik/actions/workflows/ci-web.yml) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-web?label=web%20build&style=for-the-badge)](https://github.com/goauthentik/authentik/actions/workflows/ci-web.yml)
[![Code Coverage](https://img.shields.io/codecov/c/gh/goauthentik/authentik?style=for-the-badge)](https://codecov.io/gh/goauthentik/authentik) [![Code Coverage](https://img.shields.io/codecov/c/gh/goauthentik/authentik?style=for-the-badge)](https://codecov.io/gh/goauthentik/authentik)
[![Testspace tests](https://img.shields.io/testspace/total/goauthentik/goauthentik:authentik/master?style=for-the-badge)](https://goauthentik.testspace.com/) [![Testspace tests](https://img.shields.io/testspace/total/goauthentik/goauthentik:authentik/main?style=for-the-badge)](https://goauthentik.testspace.com/)
![Docker pulls](https://img.shields.io/docker/pulls/beryju/authentik.svg?style=for-the-badge) ![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) ![Latest version](https://img.shields.io/docker/v/beryju/authentik?sort=semver&style=for-the-badge)
[![](https://img.shields.io/badge/Help%20translate-transifex-blue?style=for-the-badge)](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/)

View File

@ -6,9 +6,10 @@
| Version | Supported | | Version | Supported |
| ---------- | ------------------ | | ---------- | ------------------ |
| 2022.3.x | :white_check_mark: | | 2022.5.x | :white_check_mark: |
| 2022.4.x | :white_check_mark: | | 2022.6.x | :white_check_mark: |
| 2022.7.x | :white_check_mark: |
## Reporting a Vulnerability ## Reporting a Vulnerability
To report a vulnerability, send an email to [security@beryju.org](mailto:security@beryju.org) To report a vulnerability, send an email to [security@goauthentik.io](mailto:security@goauthentik.io)

View File

@ -2,7 +2,7 @@
from os import environ from os import environ
from typing import Optional from typing import Optional
__version__ = "2022.5.2" __version__ = "2022.7.3"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -1,7 +1,6 @@
"""authentik administration overview""" """authentik administration overview"""
from django.conf import settings from django.conf import settings
from drf_spectacular.utils import extend_schema, inline_serializer from drf_spectacular.utils import extend_schema, inline_serializer
from prometheus_client import Gauge
from rest_framework.fields import IntegerField from rest_framework.fields import IntegerField
from rest_framework.permissions import IsAdminUser from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request from rest_framework.request import Request
@ -10,8 +9,6 @@ from rest_framework.views import APIView
from authentik.root.celery import CELERY_APP from authentik.root.celery import CELERY_APP
GAUGE_WORKERS = Gauge("authentik_admin_workers", "Currently connected workers")
class WorkerView(APIView): class WorkerView(APIView):
"""Get currently connected worker count.""" """Get currently connected worker count."""

View File

@ -2,6 +2,10 @@
from importlib import import_module from importlib import import_module
from django.apps import AppConfig from django.apps import AppConfig
from prometheus_client import Gauge, Info
PROM_INFO = Info("authentik_version", "Currently running authentik version")
GAUGE_WORKERS = Gauge("authentik_admin_workers", "Currently connected workers")
class AuthentikAdminConfig(AppConfig): class AuthentikAdminConfig(AppConfig):
@ -12,7 +16,4 @@ class AuthentikAdminConfig(AppConfig):
verbose_name = "authentik Admin" verbose_name = "authentik Admin"
def ready(self): def ready(self):
from authentik.admin.tasks import clear_update_notifications
clear_update_notifications.delay()
import_module("authentik.admin.signals") import_module("authentik.admin.signals")

View File

@ -2,7 +2,7 @@
from django.dispatch import receiver from django.dispatch import receiver
from authentik.admin.api.tasks import TaskInfo from authentik.admin.api.tasks import TaskInfo
from authentik.admin.api.workers import GAUGE_WORKERS from authentik.admin.apps import GAUGE_WORKERS
from authentik.root.celery import CELERY_APP from authentik.root.celery import CELERY_APP
from authentik.root.monitoring import monitoring_set from authentik.root.monitoring import monitoring_set

View File

@ -4,11 +4,11 @@ import re
from django.core.cache import cache from django.core.cache import cache
from django.core.validators import URLValidator from django.core.validators import URLValidator
from packaging.version import parse from packaging.version import parse
from prometheus_client import Info
from requests import RequestException from requests import RequestException
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik import __version__, get_build_hash from authentik import __version__, get_build_hash
from authentik.admin.apps import PROM_INFO
from authentik.events.models import Event, EventAction, Notification from authentik.events.models import Event, EventAction, Notification
from authentik.events.monitored_tasks import ( from authentik.events.monitored_tasks import (
MonitoredTask, MonitoredTask,
@ -25,7 +25,6 @@ VERSION_CACHE_KEY = "authentik_latest_version"
VERSION_CACHE_TIMEOUT = 8 * 60 * 60 # 8 hours VERSION_CACHE_TIMEOUT = 8 * 60 * 60 # 8 hours
# Chop of the first ^ because we want to search the entire string # Chop of the first ^ because we want to search the entire string
URL_FINDER = URLValidator.regex.pattern[1:] URL_FINDER = URLValidator.regex.pattern[1:]
PROM_INFO = Info("authentik_version", "Currently running authentik version")
LOCAL_VERSION = parse(__version__) LOCAL_VERSION = parse(__version__)

View File

@ -10,6 +10,8 @@ from structlog.stdlib import get_logger
from authentik.core.middleware import KEY_AUTH_VIA, LOCAL from authentik.core.middleware import KEY_AUTH_VIA, LOCAL
from authentik.core.models import Token, TokenIntents, User from authentik.core.models import Token, TokenIntents, User
from authentik.outposts.models import Outpost from authentik.outposts.models import Outpost
from authentik.providers.oauth2.constants import SCOPE_AUTHENTIK_API
from authentik.providers.oauth2.models import RefreshToken
LOGGER = get_logger() LOGGER = get_logger()
@ -24,7 +26,7 @@ def validate_auth(header: bytes) -> str:
if auth_type.lower() != "bearer": if auth_type.lower() != "bearer":
LOGGER.debug("Unsupported authentication type, denying", type=auth_type.lower()) LOGGER.debug("Unsupported authentication type, denying", type=auth_type.lower())
raise AuthenticationFailed("Unsupported authentication type") raise AuthenticationFailed("Unsupported authentication type")
if auth_credentials == "": # nosec if auth_credentials == "": # nosec # noqa
raise AuthenticationFailed("Malformed header") raise AuthenticationFailed("Malformed header")
return auth_credentials return auth_credentials
@ -34,14 +36,30 @@ def bearer_auth(raw_header: bytes) -> Optional[User]:
auth_credentials = validate_auth(raw_header) auth_credentials = validate_auth(raw_header)
if not auth_credentials: if not auth_credentials:
return None return None
if not hasattr(LOCAL, "authentik"):
LOCAL.authentik = {}
# first, check traditional tokens # first, check traditional tokens
token = Token.filter_not_expired(key=auth_credentials, intent=TokenIntents.INTENT_API).first() key_token = Token.filter_not_expired(
if hasattr(LOCAL, "authentik"): key=auth_credentials, intent=TokenIntents.INTENT_API
).first()
if key_token:
LOCAL.authentik[KEY_AUTH_VIA] = "api_token" LOCAL.authentik[KEY_AUTH_VIA] = "api_token"
if token: return key_token.user
return token.user # then try to auth via JWT
jwt_token = RefreshToken.filter_not_expired(
refresh_token=auth_credentials, _scope__icontains=SCOPE_AUTHENTIK_API
).first()
if jwt_token:
# Double-check scopes, since they are saved in a single string
# we want to check the parsed version too
if SCOPE_AUTHENTIK_API not in jwt_token.scope:
raise AuthenticationFailed("Token invalid/expired")
LOCAL.authentik[KEY_AUTH_VIA] = "jwt"
return jwt_token.user
# then try to auth via secret key (for embedded outpost/etc)
user = token_secret_key(auth_credentials) user = token_secret_key(auth_credentials)
if user: if user:
LOCAL.authentik[KEY_AUTH_VIA] = "secret_key"
return user return user
raise AuthenticationFailed("Token invalid/expired") raise AuthenticationFailed("Token invalid/expired")
@ -56,8 +74,6 @@ def token_secret_key(value: str) -> Optional[User]:
outposts = Outpost.objects.filter(managed=MANAGED_OUTPOST) outposts = Outpost.objects.filter(managed=MANAGED_OUTPOST)
if not outposts: if not outposts:
return None return None
if hasattr(LOCAL, "authentik"):
LOCAL.authentik[KEY_AUTH_VIA] = "secret_key"
outpost = outposts.first() outpost = outposts.first()
return outpost.user return outpost.user

View File

@ -8,9 +8,6 @@ API Browser - {{ tenant.branding_title }}
{% block head %} {% block head %}
<script type="module" src="{% static 'dist/rapidoc-min.js' %}"></script> <script type="module" src="{% static 'dist/rapidoc-min.js' %}"></script>
{% endblock %}
{% block body %}
<script> <script>
function getCookie(name) { function getCookie(name) {
let cookieValue = ""; let cookieValue = "";
@ -34,16 +31,58 @@ window.addEventListener('DOMContentLoaded', (event) => {
}); });
}); });
</script> </script>
<style>
img.logo {
width: 100%;
padding: 1rem 0.5rem 1.5rem 0.5rem;
min-height: 48px;
}
</style>
{% endblock %}
{% block body %}
<rapi-doc <rapi-doc
spec-url="{{ path }}" spec-url="{{ path }}"
heading-text="authentik" heading-text=""
theme="dark" theme="light"
render-style="view" render-style="read"
default-schema-tab="schema"
primary-color="#fd4b2d" primary-color="#fd4b2d"
nav-bg-color="#212427"
bg-color="#000000"
text-color="#000000"
nav-text-color="#ffffff"
nav-hover-bg-color="#3c3f42"
nav-accent-color="#4f5255"
nav-hover-text-color="#ffffff"
use-path-in-nav-bar="true"
nav-item-spacing="relaxed"
allow-server-selection="false"
show-header="false"
allow-spec-url-load="false" allow-spec-url-load="false"
allow-spec-file-load="false"> allow-spec-file-load="false">
<div slot="logo"> <div slot="nav-logo">
<img src="{% static 'dist/assets/icons/icon.png' %}" style="width:50px; height:50px" /> <img class="logo" src="{% static 'dist/assets/icons/icon_left_brand.png' %}" />
</div> </div>
</rapi-doc> </rapi-doc>
<script>
const rapidoc = document.querySelector("rapi-doc");
const matcher = window.matchMedia("(prefers-color-scheme: light)");
const changer = (ev) => {
const style = getComputedStyle(document.documentElement);
let bg, text = "";
if (matcher.matches) {
bg = style.getPropertyValue('--pf-global--BackgroundColor--light-300');
text = style.getPropertyValue('--pf-global--Color--300');
} else {
bg = style.getPropertyValue('--ak-dark-background');
text = style.getPropertyValue('--ak-dark-foreground');
}
rapidoc.attributes.getNamedItem("bg-color").value = bg.trim();
rapidoc.attributes.getNamedItem("text-color").value = text.trim();
rapidoc.requestUpdate();
};
matcher.addEventListener("change", changer);
window.addEventListener("load", changer);
</script>
{% endblock %} {% endblock %}

View File

@ -8,28 +8,37 @@ from rest_framework.exceptions import AuthenticationFailed
from authentik.api.authentication import bearer_auth from authentik.api.authentication import bearer_auth
from authentik.core.models import USER_ATTRIBUTE_SA, Token, TokenIntents from authentik.core.models import USER_ATTRIBUTE_SA, Token, TokenIntents
from authentik.core.tests.utils import create_test_flow
from authentik.lib.generators import generate_id
from authentik.outposts.managed import OutpostManager from authentik.outposts.managed import OutpostManager
from authentik.providers.oauth2.constants import SCOPE_AUTHENTIK_API
from authentik.providers.oauth2.models import OAuth2Provider, RefreshToken
class TestAPIAuth(TestCase): class TestAPIAuth(TestCase):
"""Test API Authentication""" """Test API Authentication"""
def test_valid_bearer(self):
"""Test valid token"""
token = Token.objects.create(intent=TokenIntents.INTENT_API, user=get_anonymous_user())
self.assertEqual(bearer_auth(f"Bearer {token.key}".encode()), token.user)
def test_invalid_type(self): def test_invalid_type(self):
"""Test invalid type""" """Test invalid type"""
with self.assertRaises(AuthenticationFailed): with self.assertRaises(AuthenticationFailed):
bearer_auth("foo bar".encode()) bearer_auth("foo bar".encode())
def test_invalid_empty(self):
"""Test invalid type"""
self.assertIsNone(bearer_auth("Bearer ".encode()))
self.assertIsNone(bearer_auth("".encode()))
def test_invalid_no_token(self): def test_invalid_no_token(self):
"""Test invalid with no token""" """Test invalid with no token"""
with self.assertRaises(AuthenticationFailed): with self.assertRaises(AuthenticationFailed):
auth = b64encode(":abc".encode()).decode() auth = b64encode(":abc".encode()).decode()
self.assertIsNone(bearer_auth(f"Basic :{auth}".encode())) self.assertIsNone(bearer_auth(f"Basic :{auth}".encode()))
def test_bearer_valid(self):
"""Test valid token"""
token = Token.objects.create(intent=TokenIntents.INTENT_API, user=get_anonymous_user())
self.assertEqual(bearer_auth(f"Bearer {token.key}".encode()), token.user)
def test_managed_outpost(self): def test_managed_outpost(self):
"""Test managed outpost""" """Test managed outpost"""
with self.assertRaises(AuthenticationFailed): with self.assertRaises(AuthenticationFailed):
@ -38,3 +47,30 @@ class TestAPIAuth(TestCase):
OutpostManager().run() OutpostManager().run()
user = bearer_auth(f"Bearer {settings.SECRET_KEY}".encode()) user = bearer_auth(f"Bearer {settings.SECRET_KEY}".encode())
self.assertEqual(user.attributes[USER_ATTRIBUTE_SA], True) self.assertEqual(user.attributes[USER_ATTRIBUTE_SA], True)
def test_jwt_valid(self):
"""Test valid JWT"""
provider = OAuth2Provider.objects.create(
name=generate_id(), client_id=generate_id(), authorization_flow=create_test_flow()
)
refresh = RefreshToken.objects.create(
user=get_anonymous_user(),
provider=provider,
refresh_token=generate_id(),
_scope=SCOPE_AUTHENTIK_API,
)
self.assertEqual(bearer_auth(f"Bearer {refresh.refresh_token}".encode()), refresh.user)
def test_jwt_missing_scope(self):
"""Test valid JWT"""
provider = OAuth2Provider.objects.create(
name=generate_id(), client_id=generate_id(), authorization_flow=create_test_flow()
)
refresh = RefreshToken.objects.create(
user=get_anonymous_user(),
provider=provider,
refresh_token=generate_id(),
_scope="",
)
with self.assertRaises(AuthenticationFailed):
self.assertEqual(bearer_auth(f"Bearer {refresh.refresh_token}".encode()), refresh.user)

View File

@ -0,0 +1,29 @@
"""authentik API Modelviewset tests"""
from typing import Callable
from django.test import TestCase
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from authentik.api.v3.urls import router
class TestModelViewSets(TestCase):
"""Test Viewset"""
def viewset_tester_factory(test_viewset: type[ModelViewSet]) -> Callable:
"""Test Viewset"""
def tester(self: TestModelViewSets):
self.assertIsNotNone(getattr(test_viewset, "search_fields", None))
filterset_class = getattr(test_viewset, "filterset_class", None)
if not filterset_class:
self.assertIsNotNone(getattr(test_viewset, "filterset_fields", None))
return tester
for _, viewset, _ in router.registry:
if not issubclass(viewset, (ModelViewSet, ReadOnlyModelViewSet)):
continue
setattr(TestModelViewSets, f"test_viewset_{viewset.__name__}", viewset_tester_factory(viewset))

View File

@ -74,7 +74,7 @@ class ConfigView(APIView):
config = ConfigSerializer( config = ConfigSerializer(
{ {
"error_reporting": { "error_reporting": {
"enabled": CONFIG.y("error_reporting.enabled") and not settings.DEBUG, "enabled": CONFIG.y("error_reporting.enabled"),
"environment": CONFIG.y("error_reporting.environment"), "environment": CONFIG.y("error_reporting.environment"),
"send_pii": CONFIG.y("error_reporting.send_pii"), "send_pii": CONFIG.y("error_reporting.send_pii"),
"traces_sample_rate": float(CONFIG.y("error_reporting.sample_rate", 0.4)), "traces_sample_rate": float(CONFIG.y("error_reporting.sample_rate", 0.4)),

View File

@ -63,6 +63,7 @@ class ApplicationSerializer(ModelSerializer):
"provider", "provider",
"provider_obj", "provider_obj",
"launch_url", "launch_url",
"open_in_new_tab",
"meta_launch_url", "meta_launch_url",
"meta_icon", "meta_icon",
"meta_description", "meta_description",
@ -88,7 +89,16 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
"meta_publisher", "meta_publisher",
"group", "group",
] ]
filterset_fields = [
"name",
"slug",
"meta_launch_url",
"meta_description",
"meta_publisher",
"group",
]
lookup_field = "slug" lookup_field = "slug"
filterset_fields = ["name", "slug"]
ordering = ["name"] ordering = ["name"]
def _filter_queryset_for_list(self, queryset: QuerySet) -> QuerySet: def _filter_queryset_for_list(self, queryset: QuerySet) -> QuerySet:

View File

@ -8,7 +8,7 @@ from rest_framework.decorators import action
from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.serializers import ModelSerializer, ReadOnlyField, SerializerMethodField
from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import GenericViewSet
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
@ -26,6 +26,7 @@ LOGGER = get_logger()
class SourceSerializer(ModelSerializer, MetaNameSerializer): class SourceSerializer(ModelSerializer, MetaNameSerializer):
"""Source Serializer""" """Source Serializer"""
managed = ReadOnlyField()
component = SerializerMethodField() component = SerializerMethodField()
def get_component(self, obj: Source) -> str: def get_component(self, obj: Source) -> str:
@ -51,6 +52,8 @@ class SourceSerializer(ModelSerializer, MetaNameSerializer):
"meta_model_name", "meta_model_name",
"policy_engine_mode", "policy_engine_mode",
"user_matching_mode", "user_matching_mode",
"managed",
"user_path_template",
] ]
@ -66,6 +69,8 @@ class SourceViewSet(
queryset = Source.objects.none() queryset = Source.objects.none()
serializer_class = SourceSerializer serializer_class = SourceSerializer
lookup_field = "slug" lookup_field = "slug"
search_fields = ["slug", "name"]
filterset_fields = ["slug", "name", "managed"]
def get_queryset(self): # pragma: no cover def get_queryset(self): # pragma: no cover
return Source.objects.select_subclasses() return Source.objects.select_subclasses()

View File

@ -24,7 +24,13 @@ from drf_spectacular.utils import (
) )
from guardian.shortcuts import get_anonymous_user, get_objects_for_user from guardian.shortcuts import get_anonymous_user, get_objects_for_user
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import CharField, JSONField, SerializerMethodField from rest_framework.fields import (
CharField,
IntegerField,
JSONField,
ListField,
SerializerMethodField,
)
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import ( from rest_framework.serializers import (
@ -43,16 +49,23 @@ from authentik.api.decorators import permission_required
from authentik.core.api.groups import GroupSerializer from authentik.core.api.groups import GroupSerializer
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict
from authentik.core.middleware import SESSION_IMPERSONATE_ORIGINAL_USER, SESSION_IMPERSONATE_USER from authentik.core.middleware import (
SESSION_KEY_IMPERSONATE_ORIGINAL_USER,
SESSION_KEY_IMPERSONATE_USER,
)
from authentik.core.models import ( from authentik.core.models import (
USER_ATTRIBUTE_SA, USER_ATTRIBUTE_SA,
USER_ATTRIBUTE_TOKEN_EXPIRING, USER_ATTRIBUTE_TOKEN_EXPIRING,
USER_PATH_SERVICE_ACCOUNT,
Group, Group,
Token, Token,
TokenIntents, TokenIntents,
User, User,
) )
from authentik.events.models import EventAction from authentik.events.models import EventAction
from authentik.flows.models import FlowToken
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner
from authentik.flows.views.executor import QS_KEY_TOKEN
from authentik.stages.email.models import EmailStage from authentik.stages.email.models import EmailStage
from authentik.stages.email.tasks import send_mails from authentik.stages.email.tasks import send_mails
from authentik.stages.email.utils import TemplateEmailMessage from authentik.stages.email.utils import TemplateEmailMessage
@ -72,6 +85,16 @@ class UserSerializer(ModelSerializer):
) )
groups_obj = ListSerializer(child=GroupSerializer(), read_only=True, source="ak_groups") groups_obj = ListSerializer(child=GroupSerializer(), read_only=True, source="ak_groups")
uid = CharField(read_only=True) uid = CharField(read_only=True)
username = CharField(max_length=150)
def validate_path(self, path: str) -> str:
"""Validate path"""
if path[:1] == "/" or path[-1] == "/":
raise ValidationError(_("No leading or trailing slashes allowed."))
for segment in path.split("/"):
if segment == "":
raise ValidationError(_("No empty segments in user path allowed."))
return path
class Meta: class Meta:
@ -89,6 +112,7 @@ class UserSerializer(ModelSerializer):
"avatar", "avatar",
"attributes", "attributes",
"uid", "uid",
"path",
] ]
extra_kwargs = { extra_kwargs = {
"name": {"allow_blank": True}, "name": {"allow_blank": True},
@ -204,6 +228,11 @@ class UsersFilter(FilterSet):
is_superuser = BooleanFilter(field_name="ak_groups", lookup_expr="is_superuser") is_superuser = BooleanFilter(field_name="ak_groups", lookup_expr="is_superuser")
uuid = CharFilter(field_name="uuid") uuid = CharFilter(field_name="uuid")
path = CharFilter(
field_name="path",
)
path_startswith = CharFilter(field_name="path", lookup_expr="startswith")
groups_by_name = ModelMultipleChoiceFilter( groups_by_name = ModelMultipleChoiceFilter(
field_name="ak_groups__name", field_name="ak_groups__name",
to_field_name="name", to_field_name="name",
@ -268,12 +297,23 @@ class UserViewSet(UsedByMixin, ModelViewSet):
LOGGER.debug("No recovery flow set") LOGGER.debug("No recovery flow set")
return None, None return None, None
user: User = self.get_object() user: User = self.get_object()
token, __ = Token.objects.get_or_create( planner = FlowPlanner(flow)
identifier=f"{user.uid}-password-reset", planner.allow_empty_flows = True
user=user, plan = planner.plan(
intent=TokenIntents.INTENT_RECOVERY, self.request._request,
{
PLAN_CONTEXT_PENDING_USER: user,
},
) )
querystring = urlencode({"token": token.key}) token, __ = FlowToken.objects.update_or_create(
identifier=f"{user.uid}-password-reset",
defaults={
"user": user,
"flow": flow,
"_plan": FlowToken.pickle(plan),
},
)
querystring = urlencode({QS_KEY_TOKEN: token.key})
link = self.request.build_absolute_uri( link = self.request.build_absolute_uri(
reverse_lazy("authentik_core:if-flow", kwargs={"flow_slug": flow.slug}) reverse_lazy("authentik_core:if-flow", kwargs={"flow_slug": flow.slug})
+ f"?{querystring}" + f"?{querystring}"
@ -295,6 +335,9 @@ class UserViewSet(UsedByMixin, ModelViewSet):
{ {
"username": CharField(required=True), "username": CharField(required=True),
"token": CharField(required=True), "token": CharField(required=True),
"user_uid": CharField(required=True),
"user_pk": IntegerField(required=True),
"group_pk": CharField(required=False),
}, },
) )
}, },
@ -310,19 +353,27 @@ class UserViewSet(UsedByMixin, ModelViewSet):
username=username, username=username,
name=username, name=username,
attributes={USER_ATTRIBUTE_SA: True, USER_ATTRIBUTE_TOKEN_EXPIRING: False}, attributes={USER_ATTRIBUTE_SA: True, USER_ATTRIBUTE_TOKEN_EXPIRING: False},
path=USER_PATH_SERVICE_ACCOUNT,
) )
response = {
"username": user.username,
"user_uid": user.uid,
"user_pk": user.pk,
}
if create_group and self.request.user.has_perm("authentik_core.add_group"): if create_group and self.request.user.has_perm("authentik_core.add_group"):
group = Group.objects.create( group = Group.objects.create(
name=username, name=username,
) )
group.users.add(user) group.users.add(user)
response["group_pk"] = str(group.pk)
token = Token.objects.create( token = Token.objects.create(
identifier=slugify(f"service-account-{username}-password"), identifier=slugify(f"service-account-{username}-password"),
intent=TokenIntents.INTENT_APP_PASSWORD, intent=TokenIntents.INTENT_APP_PASSWORD,
user=user, user=user,
expires=now() + timedelta(days=360), expires=now() + timedelta(days=360),
) )
return Response({"username": user.username, "token": token.key}) response["token"] = token.key
return Response(response)
except (IntegrityError) as exc: except (IntegrityError) as exc:
return Response(data={"non_field_errors": [str(exc)]}, status=400) return Response(data={"non_field_errors": [str(exc)]}, status=400)
@ -335,11 +386,12 @@ class UserViewSet(UsedByMixin, ModelViewSet):
serializer = SessionUserSerializer( serializer = SessionUserSerializer(
data={"user": UserSelfSerializer(instance=request.user, context=context).data} data={"user": UserSelfSerializer(instance=request.user, context=context).data}
) )
if SESSION_IMPERSONATE_USER in request._request.session: if SESSION_KEY_IMPERSONATE_USER in request._request.session:
serializer.initial_data["original"] = UserSelfSerializer( serializer.initial_data["original"] = UserSelfSerializer(
instance=request._request.session[SESSION_IMPERSONATE_ORIGINAL_USER], instance=request._request.session[SESSION_KEY_IMPERSONATE_ORIGINAL_USER],
context=context, context=context,
).data ).data
self.request.session.modified = True
return Response(serializer.initial_data) return Response(serializer.initial_data)
@permission_required("authentik_core.reset_user_password") @permission_required("authentik_core.reset_user_password")
@ -366,7 +418,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
except (ValidationError, IntegrityError) as exc: except (ValidationError, IntegrityError) as exc:
LOGGER.debug("Failed to set password", exc=exc) LOGGER.debug("Failed to set password", exc=exc)
return Response(status=400) return Response(status=400)
if user.pk == request.user.pk and SESSION_IMPERSONATE_USER not in self.request.session: if user.pk == request.user.pk and SESSION_KEY_IMPERSONATE_USER not in self.request.session:
LOGGER.debug("Updating session hash after password change") LOGGER.debug("Updating session hash after password change")
update_session_auth_hash(self.request, user) update_session_auth_hash(self.request, user)
return Response(status=204) return Response(status=204)
@ -459,3 +511,32 @@ class UserViewSet(UsedByMixin, ModelViewSet):
if self.request.user.has_perm("authentik_core.view_user"): if self.request.user.has_perm("authentik_core.view_user"):
return self._filter_queryset_for_list(queryset) return self._filter_queryset_for_list(queryset)
return super().filter_queryset(queryset) return super().filter_queryset(queryset)
@extend_schema(
responses={
200: inline_serializer(
"UserPathSerializer", {"paths": ListField(child=CharField(), read_only=True)}
)
},
parameters=[
OpenApiParameter(
name="search",
location=OpenApiParameter.QUERY,
type=OpenApiTypes.STR,
)
],
)
@action(detail=False, pagination_class=None)
def paths(self, request: Request) -> Response:
"""Get all user paths"""
return Response(
data={
"paths": list(
self.filter_queryset(self.get_queryset())
.values("path")
.distinct()
.order_by("path")
.values_list("path", flat=True)
)
}
)

View File

@ -2,10 +2,7 @@
from importlib import import_module from importlib import import_module
from django.apps import AppConfig from django.apps import AppConfig
from django.db import ProgrammingError from django.conf import settings
from authentik.core.signals import GAUGE_MODELS
from authentik.lib.utils.reflection import get_apps
class AuthentikCoreConfig(AppConfig): class AuthentikCoreConfig(AppConfig):
@ -19,12 +16,7 @@ class AuthentikCoreConfig(AppConfig):
def ready(self): def ready(self):
import_module("authentik.core.signals") import_module("authentik.core.signals")
import_module("authentik.core.managed") import_module("authentik.core.managed")
try: if settings.DEBUG:
for app in get_apps(): from authentik.root.celery import worker_ready_hook
for model in app.get_models():
GAUGE_MODELS.labels( worker_ready_hook()
model_name=model._meta.model_name,
app=model._meta.app_label,
).set(model.objects.count())
except ProgrammingError:
pass

View File

@ -12,5 +12,6 @@ class CoreManager(ObjectManager):
Source, Source,
"goauthentik.io/sources/inbuilt", "goauthentik.io/sources/inbuilt",
name="authentik Built-in", name="authentik Built-in",
slug="authentik-built-in",
), ),
] ]

View File

@ -0,0 +1,13 @@
"""Run bootstrap tasks"""
from django.core.management.base import BaseCommand
from authentik.root.celery import _get_startup_tasks
class Command(BaseCommand): # pragma: no cover
"""Run bootstrap tasks to ensure certain objects are created"""
def handle(self, **options):
tasks = _get_startup_tasks()
for task in tasks:
task()

View File

@ -2,6 +2,7 @@
from django.apps import apps from django.apps import apps
from django.contrib.auth.management import create_permissions from django.contrib.auth.management import create_permissions
from django.core.management.base import BaseCommand, no_translations from django.core.management.base import BaseCommand, no_translations
from guardian.management import create_anonymous_user
class Command(BaseCommand): # pragma: no cover class Command(BaseCommand): # pragma: no cover
@ -13,3 +14,4 @@ class Command(BaseCommand): # pragma: no cover
for app in apps.get_app_configs(): for app in apps.get_app_configs():
self.stdout.write(f"Checking app {app.name} ({app.label})\n") self.stdout.write(f"Checking app {app.name} ({app.label})\n")
create_permissions(app, verbosity=0) create_permissions(app, verbosity=0)
create_anonymous_user(None, using="default")

View File

@ -7,8 +7,8 @@ from uuid import uuid4
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from sentry_sdk.api import set_tag from sentry_sdk.api import set_tag
SESSION_IMPERSONATE_USER = "authentik_impersonate_user" SESSION_KEY_IMPERSONATE_USER = "authentik/impersonate/user"
SESSION_IMPERSONATE_ORIGINAL_USER = "authentik_impersonate_original_user" SESSION_KEY_IMPERSONATE_ORIGINAL_USER = "authentik/impersonate/original_user"
LOCAL = local() LOCAL = local()
RESPONSE_HEADER_ID = "X-authentik-id" RESPONSE_HEADER_ID = "X-authentik-id"
KEY_AUTH_VIA = "auth_via" KEY_AUTH_VIA = "auth_via"
@ -25,10 +25,10 @@ class ImpersonateMiddleware:
def __call__(self, request: HttpRequest) -> HttpResponse: def __call__(self, request: HttpRequest) -> HttpResponse:
# No permission checks are done here, they need to be checked before # No permission checks are done here, they need to be checked before
# SESSION_IMPERSONATE_USER is set. # SESSION_KEY_IMPERSONATE_USER is set.
if SESSION_IMPERSONATE_USER in request.session: if SESSION_KEY_IMPERSONATE_USER in request.session:
request.user = request.session[SESSION_IMPERSONATE_USER] request.user = request.session[SESSION_KEY_IMPERSONATE_USER]
# Ensure that the user is active, otherwise nothing will work # Ensure that the user is active, otherwise nothing will work
request.user.is_active = True request.user.is_active = True
@ -56,7 +56,7 @@ class RequestIDMiddleware:
response[RESPONSE_HEADER_ID] = request.request_id response[RESPONSE_HEADER_ID] = request.request_id
setattr(response, "ak_context", {}) setattr(response, "ak_context", {})
response.ak_context.update(LOCAL.authentik) response.ak_context.update(LOCAL.authentik)
response.ak_context[KEY_USER] = request.user.username response.ak_context.setdefault(KEY_USER, request.user.username)
for key in list(LOCAL.authentik.keys()): for key in list(LOCAL.authentik.keys()):
del LOCAL.authentik[key] del LOCAL.authentik[key]
return response return response

View File

@ -12,18 +12,25 @@ import authentik.core.models
def create_default_user(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): def create_default_user(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
# We have to use a direct import here, otherwise we get an object manager error from django.contrib.auth.hashers import make_password
from authentik.core.models import User
User = apps.get_model("authentik_core", "User")
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
akadmin, _ = User.objects.using(db_alias).get_or_create( akadmin, _ = User.objects.using(db_alias).get_or_create(
username="akadmin", email="root@localhost", name="authentik Default Admin" username="akadmin", email="root@localhost", name="authentik Default Admin"
) )
if "TF_BUILD" in environ or "AK_ADMIN_PASS" in environ or settings.TEST: password = None
akadmin.set_password(environ.get("AK_ADMIN_PASS", "akadmin"), signal=False) # noqa # nosec if "TF_BUILD" in environ or settings.TEST:
password = "akadmin" # noqa # nosec
if "AK_ADMIN_PASS" in environ:
password = environ["AK_ADMIN_PASS"]
if "AUTHENTIK_BOOTSTRAP_PASSWORD" in environ:
password = environ["AUTHENTIK_BOOTSTRAP_PASSWORD"]
if password:
akadmin.password = make_password(password)
else: else:
akadmin.set_unusable_password() akadmin.password = make_password(None)
akadmin.save() akadmin.save()

View File

@ -8,18 +8,25 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def create_default_user(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): def create_default_user(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
# We have to use a direct import here, otherwise we get an object manager error from django.contrib.auth.hashers import make_password
from authentik.core.models import User
User = apps.get_model("authentik_core", "User")
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
akadmin, _ = User.objects.using(db_alias).get_or_create( akadmin, _ = User.objects.using(db_alias).get_or_create(
username="akadmin", email="root@localhost", name="authentik Default Admin" username="akadmin", email="root@localhost", name="authentik Default Admin"
) )
if "TF_BUILD" in environ or "AK_ADMIN_PASS" in environ or settings.TEST: password = None
akadmin.set_password(environ.get("AK_ADMIN_PASS", "akadmin"), signal=False) # noqa # nosec if "TF_BUILD" in environ or settings.TEST:
password = "akadmin" # noqa # nosec
if "AK_ADMIN_PASS" in environ:
password = environ["AK_ADMIN_PASS"]
if "AUTHENTIK_BOOTSTRAP_PASSWORD" in environ:
password = environ["AUTHENTIK_BOOTSTRAP_PASSWORD"]
if password:
akadmin.password = make_password(password)
else: else:
akadmin.set_unusable_password() akadmin.password = make_password(None)
akadmin.save() akadmin.save()

View File

@ -36,22 +36,29 @@ def fix_duplicates(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
def create_default_user_token(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): def create_default_user_token(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
# We have to use a direct import here, otherwise we get an object manager error from authentik.core.models import TokenIntents
from authentik.core.models import Token, TokenIntents, User
User = apps.get_model("authentik_core", "User")
Token = apps.get_model("authentik_core", "Token")
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
akadmin = User.objects.using(db_alias).filter(username="akadmin") akadmin = User.objects.using(db_alias).filter(username="akadmin")
if not akadmin.exists(): if not akadmin.exists():
return return
if "AK_ADMIN_TOKEN" not in environ: key = None
if "AK_ADMIN_TOKEN" in environ:
key = environ["AK_ADMIN_TOKEN"]
if "AUTHENTIK_BOOTSTRAP_TOKEN" in environ:
key = environ["AUTHENTIK_BOOTSTRAP_TOKEN"]
if not key:
return return
Token.objects.using(db_alias).create( Token.objects.using(db_alias).create(
identifier="authentik-boostrap-token", identifier="authentik-bootstrap-token",
user=akadmin.first(), user=akadmin.first(),
intent=TokenIntents.INTENT_API, intent=TokenIntents.INTENT_API,
expiring=False, expiring=False,
key=environ["AK_ADMIN_TOKEN"], key=key,
) )

View File

@ -0,0 +1,20 @@
# Generated by Django 4.0.5 on 2022-06-04 06:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0019_application_group"),
]
operations = [
migrations.AddField(
model_name="application",
name="open_in_new_tab",
field=models.BooleanField(
default=False, help_text="Open launch URL in a new browser tab or window."
),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.0.5 on 2022-06-13 18:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0020_application_open_in_new_tab"),
]
operations = [
migrations.AddField(
model_name="source",
name="user_path_template",
field=models.TextField(default="goauthentik.io/sources/%(slug)s"),
),
migrations.AddField(
model_name="user",
name="path",
field=models.TextField(default="users"),
),
]

View File

@ -7,22 +7,29 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def create_default_user_token(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): def create_default_user_token(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
# We have to use a direct import here, otherwise we get an object manager error from authentik.core.models import TokenIntents
from authentik.core.models import Token, TokenIntents, User
User = apps.get_model("authentik_core", "User")
Token = apps.get_model("authentik_core", "Token")
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
akadmin = User.objects.using(db_alias).filter(username="akadmin") akadmin = User.objects.using(db_alias).filter(username="akadmin")
if not akadmin.exists(): if not akadmin.exists():
return return
if "AK_ADMIN_TOKEN" not in environ: key = None
if "AK_ADMIN_TOKEN" in environ:
key = environ["AK_ADMIN_TOKEN"]
if "AUTHENTIK_BOOTSTRAP_TOKEN" in environ:
key = environ["AUTHENTIK_BOOTSTRAP_TOKEN"]
if not key:
return return
Token.objects.using(db_alias).create( Token.objects.using(db_alias).create(
identifier="authentik-boostrap-token", identifier="authentik-bootstrap-token",
user=akadmin.first(), user=akadmin.first(),
intent=TokenIntents.INTENT_API, intent=TokenIntents.INTENT_API,
expiring=False, expiring=False,
key=environ["AK_ADMIN_TOKEN"], key=key,
) )

View File

@ -46,6 +46,9 @@ USER_ATTRIBUTE_CHANGE_NAME = "goauthentik.io/user/can-change-name"
USER_ATTRIBUTE_CHANGE_EMAIL = "goauthentik.io/user/can-change-email" USER_ATTRIBUTE_CHANGE_EMAIL = "goauthentik.io/user/can-change-email"
USER_ATTRIBUTE_CAN_OVERRIDE_IP = "goauthentik.io/user/override-ips" USER_ATTRIBUTE_CAN_OVERRIDE_IP = "goauthentik.io/user/override-ips"
USER_PATH_SYSTEM_PREFIX = "goauthentik.io"
USER_PATH_SERVICE_ACCOUNT = USER_PATH_SYSTEM_PREFIX + "/service-accounts"
GRAVATAR_URL = "https://secure.gravatar.com" GRAVATAR_URL = "https://secure.gravatar.com"
DEFAULT_AVATAR = static("dist/assets/images/user_default.png") DEFAULT_AVATAR = static("dist/assets/images/user_default.png")
@ -103,7 +106,10 @@ class Group(models.Model):
SELECT authentik_core_group.*, parents.relative_depth - 1 SELECT authentik_core_group.*, parents.relative_depth - 1
FROM authentik_core_group,parents FROM authentik_core_group,parents
WHERE authentik_core_group.parent_id = parents.group_uuid WHERE (
authentik_core_group.parent_id = parents.group_uuid and
parents.relative_depth > -20
)
) )
SELECT group_uuid SELECT group_uuid
FROM parents FROM parents
@ -138,6 +144,7 @@ class User(GuardianUserMixin, AbstractUser):
uuid = models.UUIDField(default=uuid4, editable=False) uuid = models.UUIDField(default=uuid4, editable=False)
name = models.TextField(help_text=_("User's display name.")) name = models.TextField(help_text=_("User's display name."))
path = models.TextField(default="users")
sources = models.ManyToManyField("Source", through="UserSourceConnection") sources = models.ManyToManyField("Source", through="UserSourceConnection")
ak_groups = models.ManyToManyField("Group", related_name="users") ak_groups = models.ManyToManyField("Group", related_name="users")
@ -147,6 +154,11 @@ class User(GuardianUserMixin, AbstractUser):
objects = UserManager() objects = UserManager()
@staticmethod
def default_path() -> str:
"""Get the default user path"""
return User._meta.get_field("path").default
def group_attributes(self, request: Optional[HttpRequest] = None) -> dict[str, Any]: def group_attributes(self, request: Optional[HttpRequest] = None) -> dict[str, Any]:
"""Get a dictionary containing the attributes from all groups the user belongs to, """Get a dictionary containing the attributes from all groups the user belongs to,
including the users attributes""" including the users attributes"""
@ -192,7 +204,7 @@ class User(GuardianUserMixin, AbstractUser):
@property @property
def uid(self) -> str: def uid(self) -> str:
"""Generate a globall unique UID, based on the user ID and the hashed secret key""" """Generate a globally unique UID, based on the user ID and the hashed secret key"""
return sha256(f"{self.id}-{settings.SECRET_KEY}".encode("ascii")).hexdigest() return sha256(f"{self.id}-{settings.SECRET_KEY}".encode("ascii")).hexdigest()
@property @property
@ -278,6 +290,11 @@ class Application(PolicyBindingModel):
meta_launch_url = models.TextField( meta_launch_url = models.TextField(
default="", blank=True, validators=[DomainlessURLValidator()] default="", blank=True, validators=[DomainlessURLValidator()]
) )
open_in_new_tab = models.BooleanField(
default=False, help_text=_("Open launch URL in a new browser tab or window.")
)
# For template applications, this can be set to /static/authentik/applications/* # For template applications, this can be set to /static/authentik/applications/*
meta_icon = models.FileField( meta_icon = models.FileField(
upload_to="application-icons/", upload_to="application-icons/",
@ -368,6 +385,8 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
name = models.TextField(help_text=_("Source's display Name.")) name = models.TextField(help_text=_("Source's display Name."))
slug = models.SlugField(help_text=_("Internal source name, used in URLs."), unique=True) slug = models.SlugField(help_text=_("Internal source name, used in URLs."), unique=True)
user_path_template = models.TextField(default="goauthentik.io/sources/%(slug)s")
enabled = models.BooleanField(default=True) enabled = models.BooleanField(default=True)
property_mappings = models.ManyToManyField("PropertyMapping", default=None, blank=True) property_mappings = models.ManyToManyField("PropertyMapping", default=None, blank=True)
@ -403,6 +422,17 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
objects = InheritanceManager() objects = InheritanceManager()
def get_user_path(self) -> str:
"""Get user path, fallback to default for formatting errors"""
try:
return self.user_path_template % {
"slug": self.slug,
}
# pylint: disable=broad-except
except Exception as exc:
LOGGER.warning("Failed to template user path", exc=exc, source=self)
return User.default_path()
@property @property
def component(self) -> str: def component(self) -> str:
"""Return component used to edit this object""" """Return component used to edit this object"""
@ -452,8 +482,9 @@ class ExpiringModel(models.Model):
def filter_not_expired(cls, **kwargs) -> QuerySet: def filter_not_expired(cls, **kwargs) -> QuerySet:
"""Filer for tokens which are not expired yet or are not expiring, """Filer for tokens which are not expired yet or are not expiring,
and match filters in `kwargs`""" and match filters in `kwargs`"""
expired = Q(expires__lt=now(), expiring=True) for obj in cls.objects.filter(**kwargs).filter(Q(expires__lt=now(), expiring=True)):
return cls.objects.exclude(expired).filter(**kwargs) obj.delete()
return cls.objects.filter(**kwargs)
@property @property
def is_expired(self) -> bool: def is_expired(self) -> bool:

View File

@ -1,7 +1,6 @@
"""authentik core signals""" """authentik core signals"""
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from django.apps import apps
from django.contrib.auth.signals import user_logged_in, user_logged_out from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.contrib.sessions.backends.cache import KEY_PREFIX from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.core.cache import cache from django.core.cache import cache
@ -10,30 +9,16 @@ from django.db.models import Model
from django.db.models.signals import post_save, pre_delete from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver from django.dispatch import receiver
from django.http.request import HttpRequest from django.http.request import HttpRequest
from prometheus_client import Gauge
from authentik.root.monitoring import monitoring_set
# Arguments: user: User, password: str # Arguments: user: User, password: str
password_changed = Signal() password_changed = Signal()
# Arguments: credentials: dict[str, any], request: HttpRequest, stage: Stage
GAUGE_MODELS = Gauge("authentik_models", "Count of various objects", ["model_name", "app"]) login_failed = Signal()
if TYPE_CHECKING: if TYPE_CHECKING:
from authentik.core.models import AuthenticatedSession, User from authentik.core.models import AuthenticatedSession, User
@receiver(monitoring_set)
# pylint: disable=unused-argument
def monitoring_set_models(sender, **kwargs):
"""set models gauges"""
for model in apps.get_models():
GAUGE_MODELS.labels(
model_name=model._meta.model_name,
app=model._meta.app_label,
).set(model.objects.count())
@receiver(post_save) @receiver(post_save)
# pylint: disable=unused-argument # pylint: disable=unused-argument
def post_save_application(sender: type[Model], instance, created: bool, **_): def post_save_application(sender: type[Model], instance, created: bool, **_):

View File

@ -26,11 +26,11 @@ from authentik.flows.planner import (
from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_GET, SESSION_KEY_PLAN from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_GET, SESSION_KEY_PLAN
from authentik.lib.utils.urls import redirect_with_qs from authentik.lib.utils.urls import redirect_with_qs
from authentik.policies.denied import AccessDeniedResponse from authentik.policies.denied import AccessDeniedResponse
from authentik.policies.types import PolicyResult
from authentik.policies.utils import delete_none_keys from authentik.policies.utils import delete_none_keys
from authentik.stages.password import BACKEND_INBUILT from authentik.stages.password import BACKEND_INBUILT
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
from authentik.stages.user_write.stage import PLAN_CONTEXT_USER_PATH
class Action(Enum): class Action(Enum):
@ -165,9 +165,9 @@ class SourceFlowManager:
return self.handle_enroll(connection) return self.handle_enroll(connection)
except FlowNonApplicableException as exc: except FlowNonApplicableException as exc:
self._logger.warning("Flow non applicable", exc=exc) self._logger.warning("Flow non applicable", exc=exc)
return self.error_handler(exc, exc.policy_result) return self.error_handler(exc)
# Default case, assume deny # Default case, assume deny
error = ( error = Exception(
_( _(
( (
"Request to authenticate with %(source)s has been denied. Please authenticate " "Request to authenticate with %(source)s has been denied. Please authenticate "
@ -178,14 +178,13 @@ class SourceFlowManager:
) )
return self.error_handler(error) return self.error_handler(error)
def error_handler( def error_handler(self, error: Exception) -> HttpResponse:
self, error: Exception, policy_result: Optional[PolicyResult] = None
) -> HttpResponse:
"""Handle any errors by returning an access denied stage""" """Handle any errors by returning an access denied stage"""
response = AccessDeniedResponse(self.request) response = AccessDeniedResponse(self.request)
response.error_message = str(error) response.error_message = str(error)
if policy_result: if isinstance(error, FlowNonApplicableException):
response.policy_result = policy_result response.policy_result = error.policy_result
response.error_message = error.messages
return response return response
# pylint: disable=unused-argument # pylint: disable=unused-argument
@ -291,5 +290,6 @@ class SourceFlowManager:
connection, connection,
**{ **{
PLAN_CONTEXT_PROMPT: delete_none_keys(self.enroll_info), PLAN_CONTEXT_PROMPT: delete_none_keys(self.enroll_info),
PLAN_CONTEXT_USER_PATH: self.source.get_user_path(),
}, },
) )

View File

@ -5,11 +5,14 @@
{% block head_before %} {% block head_before %}
{{ block.super }} {{ block.super }}
<link rel="prefetch" href="{{ flow.background_url }}" />
{% if flow.compatibility_mode and not inspector %} {% if flow.compatibility_mode and not inspector %}
<script>ShadyDOM = { force: !navigator.webdriver };</script> <script>ShadyDOM = { force: !navigator.webdriver };</script>
{% endif %} {% endif %}
<script> <script>
window.authentik = {}; window.authentik = {
"locale": "{{ tenant.default_locale }}",
};
window.authentik.flow = { window.authentik.flow = {
"layout": "{{ flow.layout }}", "layout": "{{ flow.layout }}",
}; };
@ -19,7 +22,7 @@ window.authentik.flow = {
{% block head %} {% block head %}
<script src="{% static 'dist/flow/FlowInterface.js' %}" type="module"></script> <script src="{% static 'dist/flow/FlowInterface.js' %}" type="module"></script>
<style> <style>
.pf-c-background-image::before { :root {
--ak-flow-background: url("{{ flow.background_url }}"); --ak-flow-background: url("{{ flow.background_url }}");
} }
</style> </style>

View File

@ -4,13 +4,19 @@
{% load i18n %} {% load i18n %}
{% block head_before %} {% block head_before %}
<link rel="prefetch" href="/static/dist/assets/images/flow_background.jpg" />
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}">
{% endblock %} {% endblock %}
{% block head %} {% block head %}
<style> <style>
.pf-c-background-image::before { :root {
--ak-flow-background: url("/static/dist/assets/images/flow_background.jpg"); --ak-flow-background: url("/static/dist/assets/images/flow_background.jpg");
--pf-c-background-image--BackgroundImage: var(--ak-flow-background);
--pf-c-background-image--BackgroundImage-2x: var(--ak-flow-background);
--pf-c-background-image--BackgroundImage--sm: var(--ak-flow-background);
--pf-c-background-image--BackgroundImage--sm-2x: var(--ak-flow-background);
--pf-c-background-image--BackgroundImage--lg: var(--ak-flow-background);
} }
/* Form with user */ /* Form with user */
.form-control-static { .form-control-static {

View File

@ -29,6 +29,7 @@ class TestApplicationsAPI(APITestCase):
name="allowed", name="allowed",
slug="allowed", slug="allowed",
meta_launch_url="https://goauthentik.io/%(username)s", meta_launch_url="https://goauthentik.io/%(username)s",
open_in_new_tab=True,
provider=self.provider, provider=self.provider,
) )
self.denied = Application.objects.create(name="denied", slug="denied") self.denied = Application.objects.create(name="denied", slug="denied")
@ -100,6 +101,7 @@ class TestApplicationsAPI(APITestCase):
}, },
"launch_url": f"https://goauthentik.io/{self.user.username}", "launch_url": f"https://goauthentik.io/{self.user.username}",
"meta_launch_url": "https://goauthentik.io/%(username)s", "meta_launch_url": "https://goauthentik.io/%(username)s",
"open_in_new_tab": True,
"meta_icon": None, "meta_icon": None,
"meta_description": "", "meta_description": "",
"meta_publisher": "", "meta_publisher": "",
@ -148,6 +150,7 @@ class TestApplicationsAPI(APITestCase):
}, },
"launch_url": f"https://goauthentik.io/{self.user.username}", "launch_url": f"https://goauthentik.io/{self.user.username}",
"meta_launch_url": "https://goauthentik.io/%(username)s", "meta_launch_url": "https://goauthentik.io/%(username)s",
"open_in_new_tab": True,
"meta_icon": None, "meta_icon": None,
"meta_description": "", "meta_description": "",
"meta_publisher": "", "meta_publisher": "",
@ -158,6 +161,7 @@ class TestApplicationsAPI(APITestCase):
"meta_description": "", "meta_description": "",
"meta_icon": None, "meta_icon": None,
"meta_launch_url": "", "meta_launch_url": "",
"open_in_new_tab": False,
"meta_publisher": "", "meta_publisher": "",
"group": "", "group": "",
"name": "denied", "name": "denied",

View File

@ -2,6 +2,7 @@
from django.test.testcases import TestCase from django.test.testcases import TestCase
from authentik.core.models import Group, User from authentik.core.models import Group, User
from authentik.lib.generators import generate_id
class TestGroups(TestCase): class TestGroups(TestCase):
@ -9,32 +10,43 @@ class TestGroups(TestCase):
def test_group_membership_simple(self): def test_group_membership_simple(self):
"""Test simple membership""" """Test simple membership"""
user = User.objects.create(username="user") user = User.objects.create(username=generate_id())
user2 = User.objects.create(username="user2") user2 = User.objects.create(username=generate_id())
group = Group.objects.create(name="group") group = Group.objects.create(name=generate_id())
group.users.add(user) group.users.add(user)
self.assertTrue(group.is_member(user)) self.assertTrue(group.is_member(user))
self.assertFalse(group.is_member(user2)) self.assertFalse(group.is_member(user2))
def test_group_membership_parent(self): def test_group_membership_parent(self):
"""Test parent membership""" """Test parent membership"""
user = User.objects.create(username="user") user = User.objects.create(username=generate_id())
user2 = User.objects.create(username="user2") user2 = User.objects.create(username=generate_id())
first = Group.objects.create(name="first") first = Group.objects.create(name=generate_id())
second = Group.objects.create(name="second", parent=first) second = Group.objects.create(name=generate_id(), parent=first)
second.users.add(user) second.users.add(user)
self.assertTrue(first.is_member(user)) self.assertTrue(first.is_member(user))
self.assertFalse(first.is_member(user2)) self.assertFalse(first.is_member(user2))
def test_group_membership_parent_extra(self): def test_group_membership_parent_extra(self):
"""Test parent membership""" """Test parent membership"""
user = User.objects.create(username="user") user = User.objects.create(username=generate_id())
user2 = User.objects.create(username="user2") user2 = User.objects.create(username=generate_id())
first = Group.objects.create(name="first") first = Group.objects.create(name=generate_id())
second = Group.objects.create(name="second", parent=first) second = Group.objects.create(name=generate_id(), parent=first)
third = Group.objects.create(name="third", parent=second) third = Group.objects.create(name=generate_id(), parent=second)
second.users.add(user) second.users.add(user)
self.assertTrue(first.is_member(user)) self.assertTrue(first.is_member(user))
self.assertFalse(first.is_member(user2)) self.assertFalse(first.is_member(user2))
self.assertFalse(third.is_member(user)) self.assertFalse(third.is_member(user))
self.assertFalse(third.is_member(user2)) self.assertFalse(third.is_member(user2))
def test_group_membership_recursive(self):
"""Test group membership (recursive)"""
user = User.objects.create(username=generate_id())
group = Group.objects.create(name=generate_id())
group2 = Group.objects.create(name=generate_id(), parent=group)
group.users.add(user)
group.parent = group2
group.save()
self.assertTrue(group.is_member(user))
self.assertTrue(group2.is_member(user))

View File

@ -5,7 +5,7 @@ from rest_framework.test import APITestCase
from authentik.core.models import User from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user, create_test_flow, create_test_tenant from authentik.core.tests.utils import create_test_admin_user, create_test_flow, create_test_tenant
from authentik.flows.models import FlowDesignation from authentik.flows.models import FlowDesignation
from authentik.lib.generators import generate_key from authentik.lib.generators import generate_id, generate_key
from authentik.stages.email.models import EmailStage from authentik.stages.email.models import EmailStage
from authentik.tenants.models import Tenant from authentik.tenants.models import Tenant
@ -149,3 +149,65 @@ class TestUsersAPI(APITestCase):
}, },
) )
self.assertEqual(response.status_code, 400) self.assertEqual(response.status_code, 400)
def test_paths(self):
"""Test path"""
self.client.force_login(self.admin)
response = self.client.get(
reverse("authentik_api:user-paths"),
)
print(response.content)
self.assertEqual(response.status_code, 200)
self.assertJSONEqual(response.content.decode(), {"paths": ["users"]})
def test_path_valid(self):
"""Test path"""
self.client.force_login(self.admin)
response = self.client.post(
reverse("authentik_api:user-list"),
data={"name": generate_id(), "username": generate_id(), "groups": [], "path": "foo"},
)
self.assertEqual(response.status_code, 201)
def test_path_invalid(self):
"""Test path (invalid)"""
self.client.force_login(self.admin)
response = self.client.post(
reverse("authentik_api:user-list"),
data={"name": generate_id(), "username": generate_id(), "groups": [], "path": "/foo"},
)
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(), {"path": ["No leading or trailing slashes allowed."]}
)
self.client.force_login(self.admin)
response = self.client.post(
reverse("authentik_api:user-list"),
data={"name": generate_id(), "username": generate_id(), "groups": [], "path": ""},
)
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(response.content.decode(), {"path": ["This field may not be blank."]})
response = self.client.post(
reverse("authentik_api:user-list"),
data={"name": generate_id(), "username": generate_id(), "groups": [], "path": "foo/"},
)
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(), {"path": ["No leading or trailing slashes allowed."]}
)
response = self.client.post(
reverse("authentik_api:user-list"),
data={
"name": generate_id(),
"username": generate_id(),
"groups": [],
"path": "fos//o",
},
)
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(), {"path": ["No empty segments in user path allowed."]}
)

View File

@ -11,14 +11,13 @@ from authentik.lib.generators import generate_id
from authentik.tenants.models import Tenant from authentik.tenants.models import Tenant
def create_test_flow(designation: FlowDesignation = FlowDesignation.STAGE_CONFIGURATION) -> Flow: def create_test_flow(
designation: FlowDesignation = FlowDesignation.STAGE_CONFIGURATION, **kwargs
) -> Flow:
"""Generate a flow that can be used for testing""" """Generate a flow that can be used for testing"""
uid = generate_id(10) uid = generate_id(10)
return Flow.objects.create( return Flow.objects.create(
name=uid, name=uid, title=uid, slug=slugify(uid), designation=designation, **kwargs
title=uid,
slug=slugify(uid),
designation=designation,
) )
@ -47,11 +46,11 @@ def create_test_tenant() -> Tenant:
def create_test_cert() -> CertificateKeyPair: def create_test_cert() -> CertificateKeyPair:
"""Generate a certificate for testing""" """Generate a certificate for testing"""
CertificateKeyPair.objects.filter(name="goauthentik.io").delete()
builder = CertificateBuilder() builder = CertificateBuilder()
builder.common_name = "goauthentik.io" builder.common_name = "goauthentik.io"
builder.build( builder.build(
subject_alt_names=["goauthentik.io"], subject_alt_names=["goauthentik.io"],
validity_days=360, validity_days=360,
) )
builder.name = generate_id()
return builder.save() return builder.save()

View File

@ -14,7 +14,9 @@ from authentik.core.views.session import EndSessionView
urlpatterns = [ urlpatterns = [
path( path(
"", "",
login_required(RedirectView.as_view(pattern_name="authentik_core:if-user")), login_required(
RedirectView.as_view(pattern_name="authentik_core:if-user", query_string=True)
),
name="root-redirect", name="root-redirect",
), ),
path( path(

View File

@ -5,7 +5,10 @@ from django.shortcuts import get_object_or_404, redirect
from django.views import View from django.views import View
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.core.middleware import SESSION_IMPERSONATE_ORIGINAL_USER, SESSION_IMPERSONATE_USER from authentik.core.middleware import (
SESSION_KEY_IMPERSONATE_ORIGINAL_USER,
SESSION_KEY_IMPERSONATE_USER,
)
from authentik.core.models import User from authentik.core.models import User
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
@ -27,8 +30,8 @@ class ImpersonateInitView(View):
user_to_be = get_object_or_404(User, pk=user_id) user_to_be = get_object_or_404(User, pk=user_id)
request.session[SESSION_IMPERSONATE_ORIGINAL_USER] = request.user request.session[SESSION_KEY_IMPERSONATE_ORIGINAL_USER] = request.user
request.session[SESSION_IMPERSONATE_USER] = user_to_be request.session[SESSION_KEY_IMPERSONATE_USER] = user_to_be
Event.new(EventAction.IMPERSONATION_STARTED).from_http(request, user_to_be) Event.new(EventAction.IMPERSONATION_STARTED).from_http(request, user_to_be)
@ -41,16 +44,16 @@ class ImpersonateEndView(View):
def get(self, request: HttpRequest) -> HttpResponse: def get(self, request: HttpRequest) -> HttpResponse:
"""End Impersonation handler""" """End Impersonation handler"""
if ( if (
SESSION_IMPERSONATE_USER not in request.session SESSION_KEY_IMPERSONATE_USER not in request.session
or SESSION_IMPERSONATE_ORIGINAL_USER not in request.session or SESSION_KEY_IMPERSONATE_ORIGINAL_USER not in request.session
): ):
LOGGER.debug("Can't end impersonation", user=request.user) LOGGER.debug("Can't end impersonation", user=request.user)
return redirect("authentik_core:if-user") return redirect("authentik_core:if-user")
original_user = request.session[SESSION_IMPERSONATE_ORIGINAL_USER] original_user = request.session[SESSION_KEY_IMPERSONATE_ORIGINAL_USER]
del request.session[SESSION_IMPERSONATE_USER] del request.session[SESSION_KEY_IMPERSONATE_USER]
del request.session[SESSION_IMPERSONATE_ORIGINAL_USER] del request.session[SESSION_KEY_IMPERSONATE_ORIGINAL_USER]
Event.new(EventAction.IMPERSONATION_ENDED).from_http(request, original_user) Event.new(EventAction.IMPERSONATION_ENDED).from_http(request, original_user)

View File

@ -53,10 +53,7 @@ class CertificateBuilder:
.subject_name( .subject_name(
x509.Name( x509.Name(
[ [
x509.NameAttribute( x509.NameAttribute(NameOID.COMMON_NAME, self.common_name),
NameOID.COMMON_NAME,
self.common_name,
),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "authentik"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "authentik"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Self-signed"), x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Self-signed"),
] ]
@ -65,10 +62,7 @@ class CertificateBuilder:
.issuer_name( .issuer_name(
x509.Name( x509.Name(
[ [
x509.NameAttribute( x509.NameAttribute(NameOID.COMMON_NAME, f"authentik {__version__}"),
NameOID.COMMON_NAME,
f"authentik {__version__}",
),
] ]
) )
) )

View File

@ -2,6 +2,8 @@
from django.db import migrations from django.db import migrations
from authentik.lib.generators import generate_id
def create_self_signed(apps, schema_editor): def create_self_signed(apps, schema_editor):
CertificateKeyPair = apps.get_model("authentik_crypto", "CertificateKeyPair") CertificateKeyPair = apps.get_model("authentik_crypto", "CertificateKeyPair")
@ -9,7 +11,7 @@ def create_self_signed(apps, schema_editor):
from authentik.crypto.builder import CertificateBuilder from authentik.crypto.builder import CertificateBuilder
builder = CertificateBuilder() builder = CertificateBuilder()
builder.build() builder.build(subject_alt_names=[f"{generate_id()}.self-signed.goauthentik.io"])
CertificateKeyPair.objects.using(db_alias).create( CertificateKeyPair.objects.using(db_alias).create(
name="authentik Self-signed Certificate", name="authentik Self-signed Certificate",
certificate_data=builder.certificate, certificate_data=builder.certificate,

View File

@ -26,3 +26,4 @@ class NotificationWebhookMappingViewSet(UsedByMixin, ModelViewSet):
serializer_class = NotificationWebhookMappingSerializer serializer_class = NotificationWebhookMappingSerializer
filterset_fields = ["name"] filterset_fields = ["name"]
ordering = ["name"] ordering = ["name"]
search_fields = ["name"]

View File

@ -32,3 +32,4 @@ class NotificationRuleViewSet(UsedByMixin, ModelViewSet):
serializer_class = NotificationRuleSerializer serializer_class = NotificationRuleSerializer
filterset_fields = ["name", "severity", "group__name"] filterset_fields = ["name", "severity", "group__name"]
ordering = ["name"] ordering = ["name"]
search_fields = ["name", "group__name"]

View File

@ -68,6 +68,7 @@ class NotificationTransportViewSet(UsedByMixin, ModelViewSet):
queryset = NotificationTransport.objects.all() queryset = NotificationTransport.objects.all()
serializer_class = NotificationTransportSerializer serializer_class = NotificationTransportSerializer
filterset_fields = ["name", "mode", "webhook_url", "send_once"] filterset_fields = ["name", "mode", "webhook_url", "send_once"]
search_fields = ["name", "mode", "webhook_url"]
ordering = ["name"] ordering = ["name"]
@permission_required("authentik_events.change_notificationtransport") @permission_required("authentik_events.change_notificationtransport")

View File

@ -2,6 +2,13 @@
from importlib import import_module from importlib import import_module
from django.apps import AppConfig from django.apps import AppConfig
from prometheus_client import Gauge
GAUGE_TASKS = Gauge(
"authentik_system_tasks",
"System tasks and their status",
["task_name", "task_uid", "status"],
)
class AuthentikEventsConfig(AppConfig): class AuthentikEventsConfig(AppConfig):

View File

@ -76,11 +76,8 @@ class GeoIPReader:
except (GeoIP2Error, ValueError): except (GeoIP2Error, ValueError):
return None return None
def city_dict(self, ip_address: str) -> Optional[GeoIPDict]: def city_to_dict(self, city: City) -> GeoIPDict:
"""Wrapper for self.city that returns a dict""" """Convert City to dict"""
city = self.city(ip_address)
if not city:
return None
city_dict: GeoIPDict = { city_dict: GeoIPDict = {
"continent": city.continent.code, "continent": city.continent.code,
"country": city.country.iso_code, "country": city.country.iso_code,
@ -92,5 +89,12 @@ class GeoIPReader:
city_dict["city"] = city.city.name city_dict["city"] = city.city.name
return city_dict return city_dict
def city_dict(self, ip_address: str) -> Optional[GeoIPDict]:
"""Wrapper for self.city that returns a dict"""
city = self.city(ip_address)
if not city:
return None
return self.city_to_dict(city)
GEOIP_READER = GeoIPReader() GEOIP_READER = GeoIPReader()

View File

@ -3,6 +3,7 @@ from functools import partial
from typing import Callable from typing import Callable
from django.conf import settings from django.conf import settings
from django.contrib.sessions.models import Session
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
from django.db.models import Model from django.db.models import Model
from django.db.models.signals import post_save, pre_delete from django.db.models.signals import post_save, pre_delete
@ -15,6 +16,7 @@ from authentik.core.models import AuthenticatedSession, User
from authentik.events.models import Event, EventAction, Notification from authentik.events.models import Event, EventAction, Notification
from authentik.events.signals import EventNewThread from authentik.events.signals import EventNewThread
from authentik.events.utils import model_to_dict from authentik.events.utils import model_to_dict
from authentik.flows.models import FlowToken
from authentik.lib.sentry import before_send from authentik.lib.sentry import before_send
from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.errors import exception_to_string
@ -24,11 +26,13 @@ IGNORED_MODELS = [
UserObjectPermission, UserObjectPermission,
AuthenticatedSession, AuthenticatedSession,
StaticToken, StaticToken,
Session,
FlowToken,
] ]
if settings.DEBUG: if settings.DEBUG:
from silk.models import Request, Response from silk.models import Request, Response, SQLQuery
IGNORED_MODELS += [Request, Response] IGNORED_MODELS += [Request, Response, SQLQuery]
IGNORED_MODELS = tuple(IGNORED_MODELS) IGNORED_MODELS = tuple(IGNORED_MODELS)

View File

@ -383,6 +383,7 @@ class Migration(migrations.Migration):
models.ManyToManyField( models.ManyToManyField(
help_text="Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI.", help_text="Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI.",
to="authentik_events.NotificationTransport", to="authentik_events.NotificationTransport",
blank=True,
), ),
), ),
], ],

View File

@ -0,0 +1,50 @@
# Generated by Django 4.0.4 on 2022-05-30 18:08
from django.apps.registry import Apps
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from authentik.events.models import TransportMode
def notify_local_transport(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
db_alias = schema_editor.connection.alias
NotificationTransport = apps.get_model("authentik_events", "NotificationTransport")
NotificationRule = apps.get_model("authentik_events", "NotificationRule")
local_transport, _ = NotificationTransport.objects.using(db_alias).update_or_create(
name="default-local-transport",
defaults={"mode": TransportMode.LOCAL},
)
for trigger in NotificationRule.objects.using(db_alias).filter(
name__in=[
"default-notify-configuration-error",
"default-notify-exception",
"default-notify-update",
]
):
trigger.transports.add(local_transport)
class Migration(migrations.Migration):
dependencies = [
("authentik_events", "0001_squashed_0019_alter_notificationtransport_webhook_url"),
]
operations = [
migrations.AlterField(
model_name="notificationtransport",
name="mode",
field=models.TextField(
choices=[
("local", "authentik inbuilt notifications"),
("webhook", "Generic Webhook"),
("webhook_slack", "Slack Webhook (Slack/Discord)"),
("email", "Email"),
],
default="local",
),
),
migrations.RunPython(notify_local_transport),
]

View File

@ -23,7 +23,10 @@ from requests import RequestException
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik import __version__ from authentik import __version__
from authentik.core.middleware import SESSION_IMPERSONATE_ORIGINAL_USER, SESSION_IMPERSONATE_USER from authentik.core.middleware import (
SESSION_KEY_IMPERSONATE_ORIGINAL_USER,
SESSION_KEY_IMPERSONATE_USER,
)
from authentik.core.models import ExpiringModel, Group, PropertyMapping, User from authentik.core.models import ExpiringModel, Group, PropertyMapping, User
from authentik.events.geo import GEOIP_READER from authentik.events.geo import GEOIP_READER
from authentik.events.utils import cleanse_dict, get_user, model_to_dict, sanitize_dict from authentik.events.utils import cleanse_dict, get_user, model_to_dict, sanitize_dict
@ -233,15 +236,15 @@ class Event(ExpiringModel):
if hasattr(request, "user"): if hasattr(request, "user"):
original_user = None original_user = None
if hasattr(request, "session"): if hasattr(request, "session"):
original_user = request.session.get(SESSION_IMPERSONATE_ORIGINAL_USER, None) original_user = request.session.get(SESSION_KEY_IMPERSONATE_ORIGINAL_USER, None)
self.user = get_user(request.user, original_user) self.user = get_user(request.user, original_user)
if user: if user:
self.user = get_user(user) self.user = get_user(user)
# Check if we're currently impersonating, and add that user # Check if we're currently impersonating, and add that user
if hasattr(request, "session"): if hasattr(request, "session"):
if SESSION_IMPERSONATE_ORIGINAL_USER in request.session: if SESSION_KEY_IMPERSONATE_ORIGINAL_USER in request.session:
self.user = get_user(request.session[SESSION_IMPERSONATE_ORIGINAL_USER]) self.user = get_user(request.session[SESSION_KEY_IMPERSONATE_ORIGINAL_USER])
self.user["on_behalf_of"] = get_user(request.session[SESSION_IMPERSONATE_USER]) self.user["on_behalf_of"] = get_user(request.session[SESSION_KEY_IMPERSONATE_USER])
# User 255.255.255.255 as fallback if IP cannot be determined # User 255.255.255.255 as fallback if IP cannot be determined
self.client_ip = get_client_ip(request) self.client_ip = get_client_ip(request)
# Apply GeoIP Data, when enabled # Apply GeoIP Data, when enabled
@ -289,6 +292,7 @@ class Event(ExpiringModel):
class TransportMode(models.TextChoices): class TransportMode(models.TextChoices):
"""Modes that a notification transport can send a notification""" """Modes that a notification transport can send a notification"""
LOCAL = "local", _("authentik inbuilt notifications")
WEBHOOK = "webhook", _("Generic Webhook") WEBHOOK = "webhook", _("Generic Webhook")
WEBHOOK_SLACK = "webhook_slack", _("Slack Webhook (Slack/Discord)") WEBHOOK_SLACK = "webhook_slack", _("Slack Webhook (Slack/Discord)")
EMAIL = "email", _("Email") EMAIL = "email", _("Email")
@ -300,7 +304,7 @@ class NotificationTransport(models.Model):
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4) uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
name = models.TextField(unique=True) name = models.TextField(unique=True)
mode = models.TextField(choices=TransportMode.choices) mode = models.TextField(choices=TransportMode.choices, default=TransportMode.LOCAL)
webhook_url = models.TextField(blank=True, validators=[DomainlessURLValidator()]) webhook_url = models.TextField(blank=True, validators=[DomainlessURLValidator()])
webhook_mapping = models.ForeignKey( webhook_mapping = models.ForeignKey(
@ -315,6 +319,8 @@ class NotificationTransport(models.Model):
def send(self, notification: "Notification") -> list[str]: def send(self, notification: "Notification") -> list[str]:
"""Send notification to user, called from async task""" """Send notification to user, called from async task"""
if self.mode == TransportMode.LOCAL:
return self.send_local(notification)
if self.mode == TransportMode.WEBHOOK: if self.mode == TransportMode.WEBHOOK:
return self.send_webhook(notification) return self.send_webhook(notification)
if self.mode == TransportMode.WEBHOOK_SLACK: if self.mode == TransportMode.WEBHOOK_SLACK:
@ -323,6 +329,17 @@ class NotificationTransport(models.Model):
return self.send_email(notification) return self.send_email(notification)
raise ValueError(f"Invalid mode {self.mode} set") raise ValueError(f"Invalid mode {self.mode} set")
def send_local(self, notification: "Notification") -> list[str]:
"""Local notification delivery"""
if self.webhook_mapping:
self.webhook_mapping.evaluate(
user=notification.user,
request=None,
notification=notification,
)
notification.save()
return []
def send_webhook(self, notification: "Notification") -> list[str]: def send_webhook(self, notification: "Notification") -> list[str]:
"""Send notification to generic webhook""" """Send notification to generic webhook"""
default_body = { default_body = {
@ -481,6 +498,7 @@ class NotificationRule(PolicyBindingModel):
"selected, the notification will only be shown in the authentik UI." "selected, the notification will only be shown in the authentik UI."
) )
), ),
blank=True,
) )
severity = models.TextField( severity = models.TextField(
choices=NotificationSeverity.choices, choices=NotificationSeverity.choices,

View File

@ -8,18 +8,12 @@ from typing import Any, Optional
from celery import Task from celery import Task
from django.core.cache import cache from django.core.cache import cache
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from prometheus_client import Gauge
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.events.apps import GAUGE_TASKS
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.errors import exception_to_string
GAUGE_TASKS = Gauge(
"authentik_system_tasks",
"System tasks and their status",
["task_name", "task_uid", "status"],
)
LOGGER = get_logger() LOGGER = get_logger()

View File

@ -2,15 +2,16 @@
from threading import Thread from threading import Thread
from typing import Any, Optional from typing import Any, Optional
from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.db.models.signals import post_save, pre_delete from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver from django.dispatch import receiver
from django.http import HttpRequest from django.http import HttpRequest
from authentik.core.models import User from authentik.core.models import User
from authentik.core.signals import password_changed from authentik.core.signals import login_failed, password_changed
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.events.tasks import event_notification_handler, gdpr_cleanup from authentik.events.tasks import event_notification_handler, gdpr_cleanup
from authentik.flows.models import Stage
from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.stages.invitation.models import Invitation from authentik.stages.invitation.models import Invitation
@ -77,11 +78,18 @@ def on_user_write(sender, request: HttpRequest, user: User, data: dict[str, Any]
thread.run() thread.run()
@receiver(user_login_failed) @receiver(login_failed)
# pylint: disable=unused-argument # pylint: disable=unused-argument
def on_user_login_failed(sender, credentials: dict[str, str], request: HttpRequest, **_): def on_login_failed(
"""Failed Login""" signal,
thread = EventNewThread(EventAction.LOGIN_FAILED, request, **credentials) sender,
credentials: dict[str, str],
request: HttpRequest,
stage: Optional[Stage] = None,
**kwargs,
):
"""Failed Login, authentik custom event"""
thread = EventNewThread(EventAction.LOGIN_FAILED, request, **credentials, stage=stage, **kwargs)
thread.run() thread.run()

View File

@ -1,8 +1,11 @@
"""Event notification tasks""" """Event notification tasks"""
from typing import Optional
from django.db.models.query_utils import Q from django.db.models.query_utils import Q
from guardian.shortcuts import get_anonymous_user from guardian.shortcuts import get_anonymous_user
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.core.exceptions import PropertyMappingExpressionException
from authentik.core.models import User from authentik.core.models import User
from authentik.events.models import ( from authentik.events.models import (
Event, Event,
@ -39,10 +42,9 @@ def event_trigger_handler(event_uuid: str, trigger_name: str):
LOGGER.warning("event doesn't exist yet or anymore", event_uuid=event_uuid) LOGGER.warning("event doesn't exist yet or anymore", event_uuid=event_uuid)
return return
event: Event = events.first() event: Event = events.first()
triggers: NotificationRule = NotificationRule.objects.filter(name=trigger_name) trigger: Optional[NotificationRule] = NotificationRule.objects.filter(name=trigger_name).first()
if not triggers.exists(): if not trigger:
return return
trigger = triggers.first()
if "policy_uuid" in event.context: if "policy_uuid" in event.context:
policy_uuid = event.context["policy_uuid"] policy_uuid = event.context["policy_uuid"]
@ -81,11 +83,14 @@ def event_trigger_handler(event_uuid: str, trigger_name: str):
for transport in trigger.transports.all(): for transport in trigger.transports.all():
for user in trigger.group.users.all(): for user in trigger.group.users.all():
LOGGER.debug("created notification") LOGGER.debug("created notification")
notification = Notification.objects.create(
severity=trigger.severity, body=event.summary, event=event, user=user
)
notification_transport.apply_async( notification_transport.apply_async(
args=[notification.pk, transport.pk], queue="authentik_events" args=[
transport.pk,
str(event.pk),
user.pk,
str(trigger.pk),
],
queue="authentik_events",
) )
if transport.send_once: if transport.send_once:
break break
@ -97,19 +102,30 @@ def event_trigger_handler(event_uuid: str, trigger_name: str):
retry_backoff=True, retry_backoff=True,
base=MonitoredTask, base=MonitoredTask,
) )
def notification_transport(self: MonitoredTask, notification_pk: int, transport_pk: int): def notification_transport(
self: MonitoredTask, transport_pk: int, event_pk: str, user_pk: int, trigger_pk: str
):
"""Send notification over specified transport""" """Send notification over specified transport"""
self.save_on_success = False self.save_on_success = False
try: try:
notification: Notification = Notification.objects.filter(pk=notification_pk).first() event = Event.objects.filter(pk=event_pk).first()
if not notification: if not event:
return return
user = User.objects.filter(pk=user_pk).first()
if not user:
return
trigger = NotificationRule.objects.filter(pk=trigger_pk).first()
if not trigger:
return
notification = Notification(
severity=trigger.severity, body=event.summary, event=event, user=user
)
transport = NotificationTransport.objects.filter(pk=transport_pk).first() transport = NotificationTransport.objects.filter(pk=transport_pk).first()
if not transport: if not transport:
return return
transport.send(notification) transport.send(notification)
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL)) self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL))
except NotificationTransportError as exc: except (NotificationTransportError, PropertyMappingExpressionException) as exc:
self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc)) self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc))
raise exc raise exc

View File

@ -11,7 +11,10 @@ from authentik.events.models import (
Notification, Notification,
NotificationRule, NotificationRule,
NotificationTransport, NotificationTransport,
NotificationWebhookMapping,
TransportMode,
) )
from authentik.lib.generators import generate_id
from authentik.policies.event_matcher.models import EventMatcherPolicy from authentik.policies.event_matcher.models import EventMatcherPolicy
from authentik.policies.exceptions import PolicyException from authentik.policies.exceptions import PolicyException
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
@ -105,4 +108,26 @@ class TestEventsNotifications(TestCase):
execute_mock = MagicMock() execute_mock = MagicMock()
with patch("authentik.events.models.NotificationTransport.send", execute_mock): with patch("authentik.events.models.NotificationTransport.send", execute_mock):
Event.new(EventAction.CUSTOM_PREFIX).save() Event.new(EventAction.CUSTOM_PREFIX).save()
self.assertEqual(Notification.objects.count(), 1) self.assertEqual(execute_mock.call_count, 1)
def test_transport_mapping(self):
"""Test transport mapping"""
mapping = NotificationWebhookMapping.objects.create(
name=generate_id(),
expression="""notification.body = 'foo'""",
)
transport = NotificationTransport.objects.create(
name="transport", webhook_mapping=mapping, mode=TransportMode.LOCAL
)
NotificationRule.objects.filter(name__startswith="default").delete()
trigger = NotificationRule.objects.create(name="trigger", group=self.group)
trigger.transports.add(transport)
matcher = EventMatcherPolicy.objects.create(
name="matcher", action=EventAction.CUSTOM_PREFIX
)
PolicyBinding.objects.create(target=trigger, policy=matcher, order=0)
Notification.objects.all().delete()
Event.new(EventAction.CUSTOM_PREFIX).save()
self.assertEqual(Notification.objects.first().body, "foo")

View File

@ -10,9 +10,11 @@ from django.db import models
from django.db.models.base import Model from django.db.models.base import Model
from django.http.request import HttpRequest from django.http.request import HttpRequest
from django.views.debug import SafeExceptionReporterFilter from django.views.debug import SafeExceptionReporterFilter
from geoip2.models import City
from guardian.utils import get_anonymous_user from guardian.utils import get_anonymous_user
from authentik.core.models import User from authentik.core.models import User
from authentik.events.geo import GEOIP_READER
from authentik.policies.types import PolicyRequest from authentik.policies.types import PolicyRequest
# Special keys which are *not* cleaned, even when the default filter # Special keys which are *not* cleaned, even when the default filter
@ -93,6 +95,8 @@ def sanitize_dict(source: dict[Any, Any]) -> dict[Any, Any]:
final_dict[key] = value.hex final_dict[key] = value.hex
elif isinstance(value, (HttpRequest, WSGIRequest)): elif isinstance(value, (HttpRequest, WSGIRequest)):
continue continue
elif isinstance(value, City):
final_dict[key] = GEOIP_READER.city_to_dict(value)
elif isinstance(value, type): elif isinstance(value, type):
final_dict[key] = { final_dict[key] = {
"type": value.__name__, "type": value.__name__,

View File

@ -35,3 +35,4 @@ class FlowStageBindingViewSet(UsedByMixin, ModelViewSet):
queryset = FlowStageBinding.objects.all() queryset = FlowStageBinding.objects.all()
serializer_class = FlowStageBindingSerializer serializer_class = FlowStageBindingSerializer
filterset_fields = "__all__" filterset_fields = "__all__"
search_fields = ["stage__name"]

View File

@ -73,6 +73,7 @@ class FlowSerializer(ModelSerializer):
"compatibility_mode", "compatibility_mode",
"export_url", "export_url",
"layout", "layout",
"denied_action",
] ]
extra_kwargs = { extra_kwargs = {
"background": {"read_only": True}, "background": {"read_only": True},
@ -110,8 +111,8 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
serializer_class = FlowSerializer serializer_class = FlowSerializer
lookup_field = "slug" lookup_field = "slug"
ordering = ["slug", "name"] ordering = ["slug", "name"]
search_fields = ["name", "slug", "designation", "title"] search_fields = ["name", "slug", "designation", "title", "denied_action"]
filterset_fields = ["flow_uuid", "name", "slug", "designation"] filterset_fields = ["flow_uuid", "name", "slug", "designation", "denied_action"]
@permission_required(None, ["authentik_flows.view_flow_cache"]) @permission_required(None, ["authentik_flows.view_flow_cache"])
@extend_schema(responses={200: CacheSerializer(many=False)}) @extend_schema(responses={200: CacheSerializer(many=False)})
@ -371,7 +372,7 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
request, request,
_( _(
"Flow not applicable to current user/request: %(messages)s" "Flow not applicable to current user/request: %(messages)s"
% {"messages": str(exc)} % {"messages": exc.messages}
), ),
) )
return Response( return Response(

View File

@ -3,9 +3,20 @@ from importlib import import_module
from django.apps import AppConfig from django.apps import AppConfig
from django.db.utils import ProgrammingError from django.db.utils import ProgrammingError
from prometheus_client import Gauge, Histogram
from authentik.lib.utils.reflection import all_subclasses from authentik.lib.utils.reflection import all_subclasses
GAUGE_FLOWS_CACHED = Gauge(
"authentik_flows_cached",
"Cached flows",
)
HIST_FLOWS_PLAN_TIME = Histogram(
"authentik_flows_plan_time",
"Duration to build a plan for a flow",
["flow_slug"],
)
class AuthentikFlowsConfig(AppConfig): class AuthentikFlowsConfig(AppConfig):
"""authentik flows app config""" """authentik flows app config"""

View File

@ -1,6 +1,6 @@
"""Challenge helpers""" """Challenge helpers"""
from enum import Enum from enum import Enum
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional, TypedDict
from django.db import models from django.db import models
from django.http import JsonResponse from django.http import JsonResponse
@ -95,6 +95,13 @@ class AccessDeniedChallenge(WithUserInfoChallenge):
component = CharField(default="ak-stage-access-denied") component = CharField(default="ak-stage-access-denied")
class PermissionDict(TypedDict):
"""Consent Permission"""
id: str
name: str
class PermissionSerializer(PassiveSerializer): class PermissionSerializer(PassiveSerializer):
"""Permission used for consent""" """Permission used for consent"""

View File

@ -1,4 +1,5 @@
"""flow exceptions""" """flow exceptions"""
from django.utils.translation import gettext_lazy as _
from authentik.lib.sentry import SentryIgnoredException from authentik.lib.sentry import SentryIgnoredException
from authentik.policies.types import PolicyResult from authentik.policies.types import PolicyResult
@ -9,6 +10,13 @@ class FlowNonApplicableException(SentryIgnoredException):
policy_result: PolicyResult policy_result: PolicyResult
@property
def messages(self) -> str:
"""Get messages from policy result, fallback to generic reason"""
if len(self.policy_result.messages) < 1:
return _("Flow does not apply to current user (denied by policy).")
return "\n".join(self.policy_result.messages)
class EmptyFlowException(SentryIgnoredException): class EmptyFlowException(SentryIgnoredException):
"""Flow has no stages.""" """Flow has no stages."""

View File

@ -94,9 +94,9 @@ class Command(BaseCommand): # pragma: no cover
def output_overview(self, values): def output_overview(self, values):
"""Output results human readable""" """Output results human readable"""
total_max: int = max([max(inner) for inner in values]) total_max: int = max(max(inner) for inner in values)
total_min: int = min([min(inner) for inner in values]) total_min: int = min(min(inner) for inner in values)
total_avg = sum([sum(inner) for inner in values]) / sum([len(inner) for inner in values]) total_avg = sum(sum(inner) for inner in values) / sum(len(inner) for inner in values)
print(f"Version: {__version__}") print(f"Version: {__version__}")
print(f"Processes: {len(values)}") print(f"Processes: {len(values)}")

View File

@ -47,7 +47,8 @@ class ReevaluateMarker(StageMarker):
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
LOGGER.debug( LOGGER.debug(
"f(plan_inst)[re-eval marker]: running re-evaluation", "f(plan_inst): running re-evaluation",
marker="ReevaluateMarker",
binding=binding, binding=binding,
policy_binding=self.binding, policy_binding=self.binding,
) )
@ -56,13 +57,15 @@ class ReevaluateMarker(StageMarker):
) )
engine.use_cache = False engine.use_cache = False
engine.request.set_http_request(http_request) engine.request.set_http_request(http_request)
engine.request.context = plan.context engine.request.context["flow_plan"] = plan
engine.request.context.update(plan.context)
engine.build() engine.build()
result = engine.result result = engine.result
if result.passing: if result.passing:
return binding return binding
LOGGER.warning( LOGGER.warning(
"f(plan_inst)[re-eval marker]: binding failed re-evaluation", "f(plan_inst): binding failed re-evaluation",
marker="ReevaluateMarker",
binding=binding, binding=binding,
messages=result.messages, messages=result.messages,
) )

View File

@ -14,7 +14,7 @@ return not akadmin.has_usable_password()"""
PREFILL_POLICY_EXPRESSION = """# This policy sets the user for the currently running flow PREFILL_POLICY_EXPRESSION = """# This policy sets the user for the currently running flow
# by injecting "pending_user" # by injecting "pending_user"
akadmin = ak_user_by(username="akadmin") akadmin = ak_user_by(username="akadmin")
context["pending_user"] = akadmin context["flow_plan"].context["pending_user"] = akadmin
return True""" return True"""

View File

@ -0,0 +1,26 @@
# Generated by Django 4.0.5 on 2022-07-02 12:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0022_flow_layout"),
]
operations = [
migrations.AddField(
model_name="flow",
name="denied_action",
field=models.TextField(
choices=[
("message_continue", "Message Continue"),
("message", "Message"),
("continue", "Continue"),
],
default="message_continue",
help_text="Configure what should happen when a flow denies access to a user.",
),
),
]

View File

@ -5,7 +5,6 @@ from typing import TYPE_CHECKING, Optional
from uuid import uuid4 from uuid import uuid4
from django.db import models from django.db import models
from django.http import HttpRequest
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from model_utils.managers import InheritanceManager from model_utils.managers import InheritanceManager
from rest_framework.serializers import BaseSerializer from rest_framework.serializers import BaseSerializer
@ -40,6 +39,14 @@ class InvalidResponseAction(models.TextChoices):
RESTART_WITH_CONTEXT = "restart_with_context" RESTART_WITH_CONTEXT = "restart_with_context"
class FlowDeniedAction(models.TextChoices):
"""Configure what response is given to denied flow executions"""
MESSAGE_CONTINUE = "message_continue"
MESSAGE = "message"
CONTINUE = "continue"
class FlowDesignation(models.TextChoices): class FlowDesignation(models.TextChoices):
"""Designation of what a Flow should be used for. At a later point, this """Designation of what a Flow should be used for. At a later point, this
should be replaced by a database entry.""" should be replaced by a database entry."""
@ -87,13 +94,15 @@ class Stage(SerializerModel):
return f"Stage {self.name}" return f"Stage {self.name}"
def in_memory_stage(view: type["StageView"]) -> Stage: def in_memory_stage(view: type["StageView"], **kwargs) -> Stage:
"""Creates an in-memory stage instance, based on a `view` as view.""" """Creates an in-memory stage instance, based on a `view` as view."""
stage = Stage() stage = Stage()
# Because we can't pickle a locally generated function, # Because we can't pickle a locally generated function,
# we set the view as a separate property and reference a generic function # we set the view as a separate property and reference a generic function
# that returns that member # that returns that member
setattr(stage, "__in_memory_type", view) setattr(stage, "__in_memory_type", view)
for key, value in kwargs.items():
setattr(stage, key, value)
return stage return stage
@ -137,6 +146,12 @@ class Flow(SerializerModel, PolicyBindingModel):
), ),
) )
denied_action = models.TextField(
choices=FlowDeniedAction.choices,
default=FlowDeniedAction.MESSAGE_CONTINUE,
help_text=_("Configure what should happen when a flow denies access to a user."),
)
@property @property
def background_url(self) -> str: def background_url(self) -> str:
"""Get the URL to the background image. If the name is /static or starts with http """Get the URL to the background image. If the name is /static or starts with http
@ -155,23 +170,6 @@ class Flow(SerializerModel, PolicyBindingModel):
return FlowSerializer return FlowSerializer
@staticmethod
def with_policy(request: HttpRequest, **flow_filter) -> Optional["Flow"]:
"""Get a Flow by `**flow_filter` and check if the request from `request` can access it."""
from authentik.policies.engine import PolicyEngine
flows = Flow.objects.filter(**flow_filter).order_by("slug")
for flow in flows:
engine = PolicyEngine(flow, request.user, request)
engine.build()
result = engine.result
if result.passing:
LOGGER.debug("with_policy: flow passing", flow=flow)
return flow
LOGGER.warning("with_policy: flow not passing", flow=flow, messages=result.messages)
LOGGER.debug("with_policy: no flow found", filters=flow_filter)
return None
def __str__(self) -> str: def __str__(self) -> str:
return f"Flow {self.name} ({self.slug})" return f"Flow {self.name} ({self.slug})"

View File

@ -4,16 +4,16 @@ from typing import Any, Optional
from django.core.cache import cache from django.core.cache import cache
from django.http import HttpRequest from django.http import HttpRequest
from prometheus_client import Gauge, Histogram
from sentry_sdk.hub import Hub from sentry_sdk.hub import Hub
from sentry_sdk.tracing import Span from sentry_sdk.tracing import Span
from structlog.stdlib import BoundLogger, get_logger from structlog.stdlib import BoundLogger, get_logger
from authentik.core.models import User from authentik.core.models import User
from authentik.events.models import cleanse_dict from authentik.events.models import cleanse_dict
from authentik.flows.apps import HIST_FLOWS_PLAN_TIME
from authentik.flows.exceptions import EmptyFlowException, FlowNonApplicableException from authentik.flows.exceptions import EmptyFlowException, FlowNonApplicableException
from authentik.flows.markers import ReevaluateMarker, StageMarker from authentik.flows.markers import ReevaluateMarker, StageMarker
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, Stage from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, Stage, in_memory_stage
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.policies.engine import PolicyEngine from authentik.policies.engine import PolicyEngine
@ -26,15 +26,6 @@ PLAN_CONTEXT_SOURCE = "source"
# Is set by the Flow Planner when a FlowToken was used, and the currently active flow plan # Is set by the Flow Planner when a FlowToken was used, and the currently active flow plan
# was restored. # was restored.
PLAN_CONTEXT_IS_RESTORED = "is_restored" PLAN_CONTEXT_IS_RESTORED = "is_restored"
GAUGE_FLOWS_CACHED = Gauge(
"authentik_flows_cached",
"Cached flows",
)
HIST_FLOWS_PLAN_TIME = Histogram(
"authentik_flows_plan_time",
"Duration to build a plan for a flow",
["flow_slug"],
)
CACHE_TIMEOUT = int(CONFIG.y("redis.cache_timeout_flows")) CACHE_TIMEOUT = int(CONFIG.y("redis.cache_timeout_flows"))
@ -71,6 +62,12 @@ class FlowPlan:
self.bindings.insert(1, FlowStageBinding(stage=stage, order=0)) self.bindings.insert(1, FlowStageBinding(stage=stage, order=0))
self.markers.insert(1, marker or StageMarker()) self.markers.insert(1, marker or StageMarker())
def redirect(self, destination: str):
"""Insert a redirect stage as next stage"""
from authentik.flows.stage import RedirectStage
self.insert_stage(in_memory_stage(RedirectStage, destination=destination))
def next(self, http_request: Optional[HttpRequest]) -> Optional[FlowStageBinding]: def next(self, http_request: Optional[HttpRequest]) -> Optional[FlowStageBinding]:
"""Return next pending stage from the bottom of the list""" """Return next pending stage from the bottom of the list"""
if not self.has_stages: if not self.has_stages:
@ -117,7 +114,7 @@ class FlowPlanner:
self.use_cache = True self.use_cache = True
self.allow_empty_flows = False self.allow_empty_flows = False
self.flow = flow self.flow = flow
self._logger = get_logger().bind(flow=flow) self._logger = get_logger().bind(flow_slug=flow.slug)
def plan( def plan(
self, request: HttpRequest, default_context: Optional[dict[str, Any]] = None self, request: HttpRequest, default_context: Optional[dict[str, Any]] = None
@ -146,11 +143,11 @@ class FlowPlanner:
engine = PolicyEngine(self.flow, user, request) engine = PolicyEngine(self.flow, user, request)
if default_context: if default_context:
span.set_data("default_context", cleanse_dict(default_context)) span.set_data("default_context", cleanse_dict(default_context))
engine.request.context = default_context engine.request.context.update(default_context)
engine.build() engine.build()
result = engine.result result = engine.result
if not result.passing: if not result.passing:
exc = FlowNonApplicableException(",".join(result.messages)) exc = FlowNonApplicableException()
exc.policy_result = result exc.policy_result = result
raise exc raise exc
# User is passing so far, check if we have a cached plan # User is passing so far, check if we have a cached plan
@ -207,7 +204,8 @@ class FlowPlanner:
stage=binding.stage, stage=binding.stage,
) )
engine = PolicyEngine(binding, user, request) engine = PolicyEngine(binding, user, request)
engine.request.context = plan.context engine.request.context["flow_plan"] = plan
engine.request.context.update(plan.context)
engine.build() engine.build()
if engine.passing: if engine.passing:
self._logger.debug( self._logger.debug(

View File

@ -4,7 +4,7 @@ from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver from django.dispatch import receiver
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.flows.planner import GAUGE_FLOWS_CACHED from authentik.flows.apps import GAUGE_FLOWS_CACHED
from authentik.root.monitoring import monitoring_set from authentik.root.monitoring import monitoring_set
LOGGER = get_logger() LOGGER = get_logger()

View File

@ -9,7 +9,7 @@ from django.urls import reverse
from django.views.generic.base import View from django.views.generic.base import View
from rest_framework.request import Request from rest_framework.request import Request
from sentry_sdk.hub import Hub from sentry_sdk.hub import Hub
from structlog.stdlib import get_logger from structlog.stdlib import BoundLogger, get_logger
from authentik.core.models import DEFAULT_AVATAR, User from authentik.core.models import DEFAULT_AVATAR, User
from authentik.flows.challenge import ( from authentik.flows.challenge import (
@ -19,27 +19,35 @@ from authentik.flows.challenge import (
ChallengeTypes, ChallengeTypes,
ContextualFlowInfo, ContextualFlowInfo,
HttpChallengeResponse, HttpChallengeResponse,
RedirectChallenge,
WithUserInfoChallenge, WithUserInfoChallenge,
) )
from authentik.flows.models import InvalidResponseAction from authentik.flows.models import InvalidResponseAction
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_PENDING_USER from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_PENDING_USER
from authentik.lib.utils.reflection import class_to_path
if TYPE_CHECKING: if TYPE_CHECKING:
from authentik.flows.views.executor import FlowExecutorView from authentik.flows.views.executor import FlowExecutorView
PLAN_CONTEXT_PENDING_USER_IDENTIFIER = "pending_user_identifier" PLAN_CONTEXT_PENDING_USER_IDENTIFIER = "pending_user_identifier"
LOGGER = get_logger()
class StageView(View): class StageView(View):
"""Abstract Stage, inherits TemplateView but can be combined with FormView""" """Abstract Stage"""
executor: "FlowExecutorView" executor: "FlowExecutorView"
request: HttpRequest = None request: HttpRequest = None
logger: BoundLogger
def __init__(self, executor: "FlowExecutorView", **kwargs): def __init__(self, executor: "FlowExecutorView", **kwargs):
self.executor = executor self.executor = executor
current_stage = getattr(self.executor, "current_stage", None)
self.logger = get_logger().bind(
stage=getattr(current_stage, "name", None),
stage_view=class_to_path(type(self)),
)
super().__init__(**kwargs) super().__init__(**kwargs)
def get_pending_user(self, for_display=False) -> User: def get_pending_user(self, for_display=False) -> User:
@ -60,6 +68,9 @@ class StageView(View):
return self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] return self.executor.plan.context[PLAN_CONTEXT_PENDING_USER]
return self.request.user return self.request.user
def cleanup(self):
"""Cleanup session"""
class ChallengeStageView(StageView): class ChallengeStageView(StageView):
"""Stage view which response with a challenge""" """Stage view which response with a challenge"""
@ -74,12 +85,9 @@ class ChallengeStageView(StageView):
"""Return a challenge for the frontend to solve""" """Return a challenge for the frontend to solve"""
challenge = self._get_challenge(*args, **kwargs) challenge = self._get_challenge(*args, **kwargs)
if not challenge.is_valid(): if not challenge.is_valid():
LOGGER.warning( self.logger.warning(
"f(ch): Invalid challenge", "f(ch): Invalid challenge",
binding=self.executor.current_binding,
errors=challenge.errors, errors=challenge.errors,
stage_view=self,
challenge=challenge,
) )
return HttpChallengeResponse(challenge) return HttpChallengeResponse(challenge)
@ -96,10 +104,8 @@ class ChallengeStageView(StageView):
self.executor.current_binding.invalid_response_action self.executor.current_binding.invalid_response_action
== InvalidResponseAction.RESTART_WITH_CONTEXT == InvalidResponseAction.RESTART_WITH_CONTEXT
) )
LOGGER.debug( self.logger.debug(
"f(ch): Invalid response, restarting flow", "f(ch): Invalid response, restarting flow",
binding=self.executor.current_binding,
stage_view=self,
keep_context=keep_context, keep_context=keep_context,
) )
return self.executor.restart_flow(keep_context) return self.executor.restart_flow(keep_context)
@ -125,7 +131,7 @@ class ChallengeStageView(StageView):
} }
# pylint: disable=broad-except # pylint: disable=broad-except
except Exception as exc: except Exception as exc:
LOGGER.warning("failed to template title", exc=exc) self.logger.warning("failed to template title", exc=exc)
return self.executor.flow.title return self.executor.flow.title
def _get_challenge(self, *args, **kwargs) -> Challenge: def _get_challenge(self, *args, **kwargs) -> Challenge:
@ -185,11 +191,9 @@ class ChallengeStageView(StageView):
) )
challenge_response.initial_data["response_errors"] = full_errors challenge_response.initial_data["response_errors"] = full_errors
if not challenge_response.is_valid(): if not challenge_response.is_valid():
LOGGER.error( self.logger.error(
"f(ch): invalid challenge response", "f(ch): invalid challenge response",
binding=self.executor.current_binding,
errors=challenge_response.errors, errors=challenge_response.errors,
stage_view=self,
) )
return HttpChallengeResponse(challenge_response) return HttpChallengeResponse(challenge_response)
@ -216,3 +220,21 @@ class AccessDeniedChallengeView(ChallengeStageView):
# .get() method is called # .get() method is called
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: # pragma: no cover def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: # pragma: no cover
return self.executor.cancel() return self.executor.cancel()
class RedirectStage(ChallengeStageView):
"""Redirect to any URL"""
def get_challenge(self, *args, **kwargs) -> RedirectChallenge:
destination = getattr(
self.executor.current_stage, "destination", reverse("authentik_core:root-redirect")
)
return RedirectChallenge(
data={
"type": ChallengeTypes.REDIRECT.value,
"to": destination,
}
)
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
return HttpChallengeResponse(self.get_challenge())

View File

@ -6,14 +6,20 @@ from django.test.client import RequestFactory
from django.urls import reverse from django.urls import reverse
from authentik.core.models import User from authentik.core.models import User
from authentik.flows.exceptions import FlowNonApplicableException from authentik.core.tests.utils import create_test_flow
from authentik.flows.markers import ReevaluateMarker, StageMarker from authentik.flows.markers import ReevaluateMarker, StageMarker
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, InvalidResponseAction from authentik.flows.models import (
FlowDeniedAction,
FlowDesignation,
FlowStageBinding,
InvalidResponseAction,
)
from authentik.flows.planner import FlowPlan, FlowPlanner from authentik.flows.planner import FlowPlan, FlowPlanner
from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, StageView from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, StageView
from authentik.flows.tests import FlowTestCase from authentik.flows.tests import FlowTestCase
from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_PLAN, FlowExecutorView from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_PLAN, FlowExecutorView
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id
from authentik.policies.dummy.models import DummyPolicy from authentik.policies.dummy.models import DummyPolicy
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
from authentik.policies.reputation.models import ReputationPolicy from authentik.policies.reputation.models import ReputationPolicy
@ -22,7 +28,7 @@ from authentik.stages.deny.models import DenyStage
from authentik.stages.dummy.models import DummyStage from authentik.stages.dummy.models import DummyStage
from authentik.stages.identification.models import IdentificationStage, UserFields from authentik.stages.identification.models import IdentificationStage, UserFields
POLICY_RETURN_FALSE = PropertyMock(return_value=PolicyResult(False)) POLICY_RETURN_FALSE = PropertyMock(return_value=PolicyResult(False, "foo"))
POLICY_RETURN_TRUE = MagicMock(return_value=PolicyResult(True)) POLICY_RETURN_TRUE = MagicMock(return_value=PolicyResult(True))
@ -47,12 +53,10 @@ class TestFlowExecutor(FlowTestCase):
) )
def test_existing_plan_diff_flow(self): def test_existing_plan_diff_flow(self):
"""Check that a plan for a different flow cancels the current plan""" """Check that a plan for a different flow cancels the current plan"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-existing-plan-diff", FlowDesignation.AUTHENTICATION,
slug="test-existing-plan-diff",
designation=FlowDesignation.AUTHENTICATION,
) )
stage = DummyStage.objects.create(name="dummy") stage = DummyStage.objects.create(name=generate_id())
binding = FlowStageBinding(target=flow, stage=stage, order=0) binding = FlowStageBinding(target=flow, stage=stage, order=0)
plan = FlowPlan(flow_pk=flow.pk.hex + "a", bindings=[binding], markers=[StageMarker()]) plan = FlowPlan(flow_pk=flow.pk.hex + "a", bindings=[binding], markers=[StageMarker()])
session = self.client.session session = self.client.session
@ -77,10 +81,8 @@ class TestFlowExecutor(FlowTestCase):
) )
def test_invalid_non_applicable_flow(self): def test_invalid_non_applicable_flow(self):
"""Tests that a non-applicable flow returns the correct error message""" """Tests that a non-applicable flow returns the correct error message"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-non-applicable", FlowDesignation.AUTHENTICATION,
slug="test-non-applicable",
designation=FlowDesignation.AUTHENTICATION,
) )
CONFIG.update_from_dict({"domain": "testserver"}) CONFIG.update_from_dict({"domain": "testserver"})
@ -90,7 +92,7 @@ class TestFlowExecutor(FlowTestCase):
self.assertStageResponse( self.assertStageResponse(
response, response,
flow=flow, flow=flow,
error_message=FlowNonApplicableException.__doc__, error_message="foo",
component="ak-stage-access-denied", component="ak-stage-access-denied",
) )
@ -98,12 +100,15 @@ class TestFlowExecutor(FlowTestCase):
"authentik.flows.views.executor.to_stage_response", "authentik.flows.views.executor.to_stage_response",
TO_STAGE_RESPONSE_MOCK, TO_STAGE_RESPONSE_MOCK,
) )
def test_invalid_empty_flow(self): @patch(
"""Tests that an empty flow returns the correct error message""" "authentik.policies.engine.PolicyEngine.result",
flow = Flow.objects.create( POLICY_RETURN_FALSE,
name="test-empty", )
slug="test-empty", def test_invalid_non_applicable_flow_continue(self):
designation=FlowDesignation.AUTHENTICATION, """Tests that a non-applicable flow that should redirect"""
flow = create_test_flow(
FlowDesignation.AUTHENTICATION,
denied_action=FlowDeniedAction.CONTINUE,
) )
CONFIG.update_from_dict({"domain": "testserver"}) CONFIG.update_from_dict({"domain": "testserver"})
@ -119,10 +124,8 @@ class TestFlowExecutor(FlowTestCase):
) )
def test_invalid_flow_redirect(self): def test_invalid_flow_redirect(self):
"""Tests that an invalid flow still redirects""" """Tests that an invalid flow still redirects"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-empty", FlowDesignation.AUTHENTICATION,
slug="test-empty",
designation=FlowDesignation.AUTHENTICATION,
) )
CONFIG.update_from_dict({"domain": "testserver"}) CONFIG.update_from_dict({"domain": "testserver"})
@ -132,18 +135,33 @@ class TestFlowExecutor(FlowTestCase):
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, reverse("authentik_core:root-redirect")) self.assertEqual(response.url, reverse("authentik_core:root-redirect"))
@patch(
"authentik.flows.views.executor.to_stage_response",
TO_STAGE_RESPONSE_MOCK,
)
def test_invalid_empty_flow(self):
"""Tests that an empty flow returns the correct error message"""
flow = create_test_flow(
FlowDesignation.AUTHENTICATION,
)
CONFIG.update_from_dict({"domain": "testserver"})
response = self.client.get(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, reverse("authentik_core:root-redirect"))
def test_multi_stage_flow(self): def test_multi_stage_flow(self):
"""Test a full flow with multiple stages""" """Test a full flow with multiple stages"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-full", FlowDesignation.AUTHENTICATION,
slug="test-full",
designation=FlowDesignation.AUTHENTICATION,
) )
FlowStageBinding.objects.create( FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0
) )
FlowStageBinding.objects.create( FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy2"), order=1 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=1
) )
exec_url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}) exec_url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug})
@ -170,19 +188,19 @@ class TestFlowExecutor(FlowTestCase):
) )
def test_reevaluate_remove_last(self): def test_reevaluate_remove_last(self):
"""Test planner with re-evaluate (last stage is removed)""" """Test planner with re-evaluate (last stage is removed)"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-default-context", FlowDesignation.AUTHENTICATION,
slug="test-default-context", )
designation=FlowDesignation.AUTHENTICATION, false_policy = DummyPolicy.objects.create(
name=generate_id(), result=False, wait_min=1, wait_max=2
) )
false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2)
binding = FlowStageBinding.objects.create( binding = FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0
) )
binding2 = FlowStageBinding.objects.create( binding2 = FlowStageBinding.objects.create(
target=flow, target=flow,
stage=DummyStage.objects.create(name="dummy2"), stage=DummyStage.objects.create(name=generate_id()),
order=1, order=1,
re_evaluate_policies=True, re_evaluate_policies=True,
) )
@ -217,24 +235,24 @@ class TestFlowExecutor(FlowTestCase):
def test_reevaluate_remove_middle(self): def test_reevaluate_remove_middle(self):
"""Test planner with re-evaluate (middle stage is removed)""" """Test planner with re-evaluate (middle stage is removed)"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-default-context", FlowDesignation.AUTHENTICATION,
slug="test-default-context", )
designation=FlowDesignation.AUTHENTICATION, false_policy = DummyPolicy.objects.create(
name=generate_id(), result=False, wait_min=1, wait_max=2
) )
false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2)
binding = FlowStageBinding.objects.create( binding = FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0
) )
binding2 = FlowStageBinding.objects.create( binding2 = FlowStageBinding.objects.create(
target=flow, target=flow,
stage=DummyStage.objects.create(name="dummy2"), stage=DummyStage.objects.create(name=generate_id()),
order=1, order=1,
re_evaluate_policies=True, re_evaluate_policies=True,
) )
binding3 = FlowStageBinding.objects.create( binding3 = FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy3"), order=2 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=2
) )
PolicyBinding.objects.create(policy=false_policy, target=binding2, order=0) PolicyBinding.objects.create(policy=false_policy, target=binding2, order=0)
@ -277,24 +295,24 @@ class TestFlowExecutor(FlowTestCase):
def test_reevaluate_keep(self): def test_reevaluate_keep(self):
"""Test planner with re-evaluate (everything is kept)""" """Test planner with re-evaluate (everything is kept)"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-default-context", FlowDesignation.AUTHENTICATION,
slug="test-default-context", )
designation=FlowDesignation.AUTHENTICATION, true_policy = DummyPolicy.objects.create(
name=generate_id(), result=True, wait_min=1, wait_max=2
) )
true_policy = DummyPolicy.objects.create(result=True, wait_min=1, wait_max=2)
binding = FlowStageBinding.objects.create( binding = FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0
) )
binding2 = FlowStageBinding.objects.create( binding2 = FlowStageBinding.objects.create(
target=flow, target=flow,
stage=DummyStage.objects.create(name="dummy2"), stage=DummyStage.objects.create(name=generate_id()),
order=1, order=1,
re_evaluate_policies=True, re_evaluate_policies=True,
) )
binding3 = FlowStageBinding.objects.create( binding3 = FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy3"), order=2 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=2
) )
PolicyBinding.objects.create(policy=true_policy, target=binding2, order=0) PolicyBinding.objects.create(policy=true_policy, target=binding2, order=0)
@ -347,30 +365,30 @@ class TestFlowExecutor(FlowTestCase):
def test_reevaluate_remove_consecutive(self): def test_reevaluate_remove_consecutive(self):
"""Test planner with re-evaluate (consecutive stages are removed)""" """Test planner with re-evaluate (consecutive stages are removed)"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-default-context", FlowDesignation.AUTHENTICATION,
slug="test-default-context", )
designation=FlowDesignation.AUTHENTICATION, false_policy = DummyPolicy.objects.create(
name=generate_id(), result=False, wait_min=1, wait_max=2
) )
false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2)
binding = FlowStageBinding.objects.create( binding = FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0
) )
binding2 = FlowStageBinding.objects.create( binding2 = FlowStageBinding.objects.create(
target=flow, target=flow,
stage=DummyStage.objects.create(name="dummy2"), stage=DummyStage.objects.create(name=generate_id()),
order=1, order=1,
re_evaluate_policies=True, re_evaluate_policies=True,
) )
binding3 = FlowStageBinding.objects.create( binding3 = FlowStageBinding.objects.create(
target=flow, target=flow,
stage=DummyStage.objects.create(name="dummy3"), stage=DummyStage.objects.create(name=generate_id()),
order=2, order=2,
re_evaluate_policies=True, re_evaluate_policies=True,
) )
binding4 = FlowStageBinding.objects.create( binding4 = FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy4"), order=2 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=2
) )
PolicyBinding.objects.create(policy=false_policy, target=binding2, order=0) PolicyBinding.objects.create(policy=false_policy, target=binding2, order=0)
@ -415,13 +433,11 @@ class TestFlowExecutor(FlowTestCase):
def test_stageview_user_identifier(self): def test_stageview_user_identifier(self):
"""Test PLAN_CONTEXT_PENDING_USER_IDENTIFIER""" """Test PLAN_CONTEXT_PENDING_USER_IDENTIFIER"""
flow = Flow.objects.create( flow = create_test_flow(
name="test-default-context", FlowDesignation.AUTHENTICATION,
slug="test-default-context",
designation=FlowDesignation.AUTHENTICATION,
) )
FlowStageBinding.objects.create( FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy"), order=0 target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0
) )
ident = "test-identifier" ident = "test-identifier"
@ -443,10 +459,8 @@ class TestFlowExecutor(FlowTestCase):
def test_invalid_restart(self): def test_invalid_restart(self):
"""Test flow that restarts on invalid entry""" """Test flow that restarts on invalid entry"""
flow = Flow.objects.create( flow = create_test_flow(
name="restart-on-invalid", FlowDesignation.AUTHENTICATION,
slug="restart-on-invalid",
designation=FlowDesignation.AUTHENTICATION,
) )
# Stage 0 is a deny stage that is added dynamically # Stage 0 is a deny stage that is added dynamically
# when the reputation policy says so # when the reputation policy says so

View File

@ -9,6 +9,7 @@ from rest_framework.test import APITestCase
from authentik.core.tests.utils import create_test_admin_user from authentik.core.tests.utils import create_test_admin_user
from authentik.flows.challenge import ChallengeTypes from authentik.flows.challenge import ChallengeTypes
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, InvalidResponseAction from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, InvalidResponseAction
from authentik.lib.generators import generate_id
from authentik.stages.dummy.models import DummyStage from authentik.stages.dummy.models import DummyStage
from authentik.stages.identification.models import IdentificationStage, UserFields from authentik.stages.identification.models import IdentificationStage, UserFields
@ -24,8 +25,8 @@ class TestFlowInspector(APITestCase):
def test(self): def test(self):
"""test inspector""" """test inspector"""
flow = Flow.objects.create( flow = Flow.objects.create(
name="test-full", name=generate_id(),
slug="test-full", slug=generate_id(),
designation=FlowDesignation.AUTHENTICATION, designation=FlowDesignation.AUTHENTICATION,
) )

View File

@ -13,6 +13,26 @@ from authentik.policies.models import PolicyBinding
from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage
from authentik.stages.user_login.models import UserLoginStage from authentik.stages.user_login.models import UserLoginStage
STATIC_PROMPT_EXPORT = """{
"version": 1,
"entries": [
{
"identifiers": {
"pk": "cb954fd4-65a5-4ad9-b1ee-180ee9559cf4"
},
"model": "authentik_stages_prompt.prompt",
"attrs": {
"field_key": "username",
"label": "Username",
"type": "username",
"required": true,
"placeholder": "Username",
"order": 0
}
}
]
}"""
class TestFlowTransfer(TransactionTestCase): class TestFlowTransfer(TransactionTestCase):
"""Test flow transfer""" """Test flow transfer"""
@ -58,6 +78,22 @@ class TestFlowTransfer(TransactionTestCase):
self.assertTrue(Flow.objects.filter(slug=flow_slug).exists()) self.assertTrue(Flow.objects.filter(slug=flow_slug).exists())
def test_export_validate_import_re_import(self):
"""Test export and import it twice"""
count_initial = Prompt.objects.filter(field_key="username").count()
importer = FlowImporter(STATIC_PROMPT_EXPORT)
self.assertTrue(importer.validate())
self.assertTrue(importer.apply())
count_before = Prompt.objects.filter(field_key="username").count()
self.assertEqual(count_initial + 1, count_before)
importer = FlowImporter(STATIC_PROMPT_EXPORT)
self.assertTrue(importer.apply())
self.assertEqual(Prompt.objects.filter(field_key="username").count(), count_before)
def test_export_validate_import_policies(self): def test_export_validate_import_policies(self):
"""Test export and validate it""" """Test export and validate it"""
flow_slug = generate_id() flow_slug = generate_id()

View File

@ -27,6 +27,7 @@ def get_attrs(obj: SerializerModel) -> dict[str, Any]:
"promptstage_set", "promptstage_set",
"policybindingmodel_ptr_id", "policybindingmodel_ptr_id",
"export_url", "export_url",
"meta_model_name",
) )
for to_remove_name in to_remove: for to_remove_name in to_remove:
if to_remove_name in data: if to_remove_name in data:

View File

@ -28,6 +28,7 @@ ALLOWED_MODELS = (Flow, FlowStageBinding, Stage, Policy, PolicyBinding, Prompt)
def transaction_rollback(): def transaction_rollback():
"""Enters an atomic transaction and always triggers a rollback at the end of the block.""" """Enters an atomic transaction and always triggers a rollback at the end of the block."""
atomic = transaction.atomic() atomic = transaction.atomic()
# pylint: disable=unnecessary-dunder-call
atomic.__enter__() atomic.__enter__()
yield yield
atomic.__exit__(IntegrityError, None, None) atomic.__exit__(IntegrityError, None, None)
@ -115,6 +116,11 @@ class FlowImporter:
serializer_kwargs["instance"] = model_instance serializer_kwargs["instance"] = model_instance
else: else:
self.logger.debug("initialise new instance", model=model, **updated_identifiers) self.logger.debug("initialise new instance", model=model, **updated_identifiers)
model_instance = model()
# pk needs to be set on the model instance otherwise a new one will be generated
if "pk" in updated_identifiers:
model_instance.pk = updated_identifiers["pk"]
serializer_kwargs["instance"] = model_instance
full_data = self.__update_pks_for_attrs(entry.attrs) full_data = self.__update_pks_for_attrs(entry.attrs)
full_data.update(updated_identifiers) full_data.update(updated_identifiers)
serializer_kwargs["data"] = full_data serializer_kwargs["data"] = full_data
@ -167,7 +173,7 @@ class FlowImporter:
def validate(self) -> bool: def validate(self) -> bool:
"""Validate loaded flow export, ensure all models are allowed """Validate loaded flow export, ensure all models are allowed
and serializers have no errors""" and serializers have no errors"""
self.logger.debug("Starting flow import validaton") self.logger.debug("Starting flow import validation")
if self.__import.version != 1: if self.__import.version != 1:
self.logger.warning("Invalid bundle version") self.logger.warning("Invalid bundle version")
return False return False

View File

@ -10,6 +10,7 @@ from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect
from django.http.request import QueryDict from django.http.request import QueryDict
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.decorators.clickjacking import xframe_options_sameorigin from django.views.decorators.clickjacking import xframe_options_sameorigin
from django.views.generic import View from django.views.generic import View
@ -37,6 +38,7 @@ from authentik.flows.exceptions import EmptyFlowException, FlowNonApplicableExce
from authentik.flows.models import ( from authentik.flows.models import (
ConfigurableStage, ConfigurableStage,
Flow, Flow,
FlowDeniedAction,
FlowDesignation, FlowDesignation,
FlowStageBinding, FlowStageBinding,
FlowToken, FlowToken,
@ -49,21 +51,22 @@ from authentik.flows.planner import (
FlowPlan, FlowPlan,
FlowPlanner, FlowPlanner,
) )
from authentik.flows.stage import AccessDeniedChallengeView from authentik.flows.stage import AccessDeniedChallengeView, StageView
from authentik.lib.sentry import SentryIgnoredException from authentik.lib.sentry import SentryIgnoredException
from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.reflection import all_subclasses, class_to_path from authentik.lib.utils.reflection import all_subclasses, class_to_path
from authentik.lib.utils.urls import is_url_absolute, redirect_with_qs from authentik.lib.utils.urls import is_url_absolute, redirect_with_qs
from authentik.policies.engine import PolicyEngine
from authentik.tenants.models import Tenant from authentik.tenants.models import Tenant
LOGGER = get_logger() LOGGER = get_logger()
# Argument used to redirect user after login # Argument used to redirect user after login
NEXT_ARG_NAME = "next" NEXT_ARG_NAME = "next"
SESSION_KEY_PLAN = "authentik_flows_plan" SESSION_KEY_PLAN = "authentik/flows/plan"
SESSION_KEY_APPLICATION_PRE = "authentik_flows_application_pre" SESSION_KEY_APPLICATION_PRE = "authentik/flows/application_pre"
SESSION_KEY_GET = "authentik_flows_get" SESSION_KEY_GET = "authentik/flows/get"
SESSION_KEY_POST = "authentik_flows_post" SESSION_KEY_POST = "authentik/flows/post"
SESSION_KEY_HISTORY = "authentik_flows_history" SESSION_KEY_HISTORY = "authentik/flows/history"
QS_KEY_TOKEN = "flow_token" # nosec QS_KEY_TOKEN = "flow_token" # nosec
@ -129,21 +132,27 @@ class FlowExecutorView(APIView):
self._logger = get_logger().bind(flow_slug=flow_slug) self._logger = get_logger().bind(flow_slug=flow_slug)
set_tag("authentik.flow", self.flow.slug) set_tag("authentik.flow", self.flow.slug)
def handle_invalid_flow(self, exc: BaseException) -> HttpResponse: def handle_invalid_flow(self, exc: FlowNonApplicableException) -> HttpResponse:
"""When a flow is non-applicable check if user is on the correct domain""" """When a flow is non-applicable check if user is on the correct domain"""
if NEXT_ARG_NAME in self.request.GET: if self.flow.denied_action in [
if not is_url_absolute(self.request.GET.get(NEXT_ARG_NAME)): FlowDeniedAction.CONTINUE,
FlowDeniedAction.MESSAGE_CONTINUE,
]:
next_url = self.request.GET.get(NEXT_ARG_NAME)
if next_url and not is_url_absolute(next_url):
self._logger.debug("f(exec): Redirecting to next on fail") self._logger.debug("f(exec): Redirecting to next on fail")
return redirect(self.request.GET.get(NEXT_ARG_NAME)) return to_stage_response(self.request, redirect(next_url))
message = exc.__doc__ if exc.__doc__ else str(exc) if self.flow.denied_action == FlowDeniedAction.CONTINUE:
return self.stage_invalid(error_message=message) return to_stage_response(
self.request, redirect(reverse("authentik_core:root-redirect"))
)
return to_stage_response(self.request, self.stage_invalid(error_message=exc.messages))
def _check_flow_token(self, get_params: QueryDict): def _check_flow_token(self, key: str) -> Optional[FlowPlan]:
"""Check if the user is using a flow token to restore a plan""" """Check if the user is using a flow token to restore a plan"""
tokens = FlowToken.filter_not_expired(key=get_params[QS_KEY_TOKEN]) token: Optional[FlowToken] = FlowToken.filter_not_expired(key=key).first()
if not tokens.exists(): if not token:
return False return None
token: FlowToken = tokens.first()
try: try:
plan = token.plan plan = token.plan
except (AttributeError, EOFError, ImportError, IndexError) as exc: except (AttributeError, EOFError, ImportError, IndexError) as exc:
@ -164,7 +173,7 @@ class FlowExecutorView(APIView):
span.set_data("authentik Flow", self.flow.slug) span.set_data("authentik Flow", self.flow.slug)
get_params = QueryDict(request.GET.get("query", "")) get_params = QueryDict(request.GET.get("query", ""))
if QS_KEY_TOKEN in get_params: if QS_KEY_TOKEN in get_params:
plan = self._check_flow_token(get_params) plan = self._check_flow_token(get_params[QS_KEY_TOKEN])
if plan: if plan:
self.request.session[SESSION_KEY_PLAN] = plan self.request.session[SESSION_KEY_PLAN] = plan
# Early check if there's an active Plan for the current session # Early check if there's an active Plan for the current session
@ -188,7 +197,7 @@ class FlowExecutorView(APIView):
self.plan = self._initiate_plan() self.plan = self._initiate_plan()
except FlowNonApplicableException as exc: except FlowNonApplicableException as exc:
self._logger.warning("f(exec): Flow not applicable to current user", exc=exc) self._logger.warning("f(exec): Flow not applicable to current user", exc=exc)
return to_stage_response(self.request, self.handle_invalid_flow(exc)) return self.handle_invalid_flow(exc)
except EmptyFlowException as exc: except EmptyFlowException as exc:
self._logger.warning("f(exec): Flow is empty", exc=exc) self._logger.warning("f(exec): Flow is empty", exc=exc)
# To match behaviour with loading an empty flow plan from cache, # To match behaviour with loading an empty flow plan from cache,
@ -380,6 +389,8 @@ class FlowExecutorView(APIView):
"f(exec): Stage ok", "f(exec): Stage ok",
stage_class=class_to_path(self.current_stage_view.__class__), stage_class=class_to_path(self.current_stage_view.__class__),
) )
if isinstance(self.current_stage_view, StageView):
self.current_stage_view.cleanup()
self.request.session.get(SESSION_KEY_HISTORY, []).append(deepcopy(self.plan)) self.request.session.get(SESSION_KEY_HISTORY, []).append(deepcopy(self.plan))
self.plan.pop() self.plan.pop()
self.request.session[SESSION_KEY_PLAN] = self.plan self.request.session[SESSION_KEY_PLAN] = self.plan
@ -416,11 +427,14 @@ class FlowExecutorView(APIView):
SESSION_KEY_APPLICATION_PRE, SESSION_KEY_APPLICATION_PRE,
SESSION_KEY_PLAN, SESSION_KEY_PLAN,
SESSION_KEY_GET, SESSION_KEY_GET,
# We might need the initial POST payloads for later requests
# SESSION_KEY_POST,
# We don't delete the history on purpose, as a user might # We don't delete the history on purpose, as a user might
# still be inspecting it. # still be inspecting it.
# It's only deleted on a fresh executions # It's only deleted on a fresh executions
# SESSION_KEY_HISTORY, # SESSION_KEY_HISTORY,
] ]
self._logger.debug("f(exec): cleaning up")
for key in keys_to_delete: for key in keys_to_delete:
if key in self.request.session: if key in self.request.session:
del self.request.session[key] del self.request.session[key]
@ -466,6 +480,20 @@ class ToDefaultFlow(View):
designation: Optional[FlowDesignation] = None designation: Optional[FlowDesignation] = None
def flow_by_policy(self, request: HttpRequest, **flow_filter) -> Optional[Flow]:
"""Get a Flow by `**flow_filter` and check if the request from `request` can access it."""
flows = Flow.objects.filter(**flow_filter).order_by("slug")
for flow in flows:
engine = PolicyEngine(flow, request.user, request)
engine.build()
result = engine.result
if result.passing:
LOGGER.debug("flow_by_policy: flow passing", flow=flow)
return flow
LOGGER.warning("flow_by_policy: flow not passing", flow=flow, messages=result.messages)
LOGGER.debug("flow_by_policy: no flow found", filters=flow_filter)
return None
def dispatch(self, request: HttpRequest) -> HttpResponse: def dispatch(self, request: HttpRequest) -> HttpResponse:
tenant: Tenant = request.tenant tenant: Tenant = request.tenant
flow = None flow = None
@ -476,7 +504,7 @@ class ToDefaultFlow(View):
flow = tenant.flow_invalidation flow = tenant.flow_invalidation
# If no flow was set, get the first based on slug and policy # If no flow was set, get the first based on slug and policy
if not flow: if not flow:
flow = Flow.with_policy(request, designation=self.designation) flow = self.flow_by_policy(request, designation=self.designation)
# If we still don't have a flow, 404 # If we still don't have a flow, 404
if not flow: if not flow:
raise Http404 raise Http404

View File

@ -1,3 +1,4 @@
# update website/docs/installation/configuration.md
# This is the default configuration file # This is the default configuration file
postgresql: postgresql:
host: localhost host: localhost
@ -57,6 +58,10 @@ outposts:
container_image_base: ghcr.io/goauthentik/%(type)s:%(version)s container_image_base: ghcr.io/goauthentik/%(type)s:%(version)s
discover: true discover: true
ldap:
tls:
ciphers: null
cookie_domain: null cookie_domain: null
disable_update_check: false disable_update_check: false
disable_startup_analytics: false disable_startup_analytics: false

View File

@ -1,5 +1,5 @@
"""authentik sentry integration""" """authentik sentry integration"""
from typing import Optional from typing import Any, Optional
from aioredis.errors import ConnectionClosedError, ReplyError from aioredis.errors import ConnectionClosedError, ReplyError
from billiard.exceptions import SoftTimeLimitExceeded, WorkerLostError from billiard.exceptions import SoftTimeLimitExceeded, WorkerLostError
@ -17,7 +17,7 @@ from ldap3.core.exceptions import LDAPException
from redis.exceptions import ConnectionError as RedisConnectionError from redis.exceptions import ConnectionError as RedisConnectionError
from redis.exceptions import RedisError, ResponseError from redis.exceptions import RedisError, ResponseError
from rest_framework.exceptions import APIException from rest_framework.exceptions import APIException
from sentry_sdk import Hub from sentry_sdk import HttpTransport, Hub
from sentry_sdk import init as sentry_sdk_init from sentry_sdk import init as sentry_sdk_init
from sentry_sdk.api import set_tag from sentry_sdk.api import set_tag
from sentry_sdk.integrations.celery import CeleryIntegration from sentry_sdk.integrations.celery import CeleryIntegration
@ -30,6 +30,7 @@ from websockets.exceptions import WebSocketException
from authentik import __version__, get_build_hash from authentik import __version__, get_build_hash
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.lib.utils.http import authentik_user_agent
from authentik.lib.utils.reflection import class_to_path, get_env from authentik.lib.utils.reflection import class_to_path, get_env
LOGGER = get_logger() LOGGER = get_logger()
@ -52,11 +53,18 @@ class SentryIgnoredException(Exception):
"""Base Class for all errors that are suppressed, and not sent to sentry.""" """Base Class for all errors that are suppressed, and not sent to sentry."""
class SentryTransport(HttpTransport):
"""Custom sentry transport with custom user-agent"""
def __init__(self, options: dict[str, Any]) -> None:
super().__init__(options)
self._auth = self.parsed_dsn.to_auth(authentik_user_agent())
def sentry_init(**sentry_init_kwargs): def sentry_init(**sentry_init_kwargs):
"""Configure sentry SDK""" """Configure sentry SDK"""
sentry_env = CONFIG.y("error_reporting.environment", "customer") sentry_env = CONFIG.y("error_reporting.environment", "customer")
kwargs = { kwargs = {
"traces_sample_rate": float(CONFIG.y("error_reporting.sample_rate", 0.5)),
"environment": sentry_env, "environment": sentry_env,
"send_default_pii": CONFIG.y_bool("error_reporting.send_pii", False), "send_default_pii": CONFIG.y_bool("error_reporting.send_pii", False),
} }
@ -71,7 +79,9 @@ def sentry_init(**sentry_init_kwargs):
ThreadingIntegration(propagate_hub=True), ThreadingIntegration(propagate_hub=True),
], ],
before_send=before_send, before_send=before_send,
traces_sampler=traces_sampler,
release=f"authentik@{__version__}", release=f"authentik@{__version__}",
transport=SentryTransport,
**kwargs, **kwargs,
) )
set_tag("authentik.build_hash", get_build_hash("tagged")) set_tag("authentik.build_hash", get_build_hash("tagged"))
@ -83,6 +93,15 @@ def sentry_init(**sentry_init_kwargs):
) )
def traces_sampler(sampling_context: dict) -> float:
"""Custom sampler to ignore certain routes"""
path = sampling_context.get("asgi_scope", {}).get("path", "")
# Ignore all healthcheck routes
if path.startswith("/-/health") or path.startswith("/-/metrics"):
return 0
return float(CONFIG.y("error_reporting.sample_rate", 0.5))
def before_send(event: dict, hint: dict) -> Optional[dict]: def before_send(event: dict, hint: dict) -> Optional[dict]:
"""Check if error is database error, and ignore if so""" """Check if error is database error, and ignore if so"""
# pylint: disable=no-name-in-module # pylint: disable=no-name-in-module

View File

@ -1,10 +1,18 @@
"""error utils""" """error utils"""
from traceback import format_tb from traceback import extract_tb
TRACEBACK_HEADER = "Traceback (most recent call last):\n" from authentik.lib.utils.reflection import class_to_path
TRACEBACK_HEADER = "Traceback (most recent call last):"
def exception_to_string(exc: Exception) -> str: def exception_to_string(exc: Exception) -> str:
"""Convert exception to string stackrace""" """Convert exception to string stackrace"""
# Either use passed original exception or whatever we have # Either use passed original exception or whatever we have
return TRACEBACK_HEADER + "".join(format_tb(exc.__traceback__)) + str(exc) return "\n".join(
[
TRACEBACK_HEADER,
*[x.rstrip() for x in extract_tb(exc.__traceback__).format()],
f"{class_to_path(exc.__class__)}: {str(exc)}",
]
)

12
authentik/lib/xml.py Normal file
View File

@ -0,0 +1,12 @@
"""XML Utilities"""
from lxml.etree import XMLParser, fromstring # nosec
def get_lxml_parser():
"""Get XML parser"""
return XMLParser(resolve_entities=False)
def lxml_from_string(text: str):
"""Wrapper around fromstring"""
return fromstring(text, parser=get_lxml_parser())

View File

@ -12,5 +12,4 @@ class AuthentikManagedConfig(AppConfig):
def ready(self) -> None: def ready(self) -> None:
from authentik.managed.tasks import managed_reconcile from authentik.managed.tasks import managed_reconcile
# pyright: reportGeneralTypeIssues=false managed_reconcile.delay()
managed_reconcile.delay() # pylint: disable=no-value-for-parameter

View File

@ -11,7 +11,11 @@ from authentik.events.monitored_tasks import (
from authentik.managed.manager import ObjectManager from authentik.managed.manager import ObjectManager
@CELERY_APP.task(bind=True, base=MonitoredTask) @CELERY_APP.task(
bind=True,
base=MonitoredTask,
retry_backoff=True,
)
@prefill_task @prefill_task
def managed_reconcile(self: MonitoredTask): def managed_reconcile(self: MonitoredTask):
"""Run ObjectManager to ensure objects are up-to-date""" """Run ObjectManager to ensure objects are up-to-date"""
@ -22,3 +26,4 @@ def managed_reconcile(self: MonitoredTask):
) )
except DatabaseError as exc: # pragma: no cover except DatabaseError as exc: # pragma: no cover
self.set_status(TaskResult(TaskResultStatus.WARNING, [str(exc)])) self.set_status(TaskResult(TaskResultStatus.WARNING, [str(exc)]))
self.retry()

View File

@ -118,6 +118,7 @@ class DockerServiceConnectionViewSet(UsedByMixin, ModelViewSet):
serializer_class = DockerServiceConnectionSerializer serializer_class = DockerServiceConnectionSerializer
filterset_fields = ["name", "local", "url", "tls_verification", "tls_authentication"] filterset_fields = ["name", "local", "url", "tls_verification", "tls_authentication"]
ordering = ["name"] ordering = ["name"]
search_fields = ["name"]
class KubernetesServiceConnectionSerializer(ServiceConnectionSerializer): class KubernetesServiceConnectionSerializer(ServiceConnectionSerializer):
@ -152,3 +153,4 @@ class KubernetesServiceConnectionViewSet(UsedByMixin, ModelViewSet):
serializer_class = KubernetesServiceConnectionSerializer serializer_class = KubernetesServiceConnectionSerializer
filterset_fields = ["name", "local"] filterset_fields = ["name", "local"]
ordering = ["name"] ordering = ["name"]
search_fields = ["name"]

View File

@ -2,11 +2,20 @@
from importlib import import_module from importlib import import_module
from django.apps import AppConfig from django.apps import AppConfig
from django.db import ProgrammingError from prometheus_client import Gauge
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
LOGGER = get_logger() LOGGER = get_logger()
GAUGE_OUTPOSTS_CONNECTED = Gauge(
"authentik_outposts_connected", "Currently connected outposts", ["outpost", "uid", "expected"]
)
GAUGE_OUTPOSTS_LAST_UPDATE = Gauge(
"authentik_outposts_last_update",
"Last update from any outpost",
["outpost", "uid", "version"],
)
class AuthentikOutpostConfig(AppConfig): class AuthentikOutpostConfig(AppConfig):
"""authentik outposts app config""" """authentik outposts app config"""
@ -18,10 +27,3 @@ class AuthentikOutpostConfig(AppConfig):
def ready(self): def ready(self):
import_module("authentik.outposts.signals") import_module("authentik.outposts.signals")
import_module("authentik.outposts.managed") import_module("authentik.outposts.managed")
try:
from authentik.outposts.tasks import outpost_controller_all, outpost_local_connection
outpost_local_connection.delay()
outpost_controller_all.delay()
except ProgrammingError:
pass

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