Compare commits

..

324 commits

Author SHA1 Message Date
Jens Langhammer 1cd000dfe2
release: 2023.10.6 2024-01-09 18:50:48 +01:00
gcp-cherry-pick-bot[bot] 00ae97944a
providers/oauth2: fix CVE-2024-21637 (cherry-pick #8104) (#8105)
* providers/oauth2: fix CVE-2024-21637 (#8104)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update changelog

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2024-01-09 18:32:03 +01:00
gcp-cherry-pick-bot[bot] 9f3ccfb7c7
web/flows: fix device picker incorrect foreground color (cherry-pick #8067) (#8069)
web/flows: fix device picker incorrect foreground color (#8067)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2024-01-05 15:31:08 +01:00
gcp-cherry-pick-bot[bot] 9ed9c39ac8
rbac: fix error when looking up permissions for now uninstalled apps (cherry-pick #8068) (#8070)
rbac: fix error when looking up permissions for now uninstalled apps (#8068)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2024-01-05 15:30:59 +01:00
gcp-cherry-pick-bot[bot] 30b6eeee9f
outposts: disable deployment and secret reconciler for embedded outpost in code instead of in config (cherry-pick #8021) (#8024)
outposts: disable deployment and secret reconciler for embedded outpost in code instead of in config (#8021)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-30 21:40:54 +01:00
gcp-cherry-pick-bot[bot] afe2621783
providers/proxy: use access token (cherry-pick #8022) (#8023)
providers/proxy: use access token (#8022)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-30 18:30:42 +01:00
gcp-cherry-pick-bot[bot] 8b12c6a01a
outposts: fix Outpost reconcile not re-assigning managed attribute (cherry-pick #8014) (#8020)
outposts: fix Outpost reconcile not re-assigning managed attribute (#8014)

* outposts: fix Outpost reconcile not re-assigning managed attribute



* rework reconcile to find both name and managed outpost



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-30 15:37:36 +01:00
Jens Langhammer f63adfed96
core: fix PropertyMapping context not being available in request context
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-12-23 03:05:29 +01:00
gcp-cherry-pick-bot[bot] 9c8fec21cf
providers/oauth2: remember session_id from initial token (cherry-pick #7976) (#7977)
providers/oauth2: remember session_id from initial token (#7976)

* providers/oauth2: remember session_id original token was created with for future access/refresh tokens



* providers/proxy: use hashed session as `sid`



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-23 01:20:48 +01:00
Jens L 4776d2bcc5
sources/oauth: fix missing get_user_id for OIDC-like sources (Azure AD) (#7970)
* lib: add debug requests session that shows all sent requests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* sources/oauth: fix missing get_user_id for OIDC-like OAuth Sources

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	authentik/lib/utils/http.py
2023-12-22 00:13:42 +01:00
Jens Langhammer a15a040362
release: 2023.10.5 2023-12-21 14:18:36 +01:00
Jens L fcd6dc1d60
events: fix lint (#7700)
* events: fix lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* test without explicit poetry env use?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* delete previous poetry env

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* prevent invalid cached poetry envs

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* run test-from-stable as matrix and make required

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix missing postgres version

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* sigh

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* idk

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	.github/actions/setup/action.yml
#	.github/workflows/ci-main.yml
2023-12-19 18:40:14 +01:00
gcp-cherry-pick-bot[bot] acc3b59869
events: add better fallback for sanitize_item to ensure everything can be saved as JSON (cherry-pick #7694) (#7937)
events: add better fallback for sanitize_item to ensure everything can be saved as JSON (#7694)

* events: fix events sanitizing not handling all types



* remove some leftover prints



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-19 18:31:20 +01:00
gcp-cherry-pick-bot[bot] d9d5ac10e6
events: include user agent in events (cherry-pick #7693) (#7938)
events: include user agent in events (#7693)

* events: include user agent in events



* fix tests



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-19 18:31:06 +01:00
gcp-cherry-pick-bot[bot] 750669dcab
stages/email: improve error handling for incorrect template syntax (cherry-pick #7758) (#7936)
stages/email: improve error handling for incorrect template syntax (#7758)

* stages/email: improve error handling for incorrect template syntax



* add tests



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-19 18:30:56 +01:00
gcp-cherry-pick-bot[bot] 88a3eed67e
root: don't show warning when app has no URLs to import (cherry-pick #7765) (#7935)
root: don't show warning when app has no URLs to import (#7765)

Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-19 18:30:49 +01:00
gcp-cherry-pick-bot[bot] 6c214fffc4
blueprints: improve file change handler (cherry-pick #7813) (#7934)
blueprints: improve file change handler (#7813)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-19 18:30:37 +01:00
gcp-cherry-pick-bot[bot] 70100fc105
web/user: fix search not updating app (cherry-pick #7825) (#7933)
web/user: fix search not updating app (#7825)

web/user: fix app not updating

so when using two classes in a classMap directive, the update fails (basically saying that each class must be separated), however this error only shows when directly calling requestUpdate and is swallowed somewhere when relying on the default render cycle

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-19 18:30:23 +01:00
gcp-cherry-pick-bot[bot] 3c1163fabd
root: Fix cache related image build issues (cherry-pick #7831) (#7932)
Fix cache related image build issues

Co-authored-by: Philipp Kolberg <philipp.kolberg@t-online.de>
2023-12-19 18:30:15 +01:00
gcp-cherry-pick-bot[bot] 539e8242ff
web: fix overflow glitch on ak-page-header (cherry-pick #7883) (#7931)
web: fix overflow glitch on ak-page-header (#7883)

By adding 'grow' but not 'shrink' to the header section, the page was allowed to allocate
as much width as was available when the window opened, but not allowed to resize the width
if it was pushed closed by zoom, page resize, or summon sidebar.

This commit adds 'shrink' to the capabilities of the header.

Co-authored-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
2023-12-19 18:30:04 +01:00
gcp-cherry-pick-bot[bot] 2648333590
providers/scim: change familyName default (cherry-pick #7904) (#7930)
providers/scim: change familyName default (#7904)

* Update providers-scim.yaml



* fix: add formatted to match the givenName & familyName



* fix, update tests



---------

Signed-off-by: Antoine <antoine+github@jiveoff.fr>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
Co-authored-by: Antoine <antoine+github@jiveoff.fr>
2023-12-19 18:29:55 +01:00
gcp-cherry-pick-bot[bot] fe828ef993
tests: fix flaky tests (cherry-pick #7676) (#7939)
tests: fix flaky tests (#7676)

* tests: fix flaky tests



* make test-from-stable use actual latest version



* fix checkout



* remove hardcoded seed



* ignore tests for now i guess idk



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-12-19 18:29:44 +01:00
Jens L 29a6530742
web: dark/light theme fixes (#7872)
* web: fix css for user tree-view

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix unrelated things

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix header button colors

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix missing fallback not showing default slant

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* move global theme-dark css to only use for SSR rendered pages

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	.github/workflows/ci-main.yml
#	web/xliff/fr.xlf
2023-12-19 18:18:19 +01:00
Jens L a6b9274c4f
web/admin: always show oidc well-known URL fields when they're set (#7560)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	web/xliff/de.xlf
#	web/xliff/en.xlf
#	web/xliff/es.xlf
#	web/xliff/fr.xlf
#	web/xliff/pl.xlf
#	web/xliff/pseudo-LOCALE.xlf
#	web/xliff/tr.xlf
#	web/xliff/zh-Hans.xlf
#	web/xliff/zh-Hant.xlf
#	web/xliff/zh_TW.xlf
2023-12-19 18:10:40 +01:00
Jens Langhammer a2a67161ac
release: 2023.10.4 2023-11-21 18:38:24 +01:00
Jens Langhammer 2e8263a99b
web: fix locale
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-21 18:20:41 +01:00
gcp-cherry-pick-bot[bot] 6b9afed21f
security: fix CVE-2023-48228 (cherry-pick #7666) (#7668)
security: fix CVE-2023-48228 (#7666)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-21 18:13:54 +01:00
Jens L 1eb1f4e0b8
web/admin: fix admins not able to delete MFA devices (#7660)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	web/xliff/zh-Hans.xlf
2023-11-21 15:24:37 +01:00
gcp-cherry-pick-bot[bot] 7c3d60ec3a
events: don't update internal service accounts unless needed (cherry-pick #7611) (#7640)
events: stop spam (#7611)

* events: don't log updates to internal service accounts



* dont log reputation updates



* don't actually ignore things, stop updating outpost user when not required



* prevent updating internal service account users



* fix setattr call



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-20 19:43:30 +01:00
Jens L a494c6b6e8
root: specify node and python versions in respective config files, deduplicate in CI (#7620)
* root: specify node and python versions in respective config files, deduplicate in CI

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix engines missing for wdio

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* bump setup python version

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* actually don't bump a bunch of things

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	poetry.lock
#	website/package.json
2023-11-19 00:35:55 +01:00
gcp-cherry-pick-bot[bot] 6604d3577f
core: bump golang from 1.21.3-bookworm to 1.21.4-bookworm (cherry-pick #7483) (#7622)
core: bump golang from 1.21.3-bookworm to 1.21.4-bookworm

Bumps golang from 1.21.3-bookworm to 1.21.4-bookworm.

---
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>
2023-11-19 00:33:07 +01:00
gcp-cherry-pick-bot[bot] f8bfa7e16a
ci: fix permissions for release pipeline to publish binaries (cherry-pick #7512) (#7621)
ci: fix permissions for release pipeline to publish binaries (#7512)

ci: fix permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-19 00:31:20 +01:00
gcp-cherry-pick-bot[bot] ea6cf6eabf
events: fix missing model_* events when not directly authenticated (cherry-pick #7588) (#7597)
events: fix missing model_* events when not directly authenticated (#7588)

* events: fix missing model_* events when not directly authenticated



* defer accessing database



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-16 12:59:41 +01:00
gcp-cherry-pick-bot[bot] 769ce3ce7b
providers/scim: fix missing schemas attribute for User and Group (cherry-pick #7477) (#7596)
providers/scim: fix missing schemas attribute for User and Group (#7477)

* providers/scim: fix missing schemas attribute for User and Group



* make things actually work



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-16 12:06:01 +01:00
gcp-cherry-pick-bot[bot] 3891fb3fa8
events: sanitize functions (cherry-pick #7587) (#7589)
events: sanitize functions (#7587)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-15 23:24:13 +01:00
gcp-cherry-pick-bot[bot] 41eb965350
stages/email: use uuid for email confirmation token instead of username (cherry-pick #7581) (#7584)
stages/email: use uuid for email confirmation token instead of username (#7581)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-15 21:57:05 +01:00
gcp-cherry-pick-bot[bot] 8d95612287
providers/proxy: Fix duplicate cookies when using file system store. (cherry-pick #7541) (#7544)
providers/proxy: Fix duplicate cookies when using file system store. (#7541)

Fix duplicate cookies when using file system store.

Co-authored-by: thijs_a <thijs@thijsalders.nl>
2023-11-13 16:02:35 +01:00
Jens Langhammer 82b5274b15
release: 2023.10.3 2023-11-09 18:37:22 +01:00
gcp-cherry-pick-bot[bot] af56ce3d78
core: fix worker beat toggle inverted (cherry-pick #7508) (#7509)
core: fix worker beat toggle inverted (#7508)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-09 18:36:56 +01:00
gcp-cherry-pick-bot[bot] f5c6e7aeb0
Web: bugfix: broken backchannel selector (cherry-pick #7480) (#7507)
Web: bugfix: broken backchannel selector (#7480)

* web: break circular dependency between AKElement & Interface.

This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.

I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.

* web: fix broken typescript references

This built... and then it didn't?  Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.

* web: rollback dependabot's upgrade of context

The most frustrating part of this is that I RAN THIS, dammit, with the updated
context and the current Wizard, and it finished the End-to-End tests without
complaint.

* web: bugfix: broken backchannel selector

There were two bugs here, both of them introduced by me because I didn't understand the
system well enough the first time through, and because I didn't test thoroughly enough.

The first is that I was calling the wrong confirmation code; the resulting syntax survived
because `confirm()` is actually a legitimate function call in the context of the DOM Window,
a legacy survivor similar to `alert()` but with a yes/no return value. Bleah.

The second is that the confirm code doesn't appear to pass back a dictionary with the
`{ items: Array<Provider> }` list, it passes back just the `items` as an Array.

Co-authored-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
2023-11-09 17:58:38 +01:00
gcp-cherry-pick-bot[bot] 3809400e93
events: fix gdpr compliance always running (cherry-pick #7491) (#7505)
events: fix gdpr compliance always running

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-11-09 17:57:25 +01:00
gcp-cherry-pick-bot[bot] 1def9865cf
web/flows: attempt to fix bitwareden android compatibility (cherry-pick #7455) (#7457)
web/flows: attempt to fix bitwareden android compatibility (#7455)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-06 23:58:44 +01:00
gcp-cherry-pick-bot[bot] 3716298639
sources/oauth: fix patreon (cherry-pick #7454) (#7456)
sources/oauth: fix patreon (#7454)

* web/admin: add note for potentially confusing consumer key/secret



* sources/oauth: fix patreon default scopes



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-06 16:36:22 +01:00
gcp-cherry-pick-bot[bot] c16317d7cf
providers/proxy: fix closed redis client (cherry-pick #7385) (#7429)
providers/proxy: fix closed redis client (#7385)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 15:46:17 +01:00
gcp-cherry-pick-bot[bot] bbb8fa8269
ci: explicitly give write permissions to packages (cherry-pick #7428) (#7430)
ci: explicitly give write permissions to packages (#7428)

* ci: explicitly give write permissions to packages



* run full CI on cherry-picks



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 15:46:00 +01:00
gcp-cherry-pick-bot[bot] e4c251a178
web/admin: fix html error on oauth2 provider page (cherry-pick #7384) (#7424)
web/admin: fix html error on oauth2 provider page (#7384)

* web: break circular dependency between AKElement & Interface.

This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.

I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.

* web: fix broken typescript references

This built... and then it didn't?  Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.

* \# Details

Extra `>` symbol screwed up the reading of the rest of the component.  Unfortunately,
too many fields in an input are optional, so it was easy for this bug to bypass any
checks by the validators.  I should have caught it myself, though.

Co-authored-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
2023-11-03 13:17:26 +01:00
gcp-cherry-pick-bot[bot] 0fefd5f522
stages/email: fix duplicate querystring encoding (cherry-pick #7386) (#7425)
stages/email: fix duplicate querystring encoding (#7386)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 13:17:18 +01:00
gcp-cherry-pick-bot[bot] 88057db0b0
providers/oauth2: set auth_via for token and other endpoints (cherry-pick #7417) (#7427)
providers/oauth2: set auth_via for token and other endpoints (#7417)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 13:17:10 +01:00
gcp-cherry-pick-bot[bot] 91cb6c9beb
root: Improve multi arch Docker image build speed (cherry-pick #7355) (#7426)
root: Improve multi arch Docker image build speed (#7355)

* Improve multi arch Docker image build speed

Use only host architecture for GeoIP database update and for Go cross-compilation

* Speedup Go multi-arch compilation for other images

* Speedup multi-arch ldap image build

Co-authored-by: Philipp Kolberg <39984529+PKizzle@users.noreply.github.com>
2023-11-03 13:16:54 +01:00
Jens Langhammer 8e72fcab59
release: 2023.10.2 2023-10-28 21:43:54 +02:00
Jens L 261879022d
security: fix oobe-flow reuse when akadmin is deleted (#7361)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 21:24:06 +02:00
Jens L 2a47ff2977
website/docs: prepare 2023.10.2 release notes (#7362)
website/docs: prepare 2023.10.2

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 21:07:57 +02:00
Jens L c3a81a1cce
website/docs: add missing breaking change due to APPEND_SLASH (#7360)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 18:13:56 +02:00
Jens L 220d739fef
lifecycle: rework otp_merge migration (#7359)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 17:56:04 +02:00
transifex-integration[bot] 4a57c6f230
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7354)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-27 20:41:31 +02:00
transifex-integration[bot] 4a93b97bec
translate: Updates for file web/xliff/en.xlf in zh_CN (#7353)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-27 20:41:17 +02:00
risson ac2bbd7e2f
website/docs: add warning about Helm breaking change in 2024.x (#7351)
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-10-27 17:22:02 +00:00
Jens L ad9f500ad1
crypto: fix race conditions when creating self-signed certificates on startup (#7344)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 16:29:10 +02:00
Jens L 15d7175750
blueprints: fix entries with state: absent not being deleted if their serializer has errors (#7345)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 16:28:56 +02:00
Jens L 41d372a340
web/admin: fix @change handler for ak-radio elements (#7348)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 16:28:18 +02:00
Jens L 83b84e8d26
rbac: handle lookup error (#7341)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 13:38:44 +02:00
Jens L f22daca091
website/docs: add warning about upgrading to 2023.10 (#7340)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 12:51:49 +02:00
Jens L ae4d5a30f2
web/admin: fix role form reacting to enter (#7330)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 11:39:39 +02:00
dependabot[bot] 9708481005
core: bump github.com/google/uuid from 1.3.1 to 1.4.0 (#7333)
Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.3.1 to 1.4.0.
- [Release notes](https://github.com/google/uuid/releases)
- [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/uuid/compare/v1.3.1...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/google/uuid
  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>
2023-10-27 11:13:27 +02:00
dependabot[bot] 1c32c9e06d
core: bump goauthentik.io/api/v3 from 3.2023083.10 to 3.2023101.1 (#7334)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.10 to 3.2023101.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.10...v3.2023101.1)

---
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>
2023-10-27 11:13:14 +02:00
dependabot[bot] 7a3d92ffdb
core: bump ruff from 0.1.2 to 0.1.3 (#7335)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.2 to 0.1.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.1.2...v0.1.3)

---
updated-dependencies:
- dependency-name: ruff
  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>
2023-10-27 11:13:01 +02:00
dependabot[bot] a72b36d94d
core: bump pydantic-scim from 0.0.7 to 0.0.8 (#7336)
Bumps [pydantic-scim](https://chalk.ai) from 0.0.7 to 0.0.8.

---
updated-dependencies:
- dependency-name: pydantic-scim
  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>
2023-10-27 11:12:52 +02:00
Tana M Berry 6b25f6f592
website/blogs: Blog dockers (#7328)
* Dockers blog draft

* redo

* renamed dir

* renamed directory

* added email address

* formatting

* title tweak

* Kens edits

* link

---------

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-10-26 21:19:14 -05:00
Jens L 7d91842e8a
providers/proxy: attempt to fix duplicate cookie (#7324)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 00:41:13 +02:00
Jens L 2b4b1d2f76
stages/email: fix sending emails from task (#7325)
closes #7322

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 00:39:06 +02:00
authentik-automation[bot] 2ce5c74f33
web: bump API Client version (#7321)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-26 21:50:17 +02:00
Jens Langhammer 168fabfc70
Merge branch 'version-2023.10' 2023-10-26 21:20:55 +02:00
Jens L eb53c28352
website/docs: update release notes for 2023.10.1 (#7316)
website/docs: update for 2023.10.1

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 20:16:07 +02:00
Jens Langhammer 64c38909ff
release: 2023.10.1 2023-10-26 20:06:05 +02:00
Jens L 940492a5e1
lifecycle: fix otp merge migration (#7315)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 20:05:33 +02:00
Jens L 134799c734
root: fix pylint errors (#7312) 2023-10-26 19:57:11 +02:00
authentik-automation[bot] e086da68cd
web: bump API Client version (#7311)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-26 16:23:15 +00:00
Jens Langhammer ed46fd629e
release: 2023.10.0 2023-10-26 16:51:57 +02:00
Jens Langhammer 12bb1554f6
ci: fix release pipeline
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 16:51:52 +02:00
Jens Langhammer 263d9128c4
stages/email: fix path for email icon
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 16:06:00 +02:00
Jens Langhammer 8c6aaf4a2d
ci: fix test build
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 15:18:47 +02:00
Jens L d9b3e307e3
website/docs: add 2023.10 release notes (#7309)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 15:10:17 +02:00
authentik-automation[bot] 709fd716d8
web: bump API Client version (#7310)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-26 12:49:59 +00:00
Jens L 28053059ff
stages/user_write: allow setting user type when creating new user (#7293)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 14:33:29 +02:00
transifex-integration[bot] 94ad839437
translate: Updates for file web/xliff/en.xlf in fr (#7297)
* Translate web/xliff/en.xlf in fr

100% translated source file: 'web/xliff/en.xlf'
on 'fr'.

* Removing web/xliff/en.xlf in fr

99% of minimum 100% translated source file: 'web/xliff/en.xlf'
on 'fr'.

* Translate web/xliff/en.xlf in fr

100% translated source file: 'web/xliff/en.xlf'
on 'fr'.

---------

Signed-off-by: Jens L. <jens@goauthentik.io>
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-10-26 10:48:19 +00:00
Tana M Berry 84fdd3c750
website/docs: RBAC docs (#7191)
* draft rbac docs

* tweaks

* add a permissions topic

* tweaks

* more changes

* draft permissions topic

* more content on roles

* links

* typo

* more conceptual info

* Optimised images with calibre/image-actions

* more content on roles

* add more x-ref links

* fix links

* more content

* links

* typos

* polishing

* Update website/docs/user-group-role/access-control/permissions.md

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* separwate conceptual vs procedural in permissions

* finished groups procedurals

* new page

* added link

* Update website/docs/user-group-role/access-control/permissions.md

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* polish

* edits from PR review

* restructured view section to remove repetition

* rest of edits from PR review

* polished flows and stages

* polish

* typo

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-10-26 12:31:32 +02:00
dependabot[bot] 3f5d5e0408
web: bump fuse.js from 6.6.2 to 7.0.0 in /web (#7307)
Bumps [fuse.js](https://github.com/krisk/Fuse) from 6.6.2 to 7.0.0.
- [Release notes](https://github.com/krisk/Fuse/releases)
- [Changelog](https://github.com/krisk/Fuse/blob/main/CHANGELOG.md)
- [Commits](https://github.com/krisk/Fuse/compare/v6.6.2...v7.0.0)

---
updated-dependencies:
- dependency-name: fuse.js
  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>
2023-10-26 12:29:25 +02:00
dependabot[bot] 309c390154
web: bump lit-analyzer from 1.2.1 to 2.0.1 in /web (#7305)
Bumps [lit-analyzer](https://github.com/runem/lit-analyzer) from 1.2.1 to 2.0.1.
- [Release notes](https://github.com/runem/lit-analyzer/releases)
- [Changelog](https://github.com/runem/lit-analyzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/runem/lit-analyzer/commits)

---
updated-dependencies:
- dependency-name: lit-analyzer
  dependency-type: direct:development
  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>
2023-10-26 12:03:14 +02:00
dependabot[bot] 32493c6102
web: bump the sentry group in /web with 2 updates (#7303)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.75.0 to 7.75.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.75.0...7.75.1)

Updates `@sentry/tracing` from 7.75.0 to 7.75.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.75.0...7.75.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-26 11:52:45 +02:00
dependabot[bot] 7569314a24
web: bump mermaid from 10.5.1 to 10.6.0 in /web (#7304)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.5.1 to 10.6.0.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.5.1...v10.6.0)

---
updated-dependencies:
- dependency-name: mermaid
  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>
2023-10-26 11:52:14 +02:00
dependabot[bot] e640eab229
core: bump duo-client from 5.1.0 to 5.2.0 (#7306)
Bumps [duo-client](https://github.com/duosecurity/duo_client_python) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/duosecurity/duo_client_python/releases)
- [Commits](https://github.com/duosecurity/duo_client_python/compare/5.1.0...5.2.0)

---
updated-dependencies:
- dependency-name: duo-client
  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>
2023-10-26 11:51:51 +02:00
dependabot[bot] 848fe3e428
web: bump ts-lit-plugin from 1.2.1 to 2.0.0 in /web (#7308)
Bumps [ts-lit-plugin](https://github.com/runem/lit-analyzer) from 1.2.1 to 2.0.0.
- [Release notes](https://github.com/runem/lit-analyzer/releases)
- [Changelog](https://github.com/runem/lit-analyzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/runem/lit-analyzer/commits)

---
updated-dependencies:
- dependency-name: ts-lit-plugin
  dependency-type: direct:development
  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>
2023-10-26 11:51:20 +02:00
Ken Sternberg a52e4a3262
web: extract form processing (#7298)
* web: break circular dependency between AKElement & Interface.

This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.

I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.

* web: fix broken typescript references

This built... and then it didn't?  Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.

* web: extract the form processing from the form submission process

Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.

That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone.  Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.

w
2023-10-25 14:39:50 -07:00
transifex-integration[bot] 7f2d03dcd0
translate: Updates for file web/xliff/en.xlf in zh_CN (#7299)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-25 21:21:57 +02:00
transifex-integration[bot] 484cbc8c73
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7300)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-25 21:21:40 +02:00
Jens L f6118ec876
web/admin: add preview banner to RBAC pages (#7295)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-25 20:15:28 +02:00
Marc 'risson' Schmitt 488420eeb6 web: fix typo in traefik name
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-10-25 18:55:37 +02:00
Jens L a8f066eb51
web/admin: disable wizard banner for now (#7294)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-25 18:30:58 +02:00
Jens L 7673e5a297
web/admin: small fixes (#7292)
* show user type better on admin interface

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix rendering for backchannel in app form

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix missing trailing slash in admin redirect

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-25 18:25:37 +02:00
Oleh Vivtash add873ca9b
core: Use branding_title in the end session page (#7282)
Update end_session.html

Use branding_title in the end session "You've logged out of" section

Signed-off-by: Oleh Vivtash <oleh@vivtash.net>
2023-10-25 15:55:20 +02:00
dependabot[bot] f12a533e91
web: bump pyright from 1.1.332 to 1.1.333 in /web (#7287)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.332 to 1.1.333.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.333/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  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>
2023-10-25 12:10:08 +02:00
dependabot[bot] 18766d6d41
website: bump react-tooltip from 5.21.5 to 5.21.6 in /website (#7283)
Bumps [react-tooltip](https://github.com/ReactTooltip/react-tooltip) from 5.21.5 to 5.21.6.
- [Release notes](https://github.com/ReactTooltip/react-tooltip/releases)
- [Changelog](https://github.com/ReactTooltip/react-tooltip/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ReactTooltip/react-tooltip/compare/v5.21.5...v5.21.6)

---
updated-dependencies:
- dependency-name: react-tooltip
  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>
2023-10-25 12:09:49 +02:00
dependabot[bot] 3dd1094c50
web: bump the sentry group in /web with 2 updates (#7285)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.74.1 to 7.75.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.74.1...7.75.0)

Updates `@sentry/tracing` from 7.74.1 to 7.75.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.74.1...7.75.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-25 12:09:36 +02:00
dependabot[bot] 9b2ed944dc
web: bump the eslint group in /web with 1 update (#7286)
Bumps the eslint group in /web with 1 update: [eslint-plugin-lit](https://github.com/43081j/eslint-plugin-lit).

- [Commits](https://github.com/43081j/eslint-plugin-lit/compare/v1.9.1...v1.10.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-lit
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-25 12:09:27 +02:00
dependabot[bot] a445463a92
core: bump ruff from 0.1.1 to 0.1.2 (#7289)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.1 to 0.1.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.1.1...v0.1.2)

---
updated-dependencies:
- dependency-name: ruff
  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>
2023-10-25 12:09:17 +02:00
dependabot[bot] cefdf98b22
core: bump pytest from 7.4.2 to 7.4.3 (#7288)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.2 to 7.4.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.2...7.4.3)

---
updated-dependencies:
- dependency-name: pytest
  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>
2023-10-25 12:09:03 +02:00
dependabot[bot] f675c25b83
web: bump the wdio group in /tests/wdio with 3 updates (#7290)
Bumps the wdio group in /tests/wdio with 3 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner) and [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework).


Updates `@wdio/cli` from 8.20.2 to 8.20.5
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.20.5/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.20.0 to 8.20.5
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.20.5/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.20.0 to 8.20.3
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.20.3/packages/wdio-mocha-framework)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-25 12:08:42 +02:00
Tana M Berry aa954c4807
website/blogs: fixed typo in blog (#7281)
typo

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-10-24 16:02:26 -05:00
dependabot[bot] 87f2b37348
core: bump pylint from 2.17.7 to 3.0.2 (#7270)
* core: bump pylint from 2.17.7 to 3.0.2

Bumps [pylint](https://github.com/pylint-dev/pylint) from 2.17.7 to 3.0.2.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v2.17.7...v3.0.2)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  update-type: version-update:semver-major
...

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

* fix pylint warning

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-24 12:37:37 +02:00
dependabot[bot] 1d36d84229
web: bump the eslint group in /tests/wdio with 2 updates (#7274)
Bumps the eslint group in /tests/wdio with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.8.0 to 6.9.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/v6.9.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.8.0 to 6.9.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/v6.9.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 11:45:17 +02:00
transifex-integration[bot] 0091690863
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7278)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-24 11:45:05 +02:00
transifex-integration[bot] a289125108
translate: Updates for file web/xliff/en.xlf in zh_CN (#7277)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-24 11:44:47 +02:00
dependabot[bot] e26019b14b
ci: bump actions/setup-node from 3 to 4 (#7268)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  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>
2023-10-24 11:44:27 +02:00
dependabot[bot] 60981228d4
core: bump pylint-django from 2.5.4 to 2.5.5 (#7271)
Bumps [pylint-django](https://github.com/PyCQA/pylint-django) from 2.5.4 to 2.5.5.
- [Release notes](https://github.com/PyCQA/pylint-django/releases)
- [Changelog](https://github.com/pylint-dev/pylint-django/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/PyCQA/pylint-django/commits)

---
updated-dependencies:
- dependency-name: pylint-django
  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>
2023-10-24 11:44:06 +02:00
dependabot[bot] 03a0914553
web: bump the eslint group in /web with 2 updates (#7269)
Bumps the eslint group in /web with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.8.0 to 6.9.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/v6.9.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.8.0 to 6.9.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/v6.9.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 11:43:56 +02:00
dependabot[bot] 959fce2198
web: bump @trivago/prettier-plugin-sort-imports from 4.2.0 to 4.2.1 in /tests/wdio (#7275)
web: bump @trivago/prettier-plugin-sort-imports in /tests/wdio

Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.2.0...v4.2.1)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  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>
2023-10-24 11:43:40 +02:00
dependabot[bot] 1c171e4e55
core: bump black from 23.10.0 to 23.10.1 (#7273)
Bumps [black](https://github.com/psf/black) from 23.10.0 to 23.10.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.10.0...23.10.1)

---
updated-dependencies:
- dependency-name: black
  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>
2023-10-24 11:43:30 +02:00
dependabot[bot] 50780b62a7
web: bump @trivago/prettier-plugin-sort-imports from 4.2.0 to 4.2.1 in /web (#7272)
web: bump @trivago/prettier-plugin-sort-imports in /web

Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.2.0...v4.2.1)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  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>
2023-10-24 11:42:39 +02:00
Tana M Berry e60820a9d1
website/blogs: edited to add 1Password (#7266)
* edited to add 1Password

* edits

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-10-23 20:27:46 -05:00
Jens L c0fe99714f
stages/authenticator_sms: fix error when phone number from context already exists (#7264) 2023-10-24 02:42:16 +02:00
Jens Langhammer 6f67c1a277
website: fix blog title quotation
also fix typo

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-24 02:02:48 +02:00
Tana M Berry 04d27cbcb6
website/blogs: Okta breach blog (#7265)
* draft for Okta blog

* polish and edit

* Update website/blog/2023-10-23-another-okta-breach/item.md

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/blog/2023-10-23-another-okta-breach/item.md

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/blog/2023-10-23-another-okta-breach/item.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/blog/2023-10-23-another-okta-breach/item.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/blog/2023-10-23-another-okta-breach/item.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-10-23 23:51:07 +00:00
Ken Sternberg e3ac774a18
web: 3 fixes for small typos, annoyances, and improvements (#7249)
I'm conducting a more comprehensive survey of the UI in order to get a more holistic idea of the
changes that should be implemented.  Along the way, I'm finding a few small details that annoy me.
Here are three.

It goes to "User statistics."  I have changed both the text of the link and the page to read "User
Statistics" (it's a title, it should be capitalized).

Give people warning when you're about to take them out of the system, especially if you're opening a
new tab along the way.

Just a thing I spotted along the way.
2023-10-23 10:48:16 -07:00
Jens L 75aedb4d3f
web/admin: small wizard fixes (#7259) 2023-10-23 18:48:12 +02:00
dependabot[bot] f3e02f9281
core: bump pylint-django from 2.5.3 to 2.5.4 (#7255)
Bumps [pylint-django](https://github.com/PyCQA/pylint-django) from 2.5.3 to 2.5.4.
- [Release notes](https://github.com/PyCQA/pylint-django/releases)
- [Changelog](https://github.com/pylint-dev/pylint-django/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/PyCQA/pylint-django/compare/v2.5.3...v2.5.4)

---
updated-dependencies:
- dependency-name: pylint-django
  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>
2023-10-23 11:13:14 +02:00
dependabot[bot] 1e254b63a0
core: bump goauthentik.io/api/v3 from 3.2023083.9 to 3.2023083.10 (#7256)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.9 to 3.2023083.10.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.9...v3.2023083.10)

---
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>
2023-10-23 11:13:05 +02:00
dependabot[bot] 09ba0c470a
web: bump the wdio group in /tests/wdio with 1 update (#7258)
Bumps the wdio group in /tests/wdio with 1 update: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli).

- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.20.2/packages/wdio-cli)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-23 11:12:56 +02:00
dependabot[bot] 549d6d7c8e
web: bump the eslint group in /tests/wdio with 1 update (#7257)
Bumps the eslint group in /tests/wdio with 1 update: [eslint](https://github.com/eslint/eslint).

- [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.51.0...v8.52.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-23 11:12:28 +02:00
Jens L 616f0b8b4f
sources/oauth: fix name clash (#7253)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-21 20:29:36 +02:00
dependabot[bot] 52a452488c
web: bump the eslint group in /web with 1 update (#7250) 2023-10-21 15:54:01 +02:00
dependabot[bot] b13f7158c7
web: bump mermaid from 10.5.0 to 10.5.1 in /web (#7247)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.5.0 to 10.5.1.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.5.0...v10.5.1)

---
updated-dependencies:
- dependency-name: mermaid
  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>
2023-10-21 00:42:31 +02:00
Ken Sternberg 9582cd4599
web: break circular dependency between AKElement & Interface. (#7165)
* web: break circular dependency between AKElement & Interface.

This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.

I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.

* web: fix broken typescript references

This built... and then it didn't?  Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
2023-10-20 14:26:57 -07:00
Jens L 7e213f3ca6
sources/oauth: fix oidc well-known parsing (#7248) 2023-10-20 20:37:52 +02:00
Ken Sternberg cc781cad00
web/admin: improve user email button labels (#7233)
* web: isolate clipboard handling

We would like to use the clipboard for more than just the token copy button.  This commit
enables that by separating the "Write to Clipboard" and "Write to Notifications" routines
into separate functions, putting "writeToClipboard" into the utilities collection, and
clarifying what happens when a custom presses the TokenCopy button.

* web: break out the recovery link logic into a standalone function

UserViewPage and UserLinkPage have the same functionality to request to view a
link with which a user may access an account recovery flow.  The language and
error messages were different on both of those pages.  This commit harmonizes
the language by making the request a standalone function.  It also exploits the
breakout of the "write to clipboard" commit to write the link to the clipboard,
and to inform the user that the clipboard has been written to, when possible.

* web: parity between UserViewPage and UserListPage

Since the UserListPage's "accordion" view has an offer to "Email
the recovery link" to the user, it seemed appropriate to grant the
same capability to the UserListPage.

* web: harmonize the CSS.

After a bit of messing around, I have also ensured that the gap between the buttons is
the same in all cases, that in the columnar display the buttons are of uniform width,
and that the buttons have the same next:

- "Set Password"
- "View Recovery Link"
- "Email Recovery Link"

NOTE: This commit is contingent upon the PR for [isolate clipboard
handling](https://github.com/goauthentik/authentik/pull/7229) to
be accepted, as it relies on the clipboard handler for the "write
link to clipboard" feature.

* web: ensure the existence of the user

Every `...render()` method in the UserViewPage class has a preamble
guard clause:

```
    if (!this.user) {
        return html``;
    }
```

With this clause, it should not be necessary to repeatedly check
the type of `this.user` throughout the rest of the method, but the
nominal type is `User?`, which means that functions called from
within the method need to be protected against `undefined` failure.
By creating a new variable with the type after the guard clause,
we ensure the type is `User` (no question!) and can safely use it
without those checks.

Along the way, I replaced the empty html with `nothing` and corrected
(mostly by removing) the return types.

References:

- [Lit-HTML: Prefer `nothing` over empty html or other falsey walues](https://lit.dev/docs/api/templates/#nothing)
- [TypeScript: Type annotations on return types are rarely
necessary](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#:~:text=Return%20Type%20Annotations&text=Much%20like%20variable%20type%20annotations,example%20doesn't%20change%20anything.)

* web: accepting suggested label change
2023-10-20 10:01:18 -07:00
authentik-automation[bot] cbbb638ca7
web: bump API Client version (#7246)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-20 15:27:21 +00:00
Jens L 63426bc9a8
sources/oauth: include default JWKS URLs for OAuth sources (#6992)
* sources/oauth: include default JWKS URLs for OAuth sources

makes it easier to use pre-defined types like github, google, azure with JWT M2M instead of needing to create a generic OAuth Source

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix error

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-20 16:54:03 +02:00
Jens L 63c52fd936
sources/oauth: periodically update OAuth sources' OIDC configuration (#7245)
* sources/oauth: periodically update OAuth sources' OIDC configuration

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make monitored task

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-20 16:51:37 +02:00
Tana M Berry 5e5bc5cd49
website/blogs: Fix sso blog to remove 3rd reason (#7230)
* edits form Nick

* links

---------

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-10-20 07:30:48 -05:00
Jens L 6fb7586b00
lifecycle: fix otp_merge migration again (#7244)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-20 14:27:57 +02:00
dependabot[bot] e0da3bf2b4
web: bump core-js from 3.33.0 to 3.33.1 in /web (#7243)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.33.0 to 3.33.1.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.33.1/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  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>
2023-10-20 11:46:10 +02:00
dependabot[bot] db76446099
core: bump node from 20 to 21 (#7237)
Bumps node from 20 to 21.

---
updated-dependencies:
- dependency-name: node
  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>
2023-10-20 11:17:58 +02:00
Ken Sternberg 20e003656a
web: fix bad comment that was confusing lit-analyze (#7234)
The old comment was left over from a previous revision of the wizard, and
blocked lit-analyze's ability to understand the Modal's `slot="trigger"`
declaration.
2023-10-20 11:17:24 +02:00
transifex-integration[bot] ce4c654209
translate: Updates for file web/xliff/en.xlf in zh_CN (#7235)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-20 11:16:59 +02:00
dependabot[bot] 1dedfaeaac
core: bump ruff from 0.1.0 to 0.1.1 (#7238)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.0 to 0.1.1.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.1.0...v0.1.1)

---
updated-dependencies:
- dependency-name: ruff
  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>
2023-10-20 11:16:40 +02:00
dependabot[bot] 5b2a1f9fb4
core: bump twilio from 8.9.1 to 8.10.0 (#7239)
Bumps [twilio](https://github.com/twilio/twilio-python) from 8.9.1 to 8.10.0.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/8.9.1...8.10.0)

---
updated-dependencies:
- dependency-name: twilio
  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>
2023-10-20 11:16:29 +02:00
dependabot[bot] 2cf337f731
web: bump the storybook group in /web with 5 updates (#7240)
Bumps the storybook group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `7.5.0` | `7.5.1` |
| [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `7.5.0` | `7.5.1` |
| [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) | `7.5.0` | `7.5.1` |
| [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite) | `7.5.0` | `7.5.1` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `7.5.0` | `7.5.1` |


Updates `@storybook/addon-essentials` from 7.5.0 to 7.5.1
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.1/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.1/code/addons/essentials)

Updates `@storybook/addon-links` from 7.5.0 to 7.5.1
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.1/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.1/code/addons/links)

Updates `@storybook/web-components` from 7.5.0 to 7.5.1
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.1/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.1/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 7.5.0 to 7.5.1
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.1/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.1/code/frameworks/web-components-vite)

Updates `storybook` from 7.5.0 to 7.5.1
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.1/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.1/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-20 11:16:16 +02:00
dependabot[bot] 9dbc3777a0
web: bump the wdio group in /tests/wdio with 4 updates (#7241)
Bumps the wdio group in /tests/wdio with 4 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner), [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework) and [@wdio/spec-reporter](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-spec-reporter).


Updates `@wdio/cli` from 8.19.0 to 8.20.1
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.20.1/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.19.0 to 8.20.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.20.0/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.19.0 to 8.20.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.20.0/packages/wdio-mocha-framework)

Updates `@wdio/spec-reporter` from 8.19.0 to 8.20.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.20.0/packages/wdio-spec-reporter)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/spec-reporter"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-20 11:16:01 +02:00
transifex-integration[bot] 8c277033cf
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7236)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-20 11:15:43 +02:00
Ken Sternberg 7e536515c6
web: isolate clipboard handling (#7229)
We would like to use the clipboard for more than just the token copy button.  This commit
enables that by separating the "Write to Clipboard" and "Write to Notifications" routines
into separate functions, putting "writeToClipboard" into the utilities collection, and
clarifying what happens when a custom presses the TokenCopy button.
2023-10-19 16:26:02 -07:00
Jens L 92d170d065
web/flows: update flow background (#7232)
* web/flows: update flow background

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Optimised images with calibre/image-actions

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-19 23:53:27 +02:00
Jens L 41464aec18
web/admin: fix prompt form and codemirror mode (#7231)
* web/admin: fix extra curly brace

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* also fix form rendering

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix codemirror alignment

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use enum for codemirror mode to prevent invalid mode

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-19 23:53:04 +02:00
Jens L 4686796543
web/admin: decrease wizard hint padding (#7227)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-19 17:59:08 +02:00
Roney Dsilva f036820fd8
stages/email: Fix query parameters getting lost in Email links (#5376)
* fix to email confirmation flow

* handled query keyerror

* rewrite using django's QueryDict, add tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix makefile

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove commented out code

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Roney Dsilva <roney.dsilva@cdmx.in>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-19 17:52:27 +02:00
Jens L acad3c4d5c
core/rbac: fix missing field when removing perm, add delete from object page (#7226)
* make object permissions deletable from the object page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix error when removing object permissions form user/role page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* upgrade translation

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-19 14:53:56 +02:00
senare 34367a7481
website/integrations: grafana: add Helm and Terraform config examples (#7121)
* Added helm ref and Terraform Provider config

   Added disclaimer about secret's in Helm or i.e values.yaml

Co-authored-by: risson <18313093+rissson@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: senare <senare@gmail.com>

* fix formatting

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: senare <senare@gmail.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Manfred Nilsson <manfred.nilsson@synkzone.com>
Co-authored-by: risson <18313093+rissson@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-19 12:26:40 +00:00
dependabot[bot] 48e8c568e2
web: bump @types/codemirror from 5.60.11 to 5.60.12 in /web (#7223)
Bumps [@types/codemirror](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/codemirror) from 5.60.11 to 5.60.12.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/codemirror)

---
updated-dependencies:
- dependency-name: "@types/codemirror"
  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>
2023-10-19 12:59:06 +02:00
transifex-integration[bot] 44a0df5cf8
translate: Updates for file web/xliff/en.xlf in zh_CN (#7224)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-19 12:58:41 +02:00
transifex-integration[bot] a72b1f99ab
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7225)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-19 12:58:22 +02:00
Tana M Berry d48342f90b
website/blogs: blog about sso tax (#7202)
* blog on SSO tax

* edits

* Optimised images with calibre/image-actions

* Update website/blog/2023-10-18-taxed-out-of-security/item.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-18 18:13:32 -05:00
Ken Sternberg 3a7283c670
web: Application wizard v2 with tests (#7004)
* A lot of comments about forms.

* Adding comments to the wizard.

* Broke out the text input into a single renderer.  Still works as required.

* web: Legibility in the ApplicationForm.

This is a pretty good result.  By using the LightDOM setting, this
provides the existing Authentik form manager with access to the
ak-form-horizontal-element components without having to do any
cross-border magic.  It's not ideal, and it shows up just how badly
we've got patternfly splattered everywhere, but the actual results
are remarkable.  The patterns for text, switch, radio, textarea,
file, and even select are smaller and easier here.

I'm still noodling on what an unspread search-select element would
look like.  It's just dependency injection, so it ought to be as
straightforward as that.

* web: Marking down the start of the 'components' library.

* web: Baby steps

I become frustrated with my inability to make any progress on this project, so I decided to reach
for a tool that I consider highly reliable but also incredibly time-consuming and boring: test
driven development.

In this case, I wrote a story about how I wanted to see the first page rendered: just put the HTML
tag, completely unadorned, that will handle the first page of the wizard. Then, add an event handler
that will send the updated content to some parent object, since what we really want is to
orchestrate the state of the user's input with a centralized location. Then, rather than fiddling
with the attributes and properties of the various pages, I wanted them to be able to "look up" the
values they want, much as we'd expect a standalone form to be able to pull its values from the
server, so I added a context object that receives the update event and incorporates the new
knowledge about the state of the process into itself.

The result is surprisingly satisfying: the first page renders cleanly, displays the content that we
want, and as we fiddle with, we can *watch in real time* as the results of the context are updated
and retransmitted to all receiving objects. And the sending object gets the results so it
re-renders, but it ends up looking the same as it was before the render.

* Now, it's starting to look like a complete package. The LDAP method is working, but there is a bug:
the radio is sending the wrong value !?!?!?. Track that down, dammit. The search wrappers now resend
their events as standard `input` events, and that actually seems to work well; the browser is
decorating it with the right target, with the right `name` attribute, and since we have good
definitions of the `value` as a string (the real value of any search object is its UUID4), that
works quite well. Added search wrappers for CoreGroup and CryptoCertificate (CertificateKeyPairs),
and the latter has flags for "use the first one if it's the only one" and "allow the display of
keyless certificates."

Not sure why `state()` is blocking the transmission of typing information from the typed element
to the context handler, but it's a bug in the typechecker, and it's not a problem so far.

* Now, it's starting to look like a complete package. The LDAP method is working, but there is a bug:
the radio is sending the wrong value !?!?!?. Track that down, dammit. The search wrappers now resend
their events as standard `input` events, and that actually seems to work well; the browser is
decorating it with the right target, with the right `name` attribute, and since we have good
definitions of the `value` as a string (the real value of any search object is its UUID4), that
works quite well. Added search wrappers for CoreGroup and CryptoCertificate (CertificateKeyPairs),
and the latter has flags for "use the first one if it's the only one" and "allow the display of
keyless certificates."

Not sure why `state()` is blocking the transmission of typing information from the typed element
to the context handler, but it's a bug in the typechecker, and it's not a problem so far.

* web: tracked down that weirld bug with the radio.

Because radio inputs are actually multiples, the events handling for
radio is... wonky.  If we want our `<ak-radio>` component to be a
unitary event dispatcher, saying "This is the element selected," we
needed to do more than what was currently being handled.

I've intercepted the events that we care about and have placed
them into a controller that dictates both the setting and the
re-render of the component.  This makes it "controlled" (to use the
Angular/React/Vue) language and depends on Lit's reactiveElement
lifecycle to work, rather than trust the browser, but the browser's
experience with respect to the `<input type=radio` is pretty bad:
both input elements fire events, one for "losing selection" and
one for "gaining selection".  That can be very confusing to handle,
so we funnel them down in our aggregate radio element to a single
event, "selection changed".

As a quality-of-life measure, I've also set the label to be
unselectable; this means that a click on the label will trigger the
selection event, and a long click will not disable selection or
confuse the selection event generator.

* web: now passing the precommit phase

* web: a HACK for Storybook to inject the "use light theme" flag into the body.

This isn't really a very good hack; what it does is say that every story is
responsible for hacking its theme into the parent.  This is very annoying, but
it does mean that we can at least show our components in the best light.

* web: ak-application-wizard-authentication-by-oauth, and many fixes!

1. Fixed `eventEmitter` so that if the detail object is a scalar, it will not attempt to "objectify"
   it.  This was causing a bug where retrofitting the eventEmitter to some older components resulted
   in a detail of "some" being translated into ['s', 'o', 'm', 'e'].  Not what is wanted.
2. Removed the "transitional form" from the existing components; they had a two-step where the web
   component class was just a wrapper around an independent rendering function.  While this worked,
   it was only to make the case that they *were* independent rendering objects and could be
   supported with the right web component framework.  We're halfway there now; the last step will be
   to transform the horizontal-element and various input CSS into componentized CSS, the way
   Patternfly-Elements is currently doing.
3. Fixed the `help` field so that it could take a string or a TemplateResult, and if the latter,
   don't bother wrapping it in the helper text functionality; just let it be its own thing.  This
   supports the multi-line help of redirectURI as well as the `ak-utils-time-delta` capability.
4. Transform Oauth2ProviderForm to use the new components, to the best of our ability.  Also used
   the `provider = this.wizard.provider` and `provider = this.instance` syntax to make the render
   function *completely portable*; it's the exact same text that is dropped into...
5. The complete `ak-application-wizard-authentication-by-oauth` component. They're so similar part
   of me wonders if I could push them both out to a common reference, or a collection of common
   references.  Both components use the PropertyMapping and Sources, and both use the same
   collection of searches (Crypto, Flow).
6. A Storybook for `ak-application-wizard-authentication-by-oauth`, showing the works working.
7. New mocks for `authorizationFlow`, `propertyMappings`, and `hasJWKs`.

This sequence has revealed a bug in the radio control.  (It's always the radio control.)  If the
default doesn't match the current setting, the radio control doesn't behave as expected; it won't
change when you fully expect that it should.  I'll investigate how to harmonize those tomorrow.

* web: Converted our toggle groups to a more streamlined implementation.

* web: one more toggle group.

* initial api and schema

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* separate blueprint importer from yaml parsing

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* cleanup

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: Replace ad-hoc toggle control with ak-toggle-group

This commit replaces various ad-hoc implementations of the Patternfly Toggle Group HTML with a web
component that encapsulates all of the needed behavior and exposes a single API with a single event
handler, return the value of the option clicked.

The results are: Lots of visual clutter is eliminated.  A single link of:

```
<div class="pf-c-toggle-group__item">
  <button
      class="pf-c-toggle-group__button ${this.mode === ProxyMode.Proxy
          ? "pf-m-selected"
          : ""}"
      type="button"
      @click=${() => {
          this.mode = ProxyMode.Proxy;
      }}>
      <span class="pf-c-toggle-group__text">${msg("Proxy")}</span>
  </button>
</div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div>
```

Now looks like:

```
<option value=${ProxyMode.Proxy}>${msg("Proxy")}</option>
```

This also means that the three pages that used the Patternfly Toggle Group could eliminate all of
their Patternfly PFToggleGroup needs, as well as the `justify-content: center` extension, which also
eliminated the `css` import.

The savings aren't as spectacular as I'd hoped: removed 178 lines, but added 123; total savings 55
lines of code.  I still count this a win: we need never write another toggle component again, and
any bugs, extensions or features we may want to add can be centralized or forked without risking the
whole edifice.

* web: minor code formatting issue.

* add new "must_created" state to blueprints to prevent overwriting objects

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: adding a storybook for the ak-toggle-group component

* Bugs found by CI/CD.

* web: Replace ad-hoc search for CryptoCertificateKeyPairs with ak-crypto-certeficate-search

This commit replaces various ad-hoc implementations of `search-select` for CryptoCertificateKeyPairs
with a web component that encapsulates all of the needed behavior and exposes a single API.

The results are: Lots of visual clutter is eliminated.  A single search of:

```HTML
<ak-search-select
    .fetchObjects=${async (query?: string): Promise<CertificateKeyPair[]> => {
        const args: CryptoCertificatekeypairsListRequest = {
            ordering: "name",
            hasKey: true,
            includeDetails: false,
        };
        if (query !== undefined) {
            args.search = query;
        }
        const certificates = await new CryptoApi(
            DEFAULT_CONFIG,
        ).cryptoCertificatekeypairsList(args);
        return certificates.results;
    }}
    .renderElement=${(item: CertificateKeyPair): string => {
        return item.name;
    }}
    .value=${(item: CertificateKeyPair | undefined): string | undefined => {
        return item?.pk;
    }}
    .selected=${(item: CertificateKeyPair): boolean => {
        return this.instance?.tlsVerification === item.pk;
    }}
    ?blankable=${true}
>
</ak-search-select>
```

Now looks like:

```HTML
<ak-crypto-certificate-search certificate=${this.instance?.tlsVerification}>
</ak-crypto-certificate-search>
```

There are three searches that do not require there to be a valid key with the certificate; these are
supported with the boolean property `nokey`; likewise, there is one search (in SAMLProviderForm)
that states that if there is no current certificate in the SAMLProvider and only one certificate can
be found in the Authentik database, use that one; this is supported with the boolean property
`singleton`.

These changes replace 382 lines of object-oriented invocations with 36 lines of declarative
configuration, and 98 lines for the class.  Overall, the code for "find a crypto certificate" has
been reduced by 46%.

Suggestions for a better word than `singleton` are welcome!

* web: display tests for CryptoCertificateKeypair search

This adds a Storybook for the CryptoCertificateKeypair search, including
a mock fetch of the data.  In the course of running the tests, we discovered
that including the SearchSelect _class_ won't include the customElement declaration
unless you include the whole file!  Other bugs found: including the CSS from
Storybook is different from that of LitElement native, so much so that the
adapter needed to be included.  FlowSearch had a similar bug.  The problem
only manifests when building via Webpack (which Storybook uses) and not
Rollup, but we should support both in distribution.

* Fixed behavioral problem with the radio; the `if` there was
preventing the radio from reflecting the default correctly.
The observed behavior was that the radio wouldn't "activate"
until the item selected during the render pass was clicked on
first.

* Proxy Provider done.

* web: Tactical change.  Put all the variants on the second page; it's
a longer list, but it's also easier to manage than all those
required sub-options.

* Rounding out the catalog.

* web: SAML Manual Configuration

Added a 'design document' that just kinda describes what I'm trying
to do, in case I don't get this done by Friday Aug 11, 2023.

I had two tables doing the same thing, so I merged them and then
wrote a few map/filters to specialize them for those two use cases.

Along the way I had to fiddle with the ESLint settings so that
underscore-prefixed unused variables would be ignored.

I cleaned up the visual appeal of the forms in the LDAP application.

I was copy/pasting the "handleProviderEvent" function, so I pulled
it out into ApplicationWizardProviderPageBase.  Not so much a matter
of abstraction as just disliking that kind of duplication; it served
no purpose.

* Added SAML Story to Storybook.

* Web: This is coming together amazingly well.  Like, almost too well.

* web: 80% of the way there

This commit includes the first three pages of the wizard, the
completion of the wizard framework with evented handling, and control
over progression.

Some shortcomings of this design have become evident: it isn't
possible to communicate between the steps' wrappers, as they are
POJOs without access to the context.  An imperative decision-making
process has to be inserted in the orchestration layer,
which is kinda annoying.

But it looks good and it behaves correctly, to the extent that I've
given it behavior.  It's an excellent foundation.

* Linting.

* web: application wizard

Found where the hook for form validity should go.  Excellent!  Now I just need to incorporate
that basic validation into the business logic and we're good to go.

* Turns out that was one layer too many; the topmost component was fine for
maintaining the context.

* It looks like my brilliant strategy has hit a snag.

The idea is simple.  Let's start with this picture:

```
<application-wizard .steps=${[... a collection of step objects ...]}>
  <wizard-main .steps=${(steps from above)}>
    <application-current-panel>
      <current-form>
```

- ApplicationWizard has a Context for the ApplicationProviderPair (or whatever it's going to be).
  This context does not know about the steps; it just knows about: the "application" object, the
  "provider" object, and a discriminator to know *which* provider the user has selected.
- ApplicationWizard has Steps that, among other things, provides Panels for:
  - Application
  - Pick Provider
  - Configure Provider
  - Submit ApplicationProviderPair to the back-end
- The WizardFrame renders the CurrentPanel for the CurrentStep

The CurrentPanel gets its data from the ApplicationWizard in the form of a Context. It then sends
messages (events) to ApplicationWizard about the contents of each field as the user is filling out
the form, so that the ApplicationWizard can record those in the ApplicationProviderPair for later
submission.

When a CurrentForm is valid, the ApplicationWizard updates the Steps object to show that the "Next
button" on the Wizard is now available.

In this way, the user can progress through the system.  When they get to the last page, we can
provide in the ApplicationWizard with the means to submit the form and/or send the user back to
the page with the validation failure.

Problem: The context is being updated in real-time, which is triggering re-renders of the form. This
leads to focus problems as the fields that are not yet valid are triggering "focus grab" behavior.
This is a classic problem with "controlled" inputs. What we really want is for the CurrentPanel to
not re-render at all, but to behave like a normal, uncontrolled form, and let the browser do most of
the work.  We still want the [Next] button to enable when the form is valid enough to permit that.

---

Other details: I've ripped out a lot of Jen's work, which is probably a mistake.  It's still
preserved elsewhere.  I've also cleaned up the various wizardly things to try and look organized.
It *looks* like it should work, it just... doesn't.  Not yet.

* Late addition: I had an inspiration about how to reduce the way
reactivity broke focus by, basically, removing the reactivity and
managing the first-time-through lifecycle to prevent the update
from causing refocus.  It works well!  Now I just need to test it.

* This application fixes the bug with respect to the wizard-level context being updated incorrectly.

Understandings:

- To use uncontrolled inputs, which I prefer, the context object should not be a state or property
  at the level of consumers; it should not automatically re-render with every keystroke, i.e. "The
  React Way."  We're using Web Components, [client-side
  validation](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation) exists on the
  platform already, and live-validation is problematic for any number of reasons.
- The trade-off is that it is now necessary to re-render the target page of the wizard de-novo, but
  that's not really as big a deal as it sounds. Lit is ready to do that... and then nothing else
  until we request a change-of-page. Excellent.
- The top level context *must* be a state, but it's better if it's a state never actually used by
  the top-level context container. The debate about whether or not to make that container a dumb one
  (`<slot></slot>`) or to merge it with the top-level object continues; here, I've merged it with
  the top-level wizard object, but that object does not refer to the state variable being managed in
  its render pass, so changes to it do not cause a re-render of the whole wizard. The purpose of the
  top-level page is to manage the *steps*, not the *content of any step*. A step may change
  dynamically based on the content of a step, but that's the same thing as *which step*. Lesson:
  always know what your state is *about*.
- Deep merging is a complex subject, but here it's appropriate to our needs.

* web: Application Wizard

This commit combines a working (but very unpolished) version of the Application Wizard with Jen's
code for the CoreTransactionApplicationRequest, resulting in a successful round trip.

It fixes a number of bugs with the way ContextProducer decorators were being processed, such that
they just weren't working with our current configuration (although they did work fine in Storybook);
consumers didn't need to be fixed.

It also *removes* the steps-aware context from the Wizard.

That *may* be a mistake.  To re-iterate, the `WizardFrame` provides the chrome for a Wizard: the
button bar div, the breadcrumbs div, the header div, and it takes the steps object as its source of
truth for all of the content.  The `WizardContent` part of the application has two parts: The
`WizardMain`, which wraps the frame and supplies the context for all the `WizardPanels`, and the
`WizardPanels` themselves, which are dependent on a context from `WizardMain` for the data that
populates each panel. YAGNI right now that the panels need to know anything about the steps, and the
`WizardMain` can just pass a fresh `.steps` object to the `WizardFrame` when they need updating.
Using props drilling may make more sense here.

It certainy does *not* make sense for the panels.  They need to be renderable on-demand, and they
need to make sense of what they're rendering on-demand, so the function is

```
(panel code) => (context) => (rendered panel)
```

(Yes, that's curried notation. Deal.)

* This commit includes the first WDIO test for the ApplicationWizard.  It doesn't do much right now, but
it does log in and navigate to the wizard successfully.

* web: completed test for single application, provided new programming language to make it easier to write tests.

* Almost there.

Missing: The validation is currently not working as expected, and I cannot get the backend
to give me meaningful data helping us "go back" to the field that wasn't valid.  I really
don't want to put all the meaningful validation on the front-end; that's the road to -
perdition, the back-end must be usable by people less assiduous than we are.

Also: Need to make the button bar work better; maybe each panel can provide a custom button
bar if one is needed?

* web: Test harness

We have an end-to-end test harness that includes a trivially correct DSL for "This is what a user would do, do this":

```
const deleteProvider = (theSlug) => ([
    ["button", '>>>ak-sidebar-item a[href="#/core/providers"]'],
    ["deletebox", `>>>a[href="#/core/applications/${theSlug}"]`],
    ["button", '>>>ak-forms-delete-bulk button[slot="trigger"]'],
    ["button", '>>>ak-forms-delete-bulk div[role="dialog"] ak-spinner-button'],
]);
```

It's now possible to target individual sequences of events this way.  With a little creativity, we could have standalone functions that take parameters for our calls and just do them, without too much struggle.

* web: Revised navigation

After working with the navigation for awhile, I realized that it's a poor map; what I really wanted was
a controller/view pair, where events flow up to the controller and then messages on "what to draw" flow
down to the view.  It work quite well, and the wizard frame is smaller and smarter for it.

I've also moved the WDIO-driven tests into the 'tests' folder, because it (a) makes more sense to put
them there, and (b) it prevents any confusion about who's in charge of node_modules.

* web: Simplify, simplify, simplify

Sort-of.

This commit changes the way the "wizard step coordinator" layer works, giving the
wizard writer much more power over button bar.  It still assumes there are only
three actions the wizard frame wants to commit: next, back, and close.  This empowers
the steps themselves to re-arrange their buttons and describe the rules through which
transitions occur.

* web: resetting the form is not working yet...

I vehemently dislike the object-oriented "reset" command; every wizard should start with
an absolutely fresh copy of the data upon entry.  Refactoring the wizard to re-build its
content from the inside is the correct way to go, but I don't have a good mental image
of how to make the ModalButton and the component it invokes interact cleanly, which
frustrates the hell out of me.

* web: reset

As I said, I greatly dislike having to be dependent upon "resets"; I prefer my
data to be de novo going into a "new" transaction.  That said, we work with
what we've got; I've created an event generated by the wizard that says the
modal just closed; anything wrapping and implementing the wizard can then
capture that event and reset the data.  I've also added a pair of functions
that create the two states (what step, what form data) anew, so that resetting
is as trivial as initializing (and is exactly the same, code-wise).

* web: Without error handling, this is complete, but I still need @BeryJu (Jens)
for help with the SAML Upload (it doesn't appear to be correctly handled?) and
the error handling.

* web: revise tests for wizard

This commit replaces the previous WDIO instance with a more formal and straightforward process using
the [pageobjects](https://martinfowler.com/bliki/PageObject.html).  In this form, every major
component has its own test suite, and a test is a sequence of exercises of those components.

A test then becomes something as straightforward as:

```
        await LoginPage.open();
        await LoginPage.login("ken@goauthentik.io", "eat10bugs");

        expect(await UserLibraryPage.pageHeader).toHaveText("My Applications");
        await UserLibraryPage.goToAdmin();

        expect(await AdminOverviewPage.pageHeader).toHaveText("Welcome, ");
        await AdminOverviewPage.openApplicationsListPage();

        expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
        ApplicationsListPage.startCreateApplicationWizard();

        await ApplicationWizard.app.name.setValue(`Test application ${newId}`);
        await ApplicationWizard.nextButton.click();
        await (await ApplicationWizard.getProviderType("ldapprovider")).click();
        await ApplicationWizard.nextButton.click();
        await ApplicationWizard.ldap.setBindFlow("default-authentication-flow");
        await ApplicationWizard.nextButton.click();
        await expect(await ApplicationWizard.commitMessage).toHaveText(
            "Your application has been saved"
        );
```

Whether or not there's another layer of DSL in there or not, this is a pretty nice idiom for
maintaining tests.

* web: updating with forms and fixes for eslint complaints.

* web/add webdriverIO testing layer

This commit adds WebdriverIO as an end-to-end solution to unit testing.  WebdriverIO can be run both
locally and remotely, supports strong integration with web components, and is generally robust for
use in pipelines.  I'll confess to working through a tutorial on how to do this for web components,
and this is just chapter 2 (I think there are 5 or so chapters...).

There's a makefile, with help!  If you just run `make` it tells you:

```
Specify a command. The choices are:

  help                 Show this help
  node_modules         Runs `npm install` to prepare this feature
  precommit            Run the precommit: spell check all comments, eslint with sonarJS, prettier-write
  test-good-login      Test that we can log into the server. Requires a running instance of the server.
  test-bad-login       Test that bad usernames and passwords create appropriate error messages
```

... because Makefiles are documentation, and documentation belongs in Makefiles.

I've chosen to go with a PageObject-oriented low-level DSL; what that means is that for each major
components (a page, a form, a wizard), there's a class that provides human-readable names for
human-interactable and human-viewable objects on the page.  The LoginPage object, for example, has
selectors for the username, password, submit button, and the failure alert; accessing those allows
us to test for items as expected., and to write a DSL for "a good login" that's as straightforward
as:

```
        await LoginPage.open();
        await LoginPage.login("ken@goauthentik.io", "eat10bugs");
        await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
```

There was a *lot* of messing around with the LoginPage to get the username and password into the
system.  For example, I had to do this with all the `waitForClickable` and `waitForEnable` because
we both keep the buttons inaccessible until the form has something and we "black out" the page (put
a darkening filter over it) while accessing the flow, meaning there was a race condition such that
the test would attempt to interact with the username or password field before it was accessible.
But this works now, which is very nice.

``` JavaScript
    get inputUsername() {
        return $('>>>input[name="uidField"]');
    }

    get btnSubmit() {
        return $('>>>button[type="submit"]');
    }

    async username(username: string) {
        await this.inputUsername.waitForClickable();
        await this.inputUsername.setValue(username);
        await this.btnSubmit.waitForEnabled();
        await this.btnSubmit.click();
    }
```

The bells & whistles of *Prettier*, *Eslint*, and *Codespell* have also been enabled. I do like my
guardrails.

* web/adding tests: added comments and cleaned up some administrative features.

* web/test: changed the name of one test to reflect it's 'good' status

* core/allow alternative postgres credentials

This commit allows the `dev-reset` command in the Makefile to pick up and use credentials from the
`.env` file if they are present, or fallback to the defaults provided if they are not. This is the
only place in the Makefile where the database credentials are used directly against postgresql
binaries. The syntax was tested with bash, zsh, and csh, and did not fail under those.

The `$${:-}` syntax is a combination of a Makefile idiom for "Pass a single `$` to the environment
where this command will be executed," and the shell expresion `${VARIABLE:-default}` means
"dereference the environment variable; if it is undefined, used the default value provided."

* Re-arrange sequence to avoid recursive make.

Nothing wrong with recursive make; it just wasn't essential
here.  `migrate` is just a build target, not a task.

* Cleanup according to the Usage:
  checkmake [options] <makefile>...
  checkmake -h | --help
  checkmake --version
  checkmake --list-rules Makefile linting tool.

* core: added 'help' to the Makefile

* get postgres config from authentik config loader

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* don't set -x by default

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* sort help

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update help strings

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: test LDAP wizard sequence

* web: improve testing by adding test admin user via blueprint

* This commit continues the application wizard buildout.  In this commit are the following changes:

- Added SCIM to the list of available providers
- Fixed ForwardProxy so that its mode is set correctly.  (This is a special case in the committer;
  I'm unhappy with that.)
- Fixed the commit messages so that:
  - icons are set correctly (Success, Danger, Working)
  - icons are colored correctly according to state
  - commit message includes a `data-commit-state` field so tests can find it!
- Merged the application wizard tests into a single test pass
- Isolated common parts of the application wizard tests to reduce unnecessary repetition.  All
  application tests are the same until you reach the provider section anyway.
- Fixed the unit tests so they're finding the right error messages and are enabled to display them
  correctly.
- Moved the test Form handlers into their own folder so they're not cluttering up the Pages folder.

* web: add radius to application wizard

This commit continues the application wizard buildout.  In this commit are the following changes:

- Fixed a width-setting bug in the Makefile `make help` feature (i.e "automate that stuff!")
- Added Radius to the list of providers we can offer via the wizard
- Added `launchUrl` and `UI Settings` to features of the application page the wizard can find
- Changed 'SAML Manual Configuration' to just say "SAML Configuration"
- Modified `ak-form-group` to take and honor the `aria-label` property (which in turn makes it
  easier to target specific forms with unit testing)
- Reduced the log level for wdio to 'warn'; 'info' was super-spammy and not helpful.  It can be put
  back with `--logLevel info` from the command line.

* fix blueprints

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update package name

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add dependabot

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* prettier run

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add basic CI

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove hooks

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: application wizard refactor & completion

This commit refactors the various components of the Wizard and ApplicationWizard, creating a much
more maintainable and satisfying Wizard experience for both developers (i.e, *me* and *Jens* so
far), and for the customer.

The Wizard base has been refactored into three components:

**AkWizardController**

The `AkWizardController` provides the event listenters for the wizard; it hooks them up, recevies the
events, and forwards them to the wizard.  It unwraps the event objects and forwards the relevant
messages contained in the events.  It knows of three event categories:

- Navigation requests (move to a different step)
- Update requests (the current step has updated the business content)
- Close requests (close or cancel the wizard).

**ak-wizard-frame**

The `ak-wizard-frame` is the ModalButton interface.  It provides the Header, Breadcrumbs (nee`
"navigation block"), Buttons, and a DIV into which the main content is rendered.

**AkWizard**

`AkWizard` is an *incomplete* implementation of the wizard. It's meant to be inherited by a child
class, which will implement the rest. It extends `AKElement`. It provides the basic content needed,
such as steps, currentStep (as an index), an accessor for the step itself, an accessor for the
frame, and the interface to the `AkWizardController`.

**ApplicationWizard**

The `ApplicationWizard` itself has been refactored to accommodate these changes. It inherits from
`AkWizard` and provides the business logic for what to do when a form updates, some custom logic for
preventing moving through the wizard when the forms are incomplete, and a persistence layer for
filling out different providers in the same session. It's simplified a *lot*.

The types specified for `AkWizard` are pretty nifty, I think. I could wish the types being passed
via the custom events were more robust, but [strongly typed custom
events](https://github.com/lit/lit-element/issues/808) turn out to be quite the pain in the, er,
neck. As it is, the `precommit` pass did very good at preventing the worst disasters.

The steps themselves were re-written as objects so that they could take advantage of their `valid`
and `disabled` states and provide more meaningful buttons and labels. I think it's a solid
compromise, and it moved a lot of display logic out of the core `handleUpdate()` business method.

The tests, such as they are, are passing.

* Added comment describing new test.

* web: ensuring copy from `main` is canon

* web: fixes after merge

* web: laying the groundwork for future expansion

This commit is a hodge-podge of updates and changes to the web.  Functional changes:

- Makefile: Fixed a bug in the `help` section that prevented the WIDTH from being accurately
  calculated if `help` was included rather than in-lined.

- ESLint: Modified the "unused vars" rule so that variables starting with an underline are not
  considered by the rule.  This allows for elided variables in event handlers.  It's not a perfect
  solution-- a better one would be to use Typescript's function-specialization typing, but there are
  too many places where we elide or ignore some variables in a function's usage that switching over
  to specialization would be a huge lift.

- locale: It turns out, lit-locale does its own context management.  We don't need to have a context
  at all in this space, and that's one less listener we need to attach t othe DOM.

- ModalButton: A small thing, but using `nothing` instead of "html``" allows lit better control over
  rendering and reduces the number of actual renders of the page.

- FormGroup: Provided a means to modify the aria-label, rather than stick with the just the word
  "Details."  Specializing this field will both help users of screen readers in the future, and will
  allow test suites to find specific form groups now.

- RadioButton: provide a more consistent interface to the RadioButton.  First, we dispatch the
  events to the outside world, and we set the value locally so that the current `Form.ts` continues
  to behave as expected.  We also prevent the "button lost value" event from propagating; this
  presents a unified select-like interface to users of the RadioButtonGroup.  The current value
  semantics are preserved; other clients of the RadioButton do not see a change in behavior.

- EventEmitter: If the custom event detail is *not* an object, do not use the object-like semantics
  for forwarding it; just send it as-is.

- Comments: In the course of laying the groundwork for the application wizard, I throw a LOT of
  comments into the code, describing APIs, interfaces, class and function signatures, to better
  document the behavior inside and as signposts for future work.

* web: permit arrays to be sent in custom events without interpolation.

* actually use assignValue or rather serializeFieldRecursive

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: eslint & prettier fixes, plus small aesthetic differences.

* Restoring this file.  Not sure where it disappears to.

* fix label in dark mode

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* SCIM Manuel -> SCIM

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix lint errors

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: better converter configuration, CSS repair, and forward-domain-proxy

1. Forward Domain Proxy.  I wasn't sure if this method was appropriate for the wizard,
   but Jens says it is.  I've added it.

2. In the process of doing so, I decided that the Provider.converter field was overly
   complexified; I tried too hard to reduce the number of functions I needed to define,
   but in the process outsourced some of the logic of converting the Wizard's dataset
   into a property typed request to the `commit` phase, which was inappropriate.  All
   of the logic about a provider, aside from its display, should be here with the code
   that distinguishes between providers.  This commit makes it so.

3. Small CSS fix: the fields inherited from the Proxy provider forms had some unexpected
   CSS which was causing a bit of a weird indent.  That has been rectified.

* web: running pre-commit after merge.

* web: ensure the applications wizard tests finish after current changes

* prettier has opinions.

* web: application wizard spit & polish

The "ApplicationWizardHint" now correctly uses the localstorage and allows the user to navigate back
and see the message after it's been hidden, so that it will always be available during the test
phase.

The ApplicationList's old "Create Application Form" button has been restored for the purposes of the
test phase.

The ApplicationWizard is now available on both the ApplicationList and ProviderList pages.

Tana and I discussed the microcopy, putting a stronger second-person "You can do..." twist onto the
language, to give the user the sense of empowerment.

The ShowHintController now has both "hide" and "show" operations, to support the hint restoration.

* web: updated storybook stories for the wizard, illustration how "a simple wizard" is configured in source code and tested with storybook.

* web: I hate getting spanked by prettier.

* web: sometimes I wish I had lower standards

Anyway, this was a very stupid bug, because by definition function
definition arguments don't have uses, they're being defined, not
implemented.  Fixed, conf fixed to compensate, and consequences
conquered.

* move context from labs to main

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Revert "move context from labs to main"

This reverts commit 3718ee6904.

* web: reify the data loop

I was very unhappy with the "update this dot-path" mechanism I was using earlier; it was hard
for me to read and understand what was happening, and I wrote the darned thing.  I decided instead
to go with a hard substitution model; each phase of the wizard is responsible for updating the
*entire* payload, mostly by creating a new payload and substituting the field value associated
with the event.

On the receiver, we have to do that *again* to handle the swapping of providers when the user
chooses one and then another.  It looks clunky, and it is, but it's *legible*; a junior dev
could understand what it's doing, and that's the goal.

* Revert "web: reify the data loop"

This reverts commit 09fedcacf0.

* web: revert the 'lit' to 'lit-labs' for task and context.

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 12:43:37 -07:00
authentik-automation[bot] 3beb421e50
web: bump API Client version (#7220)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-18 18:02:44 +00:00
dependabot[bot] d0fca8272c
core: bump goauthentik.io/api/v3 from 3.2023083.7 to 3.2023083.8 (#7221)
* core: bump goauthentik.io/api/v3 from 3.2023083.7 to 3.2023083.8

Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.7 to 3.2023083.8.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.7...v3.2023083.8)

---
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>

* bump even harder

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 20:01:35 +02:00
Jens L 8aafa06259
providers/radius: TOTP MFA support (#7217)
* move CheckPasswordMFA to flow executor

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add mfa support field to radius

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 19:43:36 +02:00
authentik-automation[bot] 3c734da86a
web: bump API Client version (#7218)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-18 15:32:21 +00:00
Samir Musali a60f3b4b81
stage/deny: add custom message (#7144)
* stage/deny: add message

* add migration, tests and schema update

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add form

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 17:13:33 +02:00
Samir Musali 4262bd6ace
docs: update full-dev-setup docs (#7205) 2023-10-18 15:11:47 +00:00
Jens L 6ba4f4df46
enterprise: bump license usage task frequency (#7215)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 14:57:35 +02:00
dependabot[bot] 35147230d7
web: bump the storybook group in /web with 5 updates (#7212)
Bumps the storybook group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `7.4.6` | `7.5.0` |
| [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `7.4.6` | `7.5.0` |
| [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) | `7.4.6` | `7.5.0` |
| [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite) | `7.4.6` | `7.5.0` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `7.4.6` | `7.5.0` |


Updates `@storybook/addon-essentials` from 7.4.6 to 7.5.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.0/code/addons/essentials)

Updates `@storybook/addon-links` from 7.4.6 to 7.5.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.0/code/addons/links)

Updates `@storybook/web-components` from 7.4.6 to 7.5.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.0/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 7.4.6 to 7.5.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.0/code/frameworks/web-components-vite)

Updates `storybook` from 7.4.6 to 7.5.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.0/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: storybook
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-18 12:38:07 +02:00
dependabot[bot] e649c2f6fc
web: bump the sentry group in /web with 2 updates (#7211)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.74.0 to 7.74.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.74.0...7.74.1)

Updates `@sentry/tracing` from 7.74.0 to 7.74.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.74.0...7.74.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-18 12:37:53 +02:00
Jens Langhammer c7182bf513
Revert "web: Updates to the Context and Tasks libraries from lit. (#7168)"
This reverts commit 15be83c06c.
2023-10-18 11:22:00 +02:00
dependabot[bot] 4a8087311f
web: bump @types/codemirror from 5.60.10 to 5.60.11 in /web (#7209)
Bumps [@types/codemirror](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/codemirror) from 5.60.10 to 5.60.11.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/codemirror)

---
updated-dependencies:
- dependency-name: "@types/codemirror"
  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>
2023-10-18 11:10:04 +02:00
dependabot[bot] 29ab22b9f9
web: bump @types/chart.js from 2.9.38 to 2.9.39 in /web (#7206)
Bumps [@types/chart.js](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/chart.js) from 2.9.38 to 2.9.39.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/chart.js)

---
updated-dependencies:
- dependency-name: "@types/chart.js"
  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>
2023-10-18 11:05:07 +02:00
dependabot[bot] 5bce00862a
web: bump pyright from 1.1.331 to 1.1.332 in /web (#7208)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.331 to 1.1.332.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.332/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  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>
2023-10-18 11:04:53 +02:00
dependabot[bot] cd81e4bf70
web: bump @types/grecaptcha from 3.0.5 to 3.0.6 in /web (#7207)
Bumps [@types/grecaptcha](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/grecaptcha) from 3.0.5 to 3.0.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/grecaptcha)

---
updated-dependencies:
- dependency-name: "@types/grecaptcha"
  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>
2023-10-18 11:04:42 +02:00
Tana M Berry cb915bc86c
website/docs: added Note in Beta docs (#7203)
typo, shockingly

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-10-17 21:41:41 +00:00
dependabot[bot] b5dd681f12
web: bump the wdio group in /tests/wdio with 4 updates (#7199)
Bumps the wdio group in /tests/wdio with 4 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner), [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework) and [@wdio/spec-reporter](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-spec-reporter).


Updates `@wdio/cli` from 8.18.2 to 8.19.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.19.0/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.18.2 to 8.19.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.19.0/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.18.2 to 8.19.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.19.0/packages/wdio-mocha-framework)

Updates `@wdio/spec-reporter` from 8.18.1 to 8.19.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.19.0/packages/wdio-spec-reporter)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/spec-reporter"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 22:01:25 +02:00
dependabot[bot] 10beb4c144
core: bump black from 23.9.1 to 23.10.0 (#7200)
Bumps [black](https://github.com/psf/black) from 23.9.1 to 23.10.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.9.1...23.10.0)

---
updated-dependencies:
- dependency-name: black
  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>
2023-10-17 22:01:10 +02:00
dependabot[bot] b18896adf9
core: bump urllib3 from 2.0.6 to 2.0.7 (#7201)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.0.6...2.0.7)

---
updated-dependencies:
- dependency-name: urllib3
  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>
2023-10-17 22:00:04 +02:00
Ken Sternberg 15be83c06c
web: Updates to the Context and Tasks libraries from lit. (#7168)
* Updates to the Context and Tasks libraries from lit.

* web: fix for bad merge

* Still trying to solve that f*&!ing merge bug.

* fix build

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Updates to the Context and Tasks libraries from lit.

* web: fix for bad merge

* Still trying to solve that f*&!ing merge bug.

* fix build

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-17 21:35:11 +02:00
transifex-integration[bot] 04f7710cd6
translate: Updates for file web/xliff/en.xlf in zh_CN (#7197)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-17 21:34:43 +02:00
Marc 'risson' Schmitt 914e0d2b01 ci: test with postgres 16
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-10-17 18:21:02 +02:00
transifex-integration[bot] 3db897d64b
translate: Updates for file web/xliff/en.xlf in fr (#7189)
* Translate web/xliff/en.xlf in fr

100% translated source file: 'web/xliff/en.xlf'
on 'fr'.

* Translate web/xliff/en.xlf in fr

100% translated source file: 'web/xliff/en.xlf'
on 'fr'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-17 16:53:32 +02:00
dependabot[bot] 5b9a16826e
web: bump the esbuild group in /web with 2 updates (#7195)
Bumps the esbuild group in /web with 2 updates: [@esbuild/darwin-arm64](https://github.com/evanw/esbuild) and [@esbuild/linux-arm64](https://github.com/evanw/esbuild).


Updates `@esbuild/darwin-arm64` from 0.19.4 to 0.19.5
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.19.4...v0.19.5)

Updates `@esbuild/linux-arm64` from 0.19.4 to 0.19.5
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.19.4...v0.19.5)

---
updated-dependencies:
- dependency-name: "@esbuild/darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 12:45:25 +02:00
dependabot[bot] b5f986c7d0
web: bump the eslint group in /tests/wdio with 2 updates (#7192)
Bumps the eslint group in /tests/wdio with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.7.5 to 6.8.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/v6.8.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.7.5 to 6.8.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/v6.8.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 12:15:20 +02:00
dependabot[bot] 1cd5ced2ab
core: bump ruff from 0.0.292 to 0.1.0 (#7194)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.292 to 0.1.0.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.292...v0.1.0)

---
updated-dependencies:
- dependency-name: ruff
  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>
2023-10-17 12:15:10 +02:00
dependabot[bot] 514f466687
web: bump the eslint group in /web with 2 updates (#7193)
Bumps the eslint group in /web with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.7.5 to 6.8.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/v6.8.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.7.5 to 6.8.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/v6.8.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 12:14:58 +02:00
Ken Sternberg 9e568e1e85
web: the return of pseudolocalization (#7190)
* web: the return of pseudolocalization

The move to lit-locale lost the ability to automagically pseudolocalize the UI, a useful
utility for checking that additions to the UI have been properly cataloged as
translation targets.  This short script (barely 40 lines) digs deep into the lit-localize
toolkit and produces a pretranslated translation bundle in the target format folder.

* Linted, prettied, and commented.
2023-10-16 13:54:43 -07:00
Jens L 0697e3d5a4
rbac: revisions (#7188)
* improve system migration logging

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix filter for internal service accounts

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* merge migration

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* bump go api

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* sources/ldap: check if we need to connect to ldap before connecting

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-16 19:42:19 +02:00
dependabot[bot] 6deb231e0e
website: bump @babel/traverse from 7.21.4 to 7.23.2 in /website (#7187)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.21.4 to 7.23.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.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 18:07:17 +02:00
authentik-automation[bot] 3cda19f61b
web: bump API Client version (#7186)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-16 15:48:41 +00:00
Jens L e28babb0b8
core: Initial RBAC (#6806)
* rename consent permission

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* the user version

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

t

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* initial role

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start form

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* some minor table refactoring

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix user, add assign

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add roles ui

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix backend

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add assign API for roles

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start adding toggle buttons

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start view page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* exclude add_ permission for per-object perms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* small cleanup

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add permission list for roles

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make sidebar update

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix page header not re-rendering?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fixup

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add search

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* show first category in table groupBy except when its empty

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make model and object PK optional but required together

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* allow for setting global perms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* exclude non-authentik permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* exclude models which aren't allowed (base models etc)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* ensure all models have verbose_name set, exclude some more internal objects

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* lint fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix role perm assign

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add unasign for global perms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add meta changes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* clear modal state after submit

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add roles to our group

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix duplicate url names

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make recursive group query more usable

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add name field to role itself and move group creation to signal

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start sync

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* move rbac stuff to separate django app

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix lint and such

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix go

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start API changes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add more API tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make admin interface not require superuser for now, improve error handling

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* replace some IsAdminUser where applicable

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* migrate flow inspector perms to actual permission

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix license not being a serializermodel

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add permission modal to models without view page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add additional permissions to assign/unassign permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add action to unassign user permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add permissions tab to remaining view pages

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix flow inspector permission check

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix codecov config?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add more API tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* ensure viewsets have an order set

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* hopefully the last api name change

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make perm modal less confusing

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start user view permission page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* only make delete bulk form expandable if usedBy is set

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* expand permission tables

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add more things

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add user global permission table

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix tests' url names

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add tests for assign perms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add unassign tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* rebuild permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* prevent assigning/unassigning permissions to internal service accounts

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* only enable default api browser in debug

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix role object permissions showing duplicate

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix role link on role object permissions table

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix object permission modal having duplicate close buttons

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* return error if user has no global perm and no object perms

also improve error display on table

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* small optimisation

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* optimise even more

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update locale

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add system permission for non-object permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* allow access to admin interface based on perm

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* clean

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* don't exclude base models

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-16 17:31:50 +02:00
Jens L dce913496e
lifecycle: re-fix system migrations (#7185)
fix system migrations?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-16 17:28:53 +02:00
Jens L 25d4905d6c
outposts: use channel groups instead of saving channel names (#7183)
* outposts: use channel groups instead of saving channel names

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use pubsub

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* support storing other args with state

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-16 17:01:44 +02:00
Alissa Gerhard 00b2a773b4
sources/ldap: made ldap_sync_single calls from ldap_sync_all asynchronous (#6862) 2023-10-16 13:11:34 +02:00
Oleh Vivtash 07b8c5bc7a
website/docs: fix API OAuth token usage (#7159)
Update api.md

JWT Token howto update

Signed-off-by: Oleh Vivtash <oleh@vivtash.net>
2023-10-16 13:10:21 +02:00
dependabot[bot] 3c3f1678e5
web: bump rollup from 4.1.3 to 4.1.4 in /web (#7181)
Bumps [rollup](https://github.com/rollup/rollup) from 4.1.3 to 4.1.4.
- [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/v4.1.3...v4.1.4)

---
updated-dependencies:
- dependency-name: rollup
  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>
2023-10-16 12:34:19 +02:00
dependabot[bot] 5eb1c4e4bf
web: bump @formatjs/intl-listformat from 7.4.2 to 7.5.0 in /web (#7182)
Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 7.4.2 to 7.5.0.
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@7.4.2...@formatjs/intl-listformat@7.5.0)

---
updated-dependencies:
- dependency-name: "@formatjs/intl-listformat"
  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>
2023-10-16 12:33:45 +02:00
dependabot[bot] 1ffb76501e
web: bump @rollup/plugin-replace from 5.0.3 to 5.0.4 in /web (#7177)
Bumps [@rollup/plugin-replace](https://github.com/rollup/plugins/tree/HEAD/packages/replace) from 5.0.3 to 5.0.4.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/replace/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/babel-v5.0.4/packages/replace)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-replace"
  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>
2023-10-16 12:33:26 +02:00
dependabot[bot] c0f7a75d5c
web: bump the sentry group in /web with 2 updates (#7175)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.73.0 to 7.74.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.73.0...7.74.0)

Updates `@sentry/tracing` from 7.73.0 to 7.74.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.73.0...7.74.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 11:34:09 +02:00
dependabot[bot] ef7e4a8b57
web: bump @rollup/plugin-commonjs from 25.0.5 to 25.0.7 in /web (#7178)
Bumps [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/HEAD/packages/commonjs) from 25.0.5 to 25.0.7.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/commonjs/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/commonjs-v25.0.7/packages/commonjs)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-commonjs"
  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>
2023-10-16 11:33:45 +02:00
dependabot[bot] cf977950fd
web: bump yaml from 2.3.2 to 2.3.3 in /web (#7176)
Bumps [yaml](https://github.com/eemeli/yaml) from 2.3.2 to 2.3.3.
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](https://github.com/eemeli/yaml/compare/v2.3.2...v2.3.3)

---
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>
2023-10-16 11:32:57 +02:00
dependabot[bot] 84e0f7bc2d
web: bump rollup from 4.0.2 to 4.1.3 in /web (#7179)
Bumps [rollup](https://github.com/rollup/rollup) from 4.0.2 to 4.1.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/v4.0.2...v4.1.3)

---
updated-dependencies:
- dependency-name: rollup
  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>
2023-10-16 11:32:18 +02:00
dependabot[bot] 4a8e71e2c6
web: bump the wdio group in /tests/wdio with 3 updates (#7180)
Bumps the wdio group in /tests/wdio with 3 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner) and [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework).


Updates `@wdio/cli` from 8.18.0 to 8.18.2
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.18.2/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.18.0 to 8.18.2
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.18.2/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.18.0 to 8.18.2
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.18.2/packages/wdio-mocha-framework)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 11:31:50 +02:00
Jens L 41bb1ca707
providers/scim: remove preview (#7166)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-13 19:03:13 +02:00
dependabot[bot] 63a9cf2963
web: bump the wdio group in /tests/wdio with 4 updates (#7160)
Bumps the wdio group in /tests/wdio with 4 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner), [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework) and [@wdio/spec-reporter](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-spec-reporter).


Updates `@wdio/cli` from 8.17.0 to 8.18.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.18.0/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.17.0 to 8.18.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.18.0/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.17.0 to 8.18.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.18.0/packages/wdio-mocha-framework)

Updates `@wdio/spec-reporter` from 8.17.0 to 8.18.1
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.18.1/packages/wdio-spec-reporter)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/spec-reporter"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-13 11:35:57 +02:00
transifex-integration[bot] 27ace66836
translate: Updates for file web/xliff/en.xlf in zh_CN (#7162)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-13 11:35:44 +02:00
transifex-integration[bot] 63ad844001
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7161)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-13 11:35:29 +02:00
transifex-integration[bot] 2c73552837
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7158)
* Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

* Removing web/xliff/en.xlf in zh-Hans

99% of minimum 100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-12 19:51:56 +00:00
Tana M Berry 78af350610
website/docs: Balok pr for User docs (#7139)
* procedrual docs

* restructure

* new image, edit tweaks

* more tweaks

* edits

* edits for new button labels

* more content in invitations

* tweaks

* Optimised images with calibre/image-actions

* fixed link

* links

* ken's edits

* changed label name

* spelling checks

* fix links

* links again

* fighting with imports

* ugh

* add extensions back

* fix link

* tweak

* rename file again

* more links

* added punctuation

* use generated index

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-12 21:45:21 +02:00
Ken Sternberg 9d18bc545f
web: change 'Attributes' to 'Custom attributes' on Invitation Field (#7145)
Everywhere else, the label "Attributes" refers to the dictionary field that our
core models have and use as a JSON repository for key/value pairs that don't need
the full model's awareness or management.  Using the same label here, where the
term refers to the context data of the invitation itself, may confuse people,
so we've changed the label to signal its difference.
2023-10-12 12:33:45 -07:00
Ken Sternberg 21e5441f92
web: patternfly hints as ak-web-component (#7120)
* web: patternfly hints as ak-web-component

Patternfly 5's "Hints" React Component, but ported to web components.
The discovery that CSS Custom Properties are still available in
child components, even if they're within independent ShadowDOMs,
made this fairly easy to port from Handlebars to Lit-HTML.  Moving
the definitions into `:host` and the applications into the root DIV
of the component made duplicating the Patternfly 5 structure
straightforward.

Despite the [Patternfly
Elements]documentation](https://patternflyelements.org/docs/develop/create/),
there's a lot to Patternfly Elements that isn't well documented,
such as their slot controller, which near as I can tell just makes
it easy to determine if a slot with the given name is actually being
used by the client code, but it's hard to tell why, other than that it
provides an easy way to determine if some CSS should be included.

* Pre-commit fixes.

* web: fix some issues with styling found while testing.

* web: separated the "with Title" and "without Title" stories.

* Added footer story, fixed some CSS.

* web: hint controller

Add the `ShowHintController`.  This ReactiveController takes a token
in its constructor, and looks in LocalStorage for that token and
an associated value.  If that value is not `undefined`, it sets the
field `this.host.showHint` to the value found.

It also provides a `render()` method that provides an `ak-hint-footer`
with a checkbox and the "Don't show this message again," and responds
to clicks on the checkbox by setting the `this.hint.showHint` and
LocalStorage values to "false".

An example web component using it has been supplied.

* web: support dark mode for hints.

This was nifty.  Still not entirely sure about the `theme="dark"`
rippling through the product, but in this case it works quite well.
All it took was defining the alternative dark mode values in a CSS
entry, `:host([theme="dark"]) { ... }` and exploiting Patternfly's
already intensely atomized CSS Custom Properties properly.

* web: revise colors to use more of the Authentik dark-mode style.

* Update web/src/components/ak-hint/ak-hint.ts

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

* remove any

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens L. <jens@beryju.org>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-10-12 10:44:15 -07:00
Jens L b503379319
web: fix form default submit handler (#7122)
* web/elements: rename renderInlineForm to renderForm set submit handler to empty function

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix all kinds of forms not using the form inheritance correctly

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-12 15:12:46 +02:00
Jens L d1f2e7c0cd
web/admin: add additional Flow info (#7155)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-12 14:00:45 +02:00
Jens L abab635a01
tests: fix potential infinite wait in tests spinning up a container (#7153)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-12 13:57:29 +02:00
Jens L 6d1eef039e
ci: disable ghcr retention schedule while it's broken (#7154)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-12 13:52:32 +02:00
transifex-integration[bot] ccd805ed3c
translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#7151)
Translate locale/en/LC_MESSAGES/django.po in de

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-12 12:36:58 +02:00
dependabot[bot] 5f2b9028b8
core: bump golang.org/x/net from 0.16.0 to 0.17.0 (#7148)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-12 11:26:52 +02:00
dependabot[bot] 4272af584f
web: bump the babel group in /web with 5 updates (#7149)
Bumps the babel group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.23.0` | `7.23.2` |
| [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) | `7.23.0` | `7.23.2` |
| [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) | `7.22.15` | `7.23.2` |
| [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) | `7.22.20` | `7.23.2` |
| [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) | `7.23.0` | `7.23.2` |


Updates `@babel/core` from 7.23.0 to 7.23.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/@babel/core@7.23.2/packages/babel-core)

Updates `@babel/plugin-proposal-decorators` from 7.23.0 to 7.23.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.23.2/packages/babel-plugin-proposal-decorators)

Updates `@babel/plugin-transform-runtime` from 7.22.15 to 7.23.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.23.2/packages/babel-plugin-transform-runtime)

Updates `@babel/preset-env` from 7.22.20 to 7.23.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.23.2/packages/babel-preset-env)

Updates `@babel/preset-typescript` from 7.23.0 to 7.23.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.23.2/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/plugin-proposal-decorators"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: babel
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: babel
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-12 11:07:25 +02:00
dependabot[bot] 52ce8ec145
core: bump sentry-sdk from 1.31.0 to 1.32.0 (#7150)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.31.0 to 1.32.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.31.0...1.32.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>
2023-10-12 11:06:43 +02:00
Jens L 58bd637c43
website: make get started on pricing page go to customer portal (#7147) 2023-10-11 21:15:59 +02:00
dependabot[bot] 8f493c8e13
web: bump pyright from 1.1.330 to 1.1.331 in /web (#7143)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.330 to 1.1.331.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.331/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  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>
2023-10-11 11:36:36 +02:00
dependabot[bot] d596e65ae0
core: bump golang from 1.21.2-bookworm to 1.21.3-bookworm (#7142)
Bumps golang from 1.21.2-bookworm to 1.21.3-bookworm.

---
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>
2023-10-11 11:36:24 +02:00
dependabot[bot] a0b0bb6cbf
core: bump gitpython from 3.1.35 to 3.1.37 (#7140)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.35 to 3.1.37.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.35...3.1.37)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 23:19:46 +02:00
dependabot[bot] b795f8043c
core: bump goauthentik.io/api/v3 from 3.2023083.5 to 3.2023083.6 (#7124)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.5 to 3.2023083.6.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.5...v3.2023083.6)

---
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>
2023-10-10 13:00:38 +02:00
Baptistecottey abd9d5919d
website/docs: fix PowerDNS Docker Hub repo name (#7134)
Update index.md

Change Docker Hub repository name : https://github.com/PowerDNS-Admin/PowerDNS-Admin/issues/1317

Signed-off-by: Baptistecottey <Baptistecottey@users.noreply.github.com>
2023-10-10 12:59:57 +02:00
Rebecca Dodd 52ab0be787
website/blog: Fix typo in SCIM post (#7136)
Fix typo in SCIM post

Signed-off-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
2023-10-10 12:58:33 +02:00
Jens L dd7d3bf738
providers/proxy: fix redis cookies missing strict path (#7135)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-10 12:17:35 +02:00
dependabot[bot] bc595a9724
web: bump @lit-labs/task from 3.0.2 to 3.1.0 in /web (#7132)
Bumps [@lit-labs/task](https://github.com/lit/lit/tree/HEAD/packages/labs/task) from 3.0.2 to 3.1.0.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/task/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/task@3.1.0/packages/labs/task)

---
updated-dependencies:
- dependency-name: "@lit-labs/task"
  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>
2023-10-10 12:13:18 +02:00
dependabot[bot] 5865602fd0
web: bump @lit/localize-tools from 0.6.10 to 0.7.0 in /web (#7133)
Bumps [@lit/localize-tools](https://github.com/lit/lit/tree/HEAD/packages/localize-tools) from 0.6.10 to 0.7.0.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/localize-tools/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit/localize-tools@0.7.0/packages/localize-tools)

---
updated-dependencies:
- dependency-name: "@lit/localize-tools"
  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>
2023-10-10 12:13:09 +02:00
dependabot[bot] f07a1edcfd
web: bump the eslint group in /tests/wdio with 2 updates (#7128)
Bumps the eslint group in /tests/wdio with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.7.4 to 6.7.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/v6.7.5/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.7.4 to 6.7.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/v6.7.5/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 11:28:11 +02:00
dependabot[bot] 4b03b3f4c5
core: bump structlog from 23.1.0 to 23.2.0 (#7125)
Bumps [structlog](https://github.com/hynek/structlog) from 23.1.0 to 23.2.0.
- [Release notes](https://github.com/hynek/structlog/releases)
- [Changelog](https://github.com/hynek/structlog/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hynek/structlog/compare/23.1.0...23.2.0)

---
updated-dependencies:
- dependency-name: structlog
  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>
2023-10-10 11:27:37 +02:00
dependabot[bot] a9997cf377
core: bump selenium from 4.13.0 to 4.14.0 (#7126)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.13.0 to 4.14.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.13.0...selenium-4.14.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>
2023-10-10 11:27:28 +02:00
dependabot[bot] 00cbfd2eb9
web: bump the eslint group in /web with 2 updates (#7127)
Bumps the eslint group in /web with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.7.4 to 6.7.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/v6.7.5/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.7.4 to 6.7.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/v6.7.5/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 11:27:12 +02:00
dependabot[bot] 5c4216538b
web: bump the wdio group in /tests/wdio with 4 updates (#7129)
Bumps the wdio group in /tests/wdio with 4 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner), [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework) and [@wdio/spec-reporter](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-spec-reporter).


Updates `@wdio/cli` from 8.16.22 to 8.17.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.17.0/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.16.22 to 8.17.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.17.0/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.16.22 to 8.17.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.17.0/packages/wdio-mocha-framework)

Updates `@wdio/spec-reporter` from 8.16.22 to 8.17.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.17.0/packages/wdio-spec-reporter)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/spec-reporter"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 11:26:59 +02:00
Jens L a22bc5a261
lifecycle: fix install_id migration not running (#7116)
* lifecycle: fix install_id migration not running

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix ldap test?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* idk if this works

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-09 19:52:06 +02:00
Philipp Kolberg 94fd22b448
core: bump Go from 1.20 to 1.21 (#7117)
Initial commit.
2023-10-09 19:20:02 +02:00
vherrlein f11bb8bfd4
providers/ldap: add windows adsi support (#7098)
* fix(outpost/ldap): missing user object classes

* add "person" object class
* update user object classes
* update boolean strings to upper for being compliant

tags: WIP-LDAP-Outpost-Windows-ADSI-Support

* feat(outpost/ldap): add subschema attributes

* add supported capability OIDs for Windows
* add relevant supported ldap control OIDs

tags: WIP-LDAP-Outpost-Windows-ADSI-Support

* feat(outpost/ldap): update schema for windows Compatibility

* add relevant dITContentRules for authentik
* add all existing attribute types for Windows/Unix/Linux
* add missing object classes definitions
* update classes definitions for being compliant with LDAP schema
* update attributes orders

tags: WIP-LDAP-Outpost-Windows-ADSI-Support

* feat(outpost/ldap): refine LDAP attribute types

* remove unsused attribute types
* order attribute types

tags: WIP-LDAP-Outpost-Windows-ADSI-Support
2023-10-09 13:17:46 +02:00
authentik-automation[bot] a9011a641f
web: bump API Client version (#7113)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-09 10:50:20 +00:00
transifex-integration[bot] 15559974a8
translate: Updates for file web/xliff/en.xlf in zh-Hans on branch main (#7112)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-09 12:36:27 +02:00
transifex-integration[bot] 73930d7e8b
translate: Updates for file web/xliff/en.xlf in zh_CN on branch main (#7111)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-09 12:36:12 +02:00
dependabot[bot] 8ad7339cf1
web: bump the wdio group in /tests/wdio with 4 updates (#7108)
Bumps the wdio group in /tests/wdio with 4 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner), [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework) and [@wdio/spec-reporter](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-spec-reporter).


Updates `@wdio/cli` from 8.16.20 to 8.16.22
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.22/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.16.20 to 8.16.22
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.22/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.16.17 to 8.16.22
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.22/packages/wdio-mocha-framework)

Updates `@wdio/spec-reporter` from 8.16.17 to 8.16.22
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.22/packages/wdio-spec-reporter)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/spec-reporter"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 12:34:46 +02:00
horego ab1b3b09d6
core/api: add uuid field to core api user http response (#7110)
* feat: Add uuid field to core api user response

* update schema

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: hor <hor@HOSRV>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-09 12:34:38 +02:00
dependabot[bot] 026dfadb59
core: bump goauthentik.io/api/v3 from 3.2023083.4 to 3.2023083.5 (#7105)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.4 to 3.2023083.5.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.4...v3.2023083.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>
2023-10-09 11:52:05 +02:00
dependabot[bot] 1b0024518b
core: bump golang.org/x/oauth2 from 0.12.0 to 0.13.0 (#7106)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.12.0 to 0.13.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  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>
2023-10-09 11:51:21 +02:00
dependabot[bot] d1bef0ce48
web: bump the eslint group in /tests/wdio with 1 update (#7107)
Bumps the eslint group in /tests/wdio with 1 update: [eslint](https://github.com/eslint/eslint).

- [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.50.0...v8.51.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 11:51:04 +02:00
Jens L 4db365c947
providers/proxy: improve SLO by backchannel logging out sessions (#7099)
* outposts: add support for provider-specific websocket messages

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* providers/proxy: add custom signal on logout to logout in provider

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-09 01:06:52 +02:00
dependabot[bot] f60b65c25f
web: bump @rollup/plugin-node-resolve from 15.2.2 to 15.2.3 in /web (#7104)
Bumps [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/HEAD/packages/node-resolve) from 15.2.2 to 15.2.3.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/node-resolve/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/node-resolve-v15.2.3/packages/node-resolve)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-node-resolve"
  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>
2023-10-09 01:06:32 +02:00
dependabot[bot] f192c665d9
web: bump the eslint group in /web with 1 update (#7103)
Bumps the eslint group in /web with 1 update: [eslint](https://github.com/eslint/eslint).

- [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.50.0...v8.51.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 01:06:23 +02:00
dependabot[bot] 30da53f3d7
web: bump the storybook group in /web with 1 update (#7102)
Bumps the storybook group in /web with 1 update: [eslint-plugin-storybook](https://github.com/storybookjs/eslint-plugin-storybook).

- [Release notes](https://github.com/storybookjs/eslint-plugin-storybook/releases)
- [Changelog](https://github.com/storybookjs/eslint-plugin-storybook/blob/main/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/eslint-plugin-storybook/compare/v0.6.14...v0.6.15)

---
updated-dependencies:
- dependency-name: eslint-plugin-storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 01:06:16 +02:00
authentik-automation[bot] 962f9aad11
web: bump API Client version (#7101)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-08 22:41:19 +00:00
Jens L 6f3fc22c9b
providers/saml: add default RelayState value for IDP-initiated requests (#7100)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-09 00:08:16 +02:00
Jens L b90ed6bab3
lifecycle: improve reliability of system migrations (#7089)
* lifecycle: improve reliability of system migrations

better transaction handling which allows for re-trying migrations without needing manual intervention

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove explicit commit

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-06 18:56:10 +02:00
Jens L 25ee6f8116
sources/ldap: fix attribute path resolution (#7090)
* lib: make set_path_in_dict reusable

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* sources/ldap: use set_path_in_dict to set attributes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* stages/user_write: also use set_path_in_dict

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-06 18:01:09 +02:00
Philipp Kolberg ccb3875e86
root: Ignore the vendor folder (#7094)
Ignore the vendor folder

When creating a local development environment a vendor folder will automatically be created for storing Go dependencies. This data shall not be uploaded to GitHub.
2023-10-06 17:50:46 +02:00
jon r 9860ac983c
website/docs: fix typo in providers/scim (#7076)
chore(docs): typo in providers/scim

Signed-off-by: jon r <jon@allmende.io>
2023-10-06 17:43:03 +02:00
dependabot[bot] 9d63456ed9
web: bump rollup from 4.0.1 to 4.0.2 in /web (#7095)
Bumps [rollup](https://github.com/rollup/rollup) from 4.0.1 to 4.0.2.
- [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/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: rollup
  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>
2023-10-06 17:42:08 +02:00
dependabot[bot] 7ac25e221e
web: bump rollup from 4.0.0 to 4.0.1 in /web (#7091)
Bumps [rollup](https://github.com/rollup/rollup) from 4.0.0 to 4.0.1.
- [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/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: rollup
  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>
2023-10-06 16:08:39 +02:00
Jens Langhammer 090d2d8362
Revert "lifecycle: improve reliability of system migrations"
This reverts commit 3b8b307c4d.
2023-10-06 15:46:45 +02:00
Jens Langhammer 3b8b307c4d
lifecycle: improve reliability of system migrations
better transaction handling which allows for re-trying migrations without needing manual intervention

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-06 13:51:23 +02:00
dependabot[bot] 9050759f6b
web: bump @rollup/plugin-commonjs from 25.0.4 to 25.0.5 in /web (#7081)
Bumps [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/HEAD/packages/commonjs) from 25.0.4 to 25.0.5.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/commonjs/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/HEAD/packages/commonjs)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-commonjs"
  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>
2023-10-06 11:51:46 +02:00
dependabot[bot] cb2f06b6c1
web: bump @rollup/plugin-replace from 5.0.2 to 5.0.3 in /web (#7082)
Bumps [@rollup/plugin-replace](https://github.com/rollup/plugins/tree/HEAD/packages/replace) from 5.0.2 to 5.0.3.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/replace/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/babel-v5.0.3/packages/replace)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-replace"
  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>
2023-10-06 11:51:30 +02:00
dependabot[bot] 802d19729b
web: bump @rollup/plugin-typescript from 11.1.4 to 11.1.5 in /web (#7078)
Bumps [@rollup/plugin-typescript](https://github.com/rollup/plugins/tree/HEAD/packages/typescript) from 11.1.4 to 11.1.5.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/typescript/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/HEAD/packages/typescript)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-typescript"
  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>
2023-10-06 11:50:47 +02:00
dependabot[bot] 58f52f92f8
web: bump rollup from 3.29.4 to 4.0.0 in /web (#7080)
Bumps [rollup](https://github.com/rollup/rollup) from 3.29.4 to 4.0.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/v3.29.4...v4.0.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  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>
2023-10-06 11:50:11 +02:00
dependabot[bot] 1351bfc6e9
web: bump @rollup/plugin-node-resolve from 15.2.1 to 15.2.2 in /web (#7079)
Bumps [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/HEAD/packages/node-resolve) from 15.2.1 to 15.2.2.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/node-resolve/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/HEAD/packages/node-resolve)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-node-resolve"
  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>
2023-10-06 11:49:58 +02:00
dependabot[bot] 4b2359ffa8
web: bump @rollup/plugin-babel from 6.0.3 to 6.0.4 in /web (#7083)
Bumps [@rollup/plugin-babel](https://github.com/rollup/plugins/tree/HEAD/packages/babel) from 6.0.3 to 6.0.4.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/babel/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/HEAD/packages/babel)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-babel"
  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>
2023-10-06 11:49:21 +02:00
dependabot[bot] f71dbf2df3
web: bump @rollup/plugin-terser from 0.4.3 to 0.4.4 in /web (#7084)
Bumps [@rollup/plugin-terser](https://github.com/rollup/plugins/tree/HEAD/packages/terser) from 0.4.3 to 0.4.4.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/terser/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/HEAD/packages/terser)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-terser"
  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>
2023-10-06 11:48:54 +02:00
dependabot[bot] de50f45295
core: bump twilio from 8.9.0 to 8.9.1 (#7087)
Bumps [twilio](https://github.com/twilio/twilio-python) from 8.9.0 to 8.9.1.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/8.9.0...8.9.1)

---
updated-dependencies:
- dependency-name: twilio
  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>
2023-10-06 11:47:33 +02:00
dependabot[bot] 241a77040c
core: bump golang.org/x/sync from 0.3.0 to 0.4.0 (#7086)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.3.0 to 0.4.0.
- [Commits](https://github.com/golang/sync/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  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>
2023-10-06 11:47:21 +02:00
dependabot[bot] 279d54f800
core: bump golang from 1.21.1-bookworm to 1.21.2-bookworm (#7085)
Bumps golang from 1.21.1-bookworm to 1.21.2-bookworm.

---
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>
2023-10-06 11:47:07 +02:00
Philipp Kolberg 205d3d10e3
root: Support PyCharm's test runner (#7074)
* Initial commit.

* Use Django's test runner as basis

* Skip already correctly formatted test labels
2023-10-05 20:13:38 +02:00
Tana M Berry 36c10c74e4
website/blog: SCIM blog (#7072)
* blog about SCIM

* ready for review

* Optimised images with calibre/image-actions

* minor changes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-05 11:08:38 -05:00
dependabot[bot] 87fa313d44
web: bump the wdio group in /tests/wdio with 2 updates (#7069)
Bumps the wdio group in /tests/wdio with 2 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli) and [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner).


Updates `@wdio/cli` from 8.16.19 to 8.16.20
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.20/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.16.19 to 8.16.20
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.20/packages/wdio-local-runner)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-05 11:39:21 +02:00
dependabot[bot] 96c669803c
core: bump github.com/getsentry/sentry-go from 0.24.1 to 0.25.0 (#7070)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.24.1 to 0.25.0.
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.24.1...v0.25.0)

---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  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>
2023-10-05 11:39:03 +02:00
Jens L f28f301865
policies: fix cached policy metric (#7068) 2023-10-05 02:05:01 +02:00
Jens L 83f9eae654
root: extended flow and policy metrics (#7067) 2023-10-05 01:04:55 +02:00
Ken Sternberg 6792bf8876
web: package up horizontal elements into their own components (#7053)
* web: laying the groundwork for future expansion

This commit is a hodge-podge of updates and changes to the web.  Functional changes:

- Makefile: Fixed a bug in the `help` section that prevented the WIDTH from being accurately
  calculated if `help` was included rather than in-lined.

- ESLint: Modified the "unused vars" rule so that variables starting with an underline are not
  considered by the rule.  This allows for elided variables in event handlers.  It's not a perfect
  solution-- a better one would be to use Typescript's function-specialization typing, but there are
  too many places where we elide or ignore some variables in a function's usage that switching over
  to specialization would be a huge lift.

- locale: It turns out, lit-locale does its own context management.  We don't need to have a context
  at all in this space, and that's one less listener we need to attach t othe DOM.

- ModalButton: A small thing, but using `nothing` instead of "html``" allows lit better control over
  rendering and reduces the number of actual renders of the page.

- FormGroup: Provided a means to modify the aria-label, rather than stick with the just the word
  "Details."  Specializing this field will both help users of screen readers in the future, and will
  allow test suites to find specific form groups now.

- RadioButton: provide a more consistent interface to the RadioButton.  First, we dispatch the
  events to the outside world, and we set the value locally so that the current `Form.ts` continues
  to behave as expected.  We also prevent the "button lost value" event from propagating; this
  presents a unified select-like interface to users of the RadioButtonGroup.  The current value
  semantics are preserved; other clients of the RadioButton do not see a change in behavior.

- EventEmitter: If the custom event detail is *not* an object, do not use the object-like semantics
  for forwarding it; just send it as-is.

- Comments: In the course of laying the groundwork for the application wizard, I throw a LOT of
  comments into the code, describing APIs, interfaces, class and function signatures, to better
  document the behavior inside and as signposts for future work.

* web: permit arrays to be sent in custom events without interpolation.

* actually use assignValue or rather serializeFieldRecursive

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: package up horizontal elements into their own components.

This commit introduces a number of "components."  Jens has this idiom:

```
   <ak-form-element-horizontal label=${msg("Name")} name="name" ?required=${true}>
       <input
           type="text"
           value="${ifDefined(this.instance?.name)}"
           class="pf-c-form-control"
           required
       />
   </ak-form-element-horizontal>
```

It's a very web-oriented idiom in that it's built out of two building blocks, the "element-horizontal" descriptor,
and the input object itself.  This idiom is repeated a lot throughout the code.  As an alternative, let's wrap
everything into an inheritable interface:

```
  <ak-text-input
      name="name"
      label=${msg("Name")}
      value="${ifDefined(this.instance?.name)}
      required
  >
  </ak-text-input>
```

This preserves all the information of the above, makes it much clearer what kind of interaction we're having
(sometimes the `type=` information in an input is lost or easily missed), and while it does require you know
that there are provided components rather than the pair of layout-behavior as in the original it also gives
the developer more precision over the look and feel of the components.

*Right now* these components are placed into the LightDOM, as they are in the existing source code, because
the Form handler has a need to be able to "peer into" the "element-horizontal" component to find the values
of the input objects.  In a future revision I hope to place the burden of type/value processing onto the
input objects themselves such that the form handler will need only look for the `.value` of the associated
input control.

Other fixes:

- update the FlowSearch() such that it actually emits an input event when its value changes.
- Disable the storybook shortcuts; on Chrome, at least, they get confused with simple inputs
- Fix an issue with precommit to not scan any Python with ESLint!  :-)

* web: provide storybook stories for the components

This commit provides storybook stories for the ak-horizontal-element wrappers.  A few
bugs were found along the way, including one rather nasty one from Radio where we
were still getting the "set/unset" pair in the wrong order, so I had to knuckle down
and fix the event handler properly.

* web: test oauth2 provider "guinea pig" for new components

I used the Oauth2 provider page as my experiment in seeing if the
horizontal-element wrappers could be used instead of the raw wrappers
themselves, and I wanted to make sure a test existed that asserts
that filling out THAT form in the ProvidersList and ProvidersForm
didn't break anything.

This commit updates the WDIO tests to do just that; the test is
simple, but it does exercise the `name` field of the Provider,
something not needed in the Wizard because it's set automatically
based on the Application name, and it even asserts that the new
Provider exists in the list of available Providers when it's done.

* web: making sure ESlint and Prettier are happy

* "fix" lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-04 13:07:52 -07:00
dependabot[bot] fb1768270e
core: bump django from 4.2.5 to 4.2.6 (#7066)
Bumps [django](https://github.com/django/django) from 4.2.5 to 4.2.6.
- [Commits](https://github.com/django/django/compare/4.2.5...4.2.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>
2023-10-04 19:24:06 +02:00
transifex-integration[bot] 94fa58cd6e
translate: Updates for file locale/en/LC_MESSAGES/django.po in fr on branch main (#7065)
Translate locale/en/LC_MESSAGES/django.po in fr

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'fr'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-04 18:59:24 +02:00
dependabot[bot] b2327e7641
web: bump postcss from 8.4.29 to 8.4.31 in /web (#7064)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.29 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.29...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-04 11:17:26 +02:00
transifex-integration[bot] 94a23f0d21
translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans on branch main (#7057)
Translate django.po in zh-Hans

100% translated source file: 'django.po'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-04 11:07:54 +02:00
transifex-integration[bot] b20d6317fd
translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN on branch main (#7056)
Translate locale/en/LC_MESSAGES/django.po in zh_CN

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-04 11:07:40 +02:00
dependabot[bot] 3a64c7e101
web: bump pyright from 1.1.329 to 1.1.330 in /web (#7060)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.329 to 1.1.330.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.330/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  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>
2023-10-04 11:07:27 +02:00
dependabot[bot] 6a4cb5eebf
web: bump the storybook group in /web with 5 updates (#7059)
Bumps the storybook group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `7.4.5` | `7.4.6` |
| [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `7.4.5` | `7.4.6` |
| [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) | `7.4.5` | `7.4.6` |
| [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite) | `7.4.5` | `7.4.6` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `7.4.5` | `7.4.6` |


Updates `@storybook/addon-essentials` from 7.4.5 to 7.4.6
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.6/code/addons/essentials)

Updates `@storybook/addon-links` from 7.4.5 to 7.4.6
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.6/code/addons/links)

Updates `@storybook/web-components` from 7.4.5 to 7.4.6
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.6/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 7.4.5 to 7.4.6
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.6/code/frameworks/web-components-vite)

Updates `storybook` from 7.4.5 to 7.4.6
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.4.6/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-04 11:06:52 +02:00
dependabot[bot] ecb614765a
web: bump the wdio group in /tests/wdio with 2 updates (#7063)
Bumps the wdio group in /tests/wdio with 2 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli) and [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner).


Updates `@wdio/cli` from 8.16.18 to 8.16.19
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.19/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.16.18 to 8.16.19
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.19/packages/wdio-local-runner)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-04 11:06:15 +02:00
dependabot[bot] 6bd1df2901
core: bump duo-client from 5.0.1 to 5.1.0 (#7062)
Bumps [duo-client](https://github.com/duosecurity/duo_client_python) from 5.0.1 to 5.1.0.
- [Release notes](https://github.com/duosecurity/duo_client_python/releases)
- [Commits](https://github.com/duosecurity/duo_client_python/compare/5.0.1...5.1.0)

---
updated-dependencies:
- dependency-name: duo-client
  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>
2023-10-04 11:05:50 +02:00
dependabot[bot] a2e5203b85
core: bump goauthentik.io/api/v3 from 3.2023083.3 to 3.2023083.4 (#7061)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.3 to 3.2023083.4.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.3...v3.2023083.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>
2023-10-04 11:05:37 +02:00
Rebecca Dodd d22b9a4403
Add meta description to black box blog post (#7049)
Signed-off-by: Rebecca Dodd <82806852+rebeccadee@users.noreply.github.com>
2023-10-03 10:39:11 -05:00
Jens L 03287936e9
web/flows: fix plex login not opening new tab on mobile safari (#7050)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-03 15:32:48 +02:00
authentik-automation[bot] 962eb8da3c
web: bump API Client version (#7052)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-03 12:29:31 +00:00
Jens L a0f607b5ac
web/flows: bottom-align about text on flows page (#7051)
* web/flows: bottom-align about text on flows page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix a bunch of typos

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-03 14:10:10 +02:00
dependabot[bot] a1353d567b
core: bump codespell from 2.2.5 to 2.2.6 (#7046)
Bumps [codespell](https://github.com/codespell-project/codespell) from 2.2.5 to 2.2.6.
- [Release notes](https://github.com/codespell-project/codespell/releases)
- [Commits](https://github.com/codespell-project/codespell/compare/v2.2.5...v2.2.6)

---
updated-dependencies:
- dependency-name: codespell
  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>
2023-10-03 12:26:21 +02:00
dependabot[bot] 0cf949f362
core: bump coverage from 7.3.1 to 7.3.2 (#7047)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.3.1 to 7.3.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/7.3.1...7.3.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>
2023-10-03 12:26:11 +02:00
Ken Sternberg 3b171a02b7
web: laying the groundwork for future expansion (#7045)
* web: laying the groundwork for future expansion

This commit is a hodge-podge of updates and changes to the web.  Functional changes:

- Makefile: Fixed a bug in the `help` section that prevented the WIDTH from being accurately
  calculated if `help` was included rather than in-lined.

- ESLint: Modified the "unused vars" rule so that variables starting with an underline are not
  considered by the rule.  This allows for elided variables in event handlers.  It's not a perfect
  solution-- a better one would be to use Typescript's function-specialization typing, but there are
  too many places where we elide or ignore some variables in a function's usage that switching over
  to specialization would be a huge lift.

- locale: It turns out, lit-locale does its own context management.  We don't need to have a context
  at all in this space, and that's one less listener we need to attach t othe DOM.

- ModalButton: A small thing, but using `nothing` instead of "html``" allows lit better control over
  rendering and reduces the number of actual renders of the page.

- FormGroup: Provided a means to modify the aria-label, rather than stick with the just the word
  "Details."  Specializing this field will both help users of screen readers in the future, and will
  allow test suites to find specific form groups now.

- RadioButton: provide a more consistent interface to the RadioButton.  First, we dispatch the
  events to the outside world, and we set the value locally so that the current `Form.ts` continues
  to behave as expected.  We also prevent the "button lost value" event from propagating; this
  presents a unified select-like interface to users of the RadioButtonGroup.  The current value
  semantics are preserved; other clients of the RadioButton do not see a change in behavior.

- EventEmitter: If the custom event detail is *not* an object, do not use the object-like semantics
  for forwarding it; just send it as-is.

- Comments: In the course of laying the groundwork for the application wizard, I throw a LOT of
  comments into the code, describing APIs, interfaces, class and function signatures, to better
  document the behavior inside and as signposts for future work.

* web: permit arrays to be sent in custom events without interpolation.

* actually use assignValue or rather serializeFieldRecursive

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 13:33:27 -07:00
dependabot[bot] 1c7d47da66
core: bump urllib3 from 2.0.5 to 2.0.6 (#7042)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.5 to 2.0.6.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/v2.0.5...2.0.6)

---
updated-dependencies:
- dependency-name: urllib3
  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>
2023-10-02 21:21:27 +02:00
transifex-integration[bot] dba5905a4f
translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN on branch main (#7043)
Translate locale/en/LC_MESSAGES/django.po in zh_CN

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-02 21:21:11 +02:00
transifex-integration[bot] 6017ea07b8
translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans on branch main (#7044)
Translate django.po in zh-Hans

100% translated source file: 'django.po'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-02 21:20:48 +02:00
dependabot[bot] 672446ed9c
web: bump the eslint group in /web with 1 update (#7039)
* web: bump the eslint group in /web with 1 update

Bumps the eslint group in /web with 1 update: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin).

- [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/v6.7.4/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

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

* add wdio to frontend

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 19:37:32 +02:00
dependabot[bot] c32179fcaa
web: bump the eslint group in /tests/wdio with 1 update (#7037)
Bumps the eslint group in /tests/wdio with 1 update: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin).

- [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/v6.7.4/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 19:35:47 +02:00
dependabot[bot] 31acb560da
web: bump @typescript-eslint/parser from 6.7.3 to 6.7.4 in /web (#7041)
* web: bump @typescript-eslint/parser from 6.7.3 to 6.7.4 in /web

Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.7.3 to 6.7.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/v6.7.4/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

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

* fix group for eslint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 19:34:55 +02:00
dependabot[bot] 866c348da7
core: bump ruff from 0.0.291 to 0.0.292 (#7040)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.291 to 0.0.292.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.291...v0.0.292)

---
updated-dependencies:
- dependency-name: ruff
  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>
2023-10-02 19:34:26 +02:00
dependabot[bot] f12aef2f4e
web: bump @typescript-eslint/parser from 6.7.3 to 6.7.4 in /tests/wdio (#7038)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.7.3 to 6.7.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/v6.7.4/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2023-10-02 19:33:48 +02:00
dependabot[bot] 47ccc57d81
web: bump @wdio/mocha-framework from 8.16.12 to 8.16.17 in /tests/wdio (#7032)
Bumps [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework) from 8.16.12 to 8.16.17.
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.17/packages/wdio-mocha-framework)

---
updated-dependencies:
- dependency-name: "@wdio/mocha-framework"
  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>
2023-10-02 19:18:33 +02:00
dependabot[bot] 648b5575fc
web: bump @wdio/cli from 8.16.12 to 8.16.18 in /tests/wdio (#7033)
* web: bump @wdio/cli from 8.16.12 to 8.16.18 in /tests/wdio

Bumps [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli) from 8.16.12 to 8.16.18.
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.18/packages/wdio-cli)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

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

* group wdio in dependabot

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 19:18:21 +02:00
dependabot[bot] f09e044be4
web: bump @wdio/spec-reporter from 8.16.12 to 8.16.17 in /tests/wdio (#7034)
Bumps [@wdio/spec-reporter](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-spec-reporter) from 8.16.12 to 8.16.17.
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.17/packages/wdio-spec-reporter)

---
updated-dependencies:
- dependency-name: "@wdio/spec-reporter"
  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>
2023-10-02 19:17:10 +02:00
dependabot[bot] e8a408c15c
web: bump @wdio/local-runner from 8.16.12 to 8.16.18 in /tests/wdio (#7036)
Bumps [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner) from 8.16.12 to 8.16.18.
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.16.18/packages/wdio-local-runner)

---
updated-dependencies:
- dependency-name: "@wdio/local-runner"
  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>
2023-10-02 19:16:46 +02:00
dependabot[bot] a5ca86c5a0
web: bump the sentry group in /web with 2 updates (#7035)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.72.0 to 7.73.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.72.0...7.73.0)

Updates `@sentry/tracing` from 7.72.0 to 7.73.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.72.0...7.73.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 19:14:03 +02:00
Ken Sternberg 20dde50ed3
web: add webdriverIO testing layer (#6959)
* web/add webdriverIO testing layer

This commit adds WebdriverIO as an end-to-end solution to unit testing.  WebdriverIO can be run both
locally and remotely, supports strong integration with web components, and is generally robust for
use in pipelines.  I'll confess to working through a tutorial on how to do this for web components,
and this is just chapter 2 (I think there are 5 or so chapters...).

There's a makefile, with help!  If you just run `make` it tells you:

```
Specify a command. The choices are:

  help                 Show this help
  node_modules         Runs `npm install` to prepare this feature
  precommit            Run the precommit: spell check all comments, eslint with sonarJS, prettier-write
  test-good-login      Test that we can log into the server. Requires a running instance of the server.
  test-bad-login       Test that bad usernames and passwords create appropriate error messages
```

... because Makefiles are documentation, and documentation belongs in Makefiles.

I've chosen to go with a PageObject-oriented low-level DSL; what that means is that for each major
components (a page, a form, a wizard), there's a class that provides human-readable names for
human-interactable and human-viewable objects on the page.  The LoginPage object, for example, has
selectors for the username, password, submit button, and the failure alert; accessing those allows
us to test for items as expected., and to write a DSL for "a good login" that's as straightforward
as:

```
        await LoginPage.open();
        await LoginPage.login("ken@goauthentik.io", "eat10bugs");
        await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
```

There was a *lot* of messing around with the LoginPage to get the username and password into the
system.  For example, I had to do this with all the `waitForClickable` and `waitForEnable` because
we both keep the buttons inaccessible until the form has something and we "black out" the page (put
a darkening filter over it) while accessing the flow, meaning there was a race condition such that
the test would attempt to interact with the username or password field before it was accessible.
But this works now, which is very nice.

``` JavaScript
    get inputUsername() {
        return $('>>>input[name="uidField"]');
    }

    get btnSubmit() {
        return $('>>>button[type="submit"]');
    }

    async username(username: string) {
        await this.inputUsername.waitForClickable();
        await this.inputUsername.setValue(username);
        await this.btnSubmit.waitForEnabled();
        await this.btnSubmit.click();
    }
```

The bells & whistles of *Prettier*, *Eslint*, and *Codespell* have also been enabled. I do like my
guardrails.

* web/adding tests: added comments and cleaned up some administrative features.

* web/test: changed the name of one test to reflect it's 'good' status

* web: improve testing by adding test admin user via blueprint

* fix blueprints

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update package name

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add dependabot

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* prettier run

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add basic CI

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove hooks

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 08:40:39 -07:00
Jens L 86939937cf
web/admin: use <pre> for order field on bound elements (#7031)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 16:57:21 +02:00
Jens L 4a9b9a2d14
blueprints: fix mismatched user-login stage order (#7030)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 16:04:54 +02:00
Jens L cb6dadbf94
stages/email: rework email templates (#7029)
rework email templates

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 16:04:40 +02:00
Jens L e40a0b1f8b
website/docs: add notice for nginx ingress configuration requirement (#7027)
* website/docs: add notice for nginx ingress configuration requirement

https://github.com/goauthentik/infrastructure/pull/574
Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Update website/docs/providers/proxy/_nginx_ingress.md

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Jens L. <jens@beryju.org>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens L. <jens@beryju.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2023-10-02 16:04:26 +02:00
Marc 'risson' Schmitt 9e23a5edab translate: Updates for web/xliff/en.xlf in fr
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-10-02 13:31:21 +02:00
Marc 'risson' Schmitt 9c3ff1d71b web: locales: rename fr_FR to fr to match transifex
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-10-02 13:31:21 +02:00
Jens L 29de5d34d6
events: fix error when storing events with date/time/datetime/etc (#7028)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 12:44:17 +02:00
Jens L 8c891b04f2
stages/invitation: fix mis-matched serializer class for invitation (#7018)
* stages/invitation: fix mis-matched serializer class for invitation

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix returning an instance

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 12:26:14 +02:00
dependabot[bot] 8efdbd54e8
web: bump mermaid from 10.4.0 to 10.5.0 in /web (#7026)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.4.0 to 10.5.0.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.4.0...v10.5.0)

---
updated-dependencies:
- dependency-name: mermaid
  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>
2023-10-02 11:52:05 +02:00
dependabot[bot] a3cd3ed6b8
web: bump core-js from 3.32.2 to 3.33.0 in /web (#7020)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.32.2 to 3.33.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.33.0/packages/core-js)

---
updated-dependencies:
- dependency-name: core-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>
2023-10-02 11:27:00 +02:00
dependabot[bot] 202b71537a
core: bump webauthn from 1.10.1 to 1.11.0 (#7021)
Bumps [webauthn](https://github.com/duo-labs/py_webauthn) from 1.10.1 to 1.11.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.10.1...v1.11.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>
2023-10-02 11:26:41 +02:00
dependabot[bot] fdf5c7161c
core: bump pylint from 2.17.6 to 2.17.7 (#7022)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 2.17.6 to 2.17.7.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v2.17.6...v2.17.7)

---
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>
2023-10-02 11:26:21 +02:00
dependabot[bot] 47e226aecf
core: bump django-redis from 5.3.0 to 5.4.0 (#7023)
Bumps [django-redis](https://github.com/jazzband/django-redis) from 5.3.0 to 5.4.0.
- [Release notes](https://github.com/jazzband/django-redis/releases)
- [Changelog](https://github.com/jazzband/django-redis/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jazzband/django-redis/compare/5.3.0...5.4.0)

---
updated-dependencies:
- dependency-name: django-redis
  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>
2023-10-02 11:26:01 +02:00
dependabot[bot] bcb83c259f
core: bump packaging from 23.1 to 23.2 (#7024)
Bumps [packaging](https://github.com/pypa/packaging) from 23.1 to 23.2.
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/packaging/compare/23.1...23.2)

---
updated-dependencies:
- dependency-name: packaging
  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>
2023-10-02 11:25:44 +02:00
Marc 'risson' Schmitt d55c0c1c2d web/admin: invitation stage: default "continue without invitation" to false
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-29 18:40:12 +02:00
dependabot[bot] 17047da18b
core: bump pydantic from 2.4.1 to 2.4.2 (#7014)
* core: bump pydantic from 2.4.1 to 2.4.2

Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.4.1 to 2.4.2.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.4.1...v2.4.2)

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

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

* fix codeowners

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-09-29 10:50:43 +02:00
dependabot[bot] 57d1dd44a8
website: bump postcss from 8.4.30 to 8.4.31 in /website (#7015)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.30 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.30...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  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>
2023-09-29 10:49:14 +02:00
625 changed files with 40454 additions and 11127 deletions

View file

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 2023.8.3 current_version = 2023.10.6
tag = True tag = True
commit = True commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+) parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)

View file

@ -2,36 +2,39 @@ name: "Setup authentik testing environment"
description: "Setup authentik testing environment" description: "Setup authentik testing environment"
inputs: inputs:
postgresql_tag: postgresql_version:
description: "Optional postgresql image tag" description: "Optional postgresql image tag"
default: "12" default: "12"
runs: runs:
using: "composite" using: "composite"
steps: steps:
- name: Install poetry - name: Install poetry & deps
shell: bash shell: bash
run: | run: |
pipx install poetry || true pipx install poetry || true
sudo apt update sudo apt-get update
sudo apt install -y libpq-dev openssl libxmlsec1-dev pkg-config gettext sudo apt-get install --no-install-recommends -y libpq-dev openssl libxmlsec1-dev pkg-config gettext
- name: Setup python and restore poetry - name: Setup python and restore poetry
uses: actions/setup-python@v3 uses: actions/setup-python@v4
with: with:
python-version: "3.11" python-version-file: 'pyproject.toml'
cache: "poetry" cache: "poetry"
- name: Setup node - name: Setup node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "20" node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: web/package-lock.json cache-dependency-path: web/package-lock.json
- name: Setup go
uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
- name: Setup dependencies - name: Setup dependencies
shell: bash shell: bash
run: | run: |
export PSQL_TAG=${{ inputs.postgresql_tag }} export PSQL_TAG=${{ inputs.postgresql_version }}
docker-compose -f .github/actions/setup/docker-compose.yml up -d docker-compose -f .github/actions/setup/docker-compose.yml up -d
poetry env use python3.11
poetry install poetry install
cd web && npm ci cd web && npm ci
- name: Generate config - name: Generate config

2
.github/codecov.yml vendored
View file

@ -6,5 +6,5 @@ coverage:
# adjust accordingly based on how flaky your tests are # adjust accordingly based on how flaky your tests are
# this allows a 1% drop from the previous base commit coverage # this allows a 1% drop from the previous base commit coverage
threshold: 1% threshold: 1%
notify: comment:
after_n_builds: 3 after_n_builds: 3

View file

@ -30,6 +30,7 @@ updates:
open-pull-requests-limit: 10 open-pull-requests-limit: 10
commit-message: commit-message:
prefix: "web:" prefix: "web:"
# TODO: deduplicate these groups
groups: groups:
sentry: sentry:
patterns: patterns:
@ -40,7 +41,7 @@ updates:
- "babel-*" - "babel-*"
eslint: eslint:
patterns: patterns:
- "@typescript-eslint/eslint-*" - "@typescript-eslint/*"
- "eslint" - "eslint"
- "eslint-*" - "eslint-*"
storybook: storybook:
@ -50,6 +51,40 @@ updates:
esbuild: esbuild:
patterns: patterns:
- "@esbuild/*" - "@esbuild/*"
- package-ecosystem: npm
directory: "/tests/wdio"
schedule:
interval: daily
time: "04:00"
labels:
- dependencies
open-pull-requests-limit: 10
commit-message:
prefix: "web:"
# TODO: deduplicate these groups
groups:
sentry:
patterns:
- "@sentry/*"
babel:
patterns:
- "@babel/*"
- "babel-*"
eslint:
patterns:
- "@typescript-eslint/*"
- "eslint"
- "eslint-*"
storybook:
patterns:
- "@storybook/*"
- "*storybook*"
esbuild:
patterns:
- "@esbuild/*"
wdio:
patterns:
- "@wdio/*"
- package-ecosystem: npm - package-ecosystem: npm
directory: "/website" directory: "/website"
schedule: schedule:

View file

@ -11,6 +11,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
env: env:
POSTGRES_DB: authentik POSTGRES_DB: authentik
@ -47,25 +48,38 @@ jobs:
- name: run migrations - name: run migrations
run: poetry run python -m lifecycle.migrate run: poetry run python -m lifecycle.migrate
test-migrations-from-stable: test-migrations-from-stable:
name: test-migrations-from-stable - PostgreSQL ${{ matrix.psql }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
continue-on-error: true strategy:
fail-fast: false
matrix:
psql:
- 12-alpine
- 15-alpine
- 16-alpine
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup authentik env - name: Setup authentik env
uses: ./.github/actions/setup uses: ./.github/actions/setup
with:
postgresql_version: ${{ matrix.psql }}
- name: checkout stable - name: checkout stable
run: | run: |
# Delete all poetry envs
rm -rf /home/runner/.cache/pypoetry
# Copy current, latest config to local # Copy current, latest config to local
cp authentik/lib/default.yml local.env.yml cp authentik/lib/default.yml local.env.yml
cp -R .github .. cp -R .github ..
cp -R scripts .. cp -R scripts ..
git checkout $(git describe --tags $(git rev-list --tags --max-count=1)) git checkout version/$(python -c "from authentik import __version__; print(__version__)")
rm -rf .github/ scripts/ rm -rf .github/ scripts/
mv ../.github ../scripts . mv ../.github ../scripts .
- name: Setup authentik env (ensure stable deps are installed) - name: Setup authentik env (ensure stable deps are installed)
uses: ./.github/actions/setup uses: ./.github/actions/setup
with:
postgresql_version: ${{ matrix.psql }}
- name: run migrations to stable - name: run migrations to stable
run: poetry run python -m lifecycle.migrate run: poetry run python -m lifecycle.migrate
- name: checkout current code - name: checkout current code
@ -75,9 +89,13 @@ jobs:
git reset --hard HEAD git reset --hard HEAD
git clean -d -fx . git clean -d -fx .
git checkout $GITHUB_SHA git checkout $GITHUB_SHA
# Delete previous poetry env
rm -rf $(poetry env info --path)
poetry install poetry install
- name: Setup authentik env (ensure latest deps are installed) - name: Setup authentik env (ensure latest deps are installed)
uses: ./.github/actions/setup uses: ./.github/actions/setup
with:
postgresql_version: ${{ matrix.psql }}
- name: migrate to latest - name: migrate to latest
run: poetry run python -m lifecycle.migrate run: poetry run python -m lifecycle.migrate
test-unittest: test-unittest:
@ -90,12 +108,13 @@ jobs:
psql: psql:
- 12-alpine - 12-alpine
- 15-alpine - 15-alpine
- 16-alpine
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup authentik env - name: Setup authentik env
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
postgresql_tag: ${{ matrix.psql }} postgresql_version: ${{ matrix.psql }}
- name: run unittest - name: run unittest
run: | run: |
poetry run make test poetry run make test
@ -184,6 +203,9 @@ jobs:
build: build:
needs: ci-core-mark needs: ci-core-mark
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
timeout-minutes: 120 timeout-minutes: 120
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -234,6 +256,9 @@ jobs:
build-arm64: build-arm64:
needs: ci-core-mark needs: ci-core-mark
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
timeout-minutes: 120 timeout-minutes: 120
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View file

@ -9,6 +9,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
jobs: jobs:
lint-golint: lint-golint:
@ -29,7 +30,7 @@ jobs:
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v3 uses: golangci/golangci-lint-action@v3
with: with:
version: v1.52.2 version: v1.54.2
args: --timeout 5000s --verbose args: --timeout 5000s --verbose
skip-cache: true skip-cache: true
test-unittest: test-unittest:
@ -65,6 +66,9 @@ jobs:
- ldap - ldap
- radius - radius
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@ -124,9 +128,9 @@ jobs:
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: web/package-lock.json cache-dependency-path: web/package-lock.json
- name: Generate API - name: Generate API

View file

@ -9,31 +9,38 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
jobs: jobs:
lint-eslint: lint-eslint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
project:
- web
- tests/wdio
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: ${{ matrix.project }}/package.json
cache: "npm" cache: "npm"
cache-dependency-path: web/package-lock.json cache-dependency-path: ${{ matrix.project }}/package-lock.json
- working-directory: web/ - working-directory: ${{ matrix.project }}/
run: npm ci run: npm ci
- name: Generate API - name: Generate API
run: make gen-client-ts run: make gen-client-ts
- name: Eslint - name: Eslint
working-directory: web/ working-directory: ${{ matrix.project }}/
run: npm run lint run: npm run lint
lint-build: lint-build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: web/package-lock.json cache-dependency-path: web/package-lock.json
- working-directory: web/ - working-directory: web/
@ -45,27 +52,33 @@ jobs:
run: npm run tsc run: npm run tsc
lint-prettier: lint-prettier:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
project:
- web
- tests/wdio
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: ${{ matrix.project }}/package.json
cache: "npm" cache: "npm"
cache-dependency-path: web/package-lock.json cache-dependency-path: ${{ matrix.project }}/package-lock.json
- working-directory: web/ - working-directory: ${{ matrix.project }}/
run: npm ci run: npm ci
- name: Generate API - name: Generate API
run: make gen-client-ts run: make gen-client-ts
- name: prettier - name: prettier
working-directory: web/ working-directory: ${{ matrix.project }}/
run: npm run prettier-check run: npm run prettier-check
lint-lit-analyse: lint-lit-analyse:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: web/package-lock.json cache-dependency-path: web/package-lock.json
- working-directory: web/ - working-directory: web/
@ -95,9 +108,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: web/package-lock.json cache-dependency-path: web/package-lock.json
- working-directory: web/ - working-directory: web/

View file

@ -9,15 +9,16 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
jobs: jobs:
lint-prettier: lint-prettier:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: website/package.json
cache: "npm" cache: "npm"
cache-dependency-path: website/package-lock.json cache-dependency-path: website/package-lock.json
- working-directory: website/ - working-directory: website/
@ -29,9 +30,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: website/package.json
cache: "npm" cache: "npm"
cache-dependency-path: website/package-lock.json cache-dependency-path: website/package-lock.json
- working-directory: website/ - working-directory: website/
@ -50,9 +51,9 @@ jobs:
- build-docs-only - build-docs-only
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: website/package.json
cache: "npm" cache: "npm"
cache-dependency-path: website/package-lock.json cache-dependency-path: website/package-lock.json
- working-directory: website/ - working-directory: website/

View file

@ -1,8 +1,8 @@
name: ghcr-retention name: ghcr-retention
on: on:
schedule: # schedule:
- cron: "0 0 * * *" # every day at midnight # - cron: "0 0 * * *" # every day at midnight
workflow_dispatch: workflow_dispatch:
jobs: jobs:

View file

@ -6,6 +6,7 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
# Needed to be able to push to the next branch
contents: write contents: write
jobs: jobs:

View file

@ -7,6 +7,9 @@ on:
jobs: jobs:
build-server: build-server:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
@ -27,8 +30,10 @@ jobs:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: make empty ts client - name: make empty clients
run: mkdir -p ./gen-ts-client run: |
mkdir -p ./gen-ts-api
mkdir -p ./gen-go-api
- name: Build Docker Image - name: Build Docker Image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
@ -50,6 +55,9 @@ jobs:
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
build-outpost: build-outpost:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -69,6 +77,10 @@ jobs:
- name: prepare variables - name: prepare variables
uses: ./.github/actions/docker-push-variables uses: ./.github/actions/docker-push-variables
id: ev id: ev
- name: make empty clients
run: |
mkdir -p ./gen-ts-api
mkdir -p ./gen-go-api
- name: Docker Login Registry - name: Docker Login Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
@ -93,12 +105,16 @@ jobs:
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
context: .
build-args: | build-args: |
VERSION=${{ steps.ev.outputs.version }} VERSION=${{ steps.ev.outputs.version }}
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
build-outpost-binary: build-outpost-binary:
timeout-minutes: 120 timeout-minutes: 120
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload binaries to the release
contents: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -113,9 +129,9 @@ jobs:
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: web/package-lock.json cache-dependency-path: web/package-lock.json
- name: Build web - name: Build web

View file

@ -16,6 +16,7 @@ jobs:
echo "PG_PASS=$(openssl rand -base64 32)" >> .env echo "PG_PASS=$(openssl rand -base64 32)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env
docker buildx install docker buildx install
mkdir -p ./gen-ts-api
docker build -t testing:latest . docker build -t testing:latest .
echo "AUTHENTIK_IMAGE=testing" >> .env echo "AUTHENTIK_IMAGE=testing" >> .env
echo "AUTHENTIK_TAG=latest" >> .env echo "AUTHENTIK_TAG=latest" >> .env

View file

@ -6,8 +6,8 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
# Needed to update issues and PRs
issues: write issues: write
pull-requests: write
jobs: jobs:
stale: stale:

View file

@ -17,9 +17,9 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
token: ${{ steps.generate_token.outputs.token }} token: ${{ steps.generate_token.outputs.token }}
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version-file: web/package.json
registry-url: "https://registry.npmjs.org" registry-url: "https://registry.npmjs.org"
- name: Generate API Client - name: Generate API Client
run: make gen-client-ts run: make gen-client-ts

4
.gitignore vendored
View file

@ -194,7 +194,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
/variables/
media/ media/
*mmdb *mmdb
@ -207,3 +206,6 @@ data/
.netlify .netlify
.ruff_cache .ruff_cache
source_docs/ source_docs/
### Golang ###
/vendor/

View file

@ -9,6 +9,8 @@ lifecycle/ @goauthentik/backend
schemas/ @goauthentik/backend schemas/ @goauthentik/backend
scripts/ @goauthentik/backend scripts/ @goauthentik/backend
tests/ @goauthentik/backend tests/ @goauthentik/backend
pyproject.toml @goauthentik/backend
poetry.lock @goauthentik/backend
# Infrastructure # Infrastructure
.github/ @goauthentik/infrastructure .github/ @goauthentik/infrastructure
Dockerfile @goauthentik/infrastructure Dockerfile @goauthentik/infrastructure
@ -17,6 +19,7 @@ Dockerfile @goauthentik/infrastructure
docker-compose.yml @goauthentik/infrastructure docker-compose.yml @goauthentik/infrastructure
# Web # Web
web/ @goauthentik/frontend web/ @goauthentik/frontend
tests/wdio/ @goauthentik/frontend
# Docs & Website # Docs & Website
website/ @goauthentik/docs website/ @goauthentik/docs
# Security # Security

View file

@ -1,5 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build website # Stage 1: Build website
FROM --platform=${BUILDPLATFORM} docker.io/node:20 as website-builder FROM --platform=${BUILDPLATFORM} docker.io/node:21 as website-builder
ENV NODE_ENV=production ENV NODE_ENV=production
@ -7,7 +9,7 @@ WORKDIR /work/website
RUN --mount=type=bind,target=/work/website/package.json,src=./website/package.json \ RUN --mount=type=bind,target=/work/website/package.json,src=./website/package.json \
--mount=type=bind,target=/work/website/package-lock.json,src=./website/package-lock.json \ --mount=type=bind,target=/work/website/package-lock.json,src=./website/package-lock.json \
--mount=type=cache,target=/root/.npm \ --mount=type=cache,id=npm-website,sharing=shared,target=/root/.npm \
npm ci --include=dev npm ci --include=dev
COPY ./website /work/website/ COPY ./website /work/website/
@ -17,7 +19,7 @@ COPY ./SECURITY.md /work/
RUN npm run build-docs-only RUN npm run build-docs-only
# Stage 2: Build webui # Stage 2: Build webui
FROM --platform=${BUILDPLATFORM} docker.io/node:20 as web-builder FROM --platform=${BUILDPLATFORM} docker.io/node:21 as web-builder
ENV NODE_ENV=production ENV NODE_ENV=production
@ -25,7 +27,7 @@ WORKDIR /work/web
RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \ RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \ --mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \
--mount=type=cache,target=/root/.npm \ --mount=type=cache,id=npm-web,sharing=shared,target=/root/.npm \
npm ci --include=dev npm ci --include=dev
COPY ./web /work/web/ COPY ./web /work/web/
@ -35,7 +37,14 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
RUN npm run build RUN npm run build
# Stage 3: Build go proxy # Stage 3: Build go proxy
FROM docker.io/golang:1.21.1-bookworm AS go-builder FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS go-builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io WORKDIR /go/src/goauthentik.io
@ -55,12 +64,12 @@ COPY ./go.sum /go/src/goauthentik.io/go.sum
ENV CGO_ENABLED=0 ENV CGO_ENABLED=0
RUN --mount=type=cache,target=/go/pkg/mod \ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \
go build -o /go/authentik ./cmd/server GOARM="${TARGETVARIANT#v}" go build -o /go/authentik ./cmd/server
# Stage 4: MaxMind GeoIP # Stage 4: MaxMind GeoIP
FROM ghcr.io/maxmind/geoipupdate:v6.0 as geoip FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v6.0 as geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City" ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City"
ENV GEOIPUPDATE_VERBOSE="true" ENV GEOIPUPDATE_VERBOSE="true"
@ -82,7 +91,9 @@ ENV VENV_PATH="/ak-root/venv" \
POETRY_VIRTUALENVS_CREATE=false \ POETRY_VIRTUALENVS_CREATE=false \
PATH="/ak-root/venv/bin:$PATH" PATH="/ak-root/venv/bin:$PATH"
RUN --mount=type=cache,target=/var/cache/apt \ RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \
apt-get update && \ apt-get update && \
# Required for installing pip packages # Required for installing pip packages
apt-get install -y --no-install-recommends build-essential pkg-config libxmlsec1-dev zlib1g-dev libpq-dev apt-get install -y --no-install-recommends build-essential pkg-config libxmlsec1-dev zlib1g-dev libpq-dev

View file

@ -28,10 +28,13 @@ CODESPELL_ARGS = -D - -D .github/codespell-dictionary.txt \
all: lint-fix lint test gen web ## Lint, build, and test everything all: lint-fix lint test gen web ## Lint, build, and test everything
HELP_WIDTH := $(shell grep -h '^[a-z][^ ]*:.*\#\#' $(MAKEFILE_LIST) 2>/dev/null | \
cut -d':' -f1 | awk '{printf "%d\n", length}' | sort -rn | head -1)
help: ## Show this help help: ## Show this help
@echo "\nSpecify a command. The choices are:\n" @echo "\nSpecify a command. The choices are:\n"
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ @grep -Eh '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[0;36m%-24s\033[m %s\n", $$1, $$2}' | \ awk 'BEGIN {FS = ":.*?## "}; {printf " \033[0;36m%-$(HELP_WIDTH)s \033[m %s\n", $$1, $$2}' | \
sort sort
@echo "" @echo ""
@ -53,14 +56,15 @@ test: ## Run the server tests and produce a coverage report (locally)
coverage report coverage report
lint-fix: ## Lint and automatically fix errors in the python source code. Reports spelling errors. lint-fix: ## Lint and automatically fix errors in the python source code. Reports spelling errors.
isort authentik $(PY_SOURCES) isort $(PY_SOURCES)
black authentik $(PY_SOURCES) black $(PY_SOURCES)
ruff authentik $(PY_SOURCES) ruff $(PY_SOURCES)
codespell -w $(CODESPELL_ARGS) codespell -w $(CODESPELL_ARGS)
lint: ## Lint the python and golang sources lint: ## Lint the python and golang sources
pylint $(PY_SOURCES)
bandit -r $(PY_SOURCES) -x node_modules bandit -r $(PY_SOURCES) -x node_modules
./web/node_modules/.bin/pyright $(PY_SOURCES)
pylint $(PY_SOURCES)
golangci-lint run -v golangci-lint run -v
migrate: ## Run the Authentik Django server's migrations migrate: ## Run the Authentik Django server's migrations
@ -75,10 +79,10 @@ install: web-install website-install ## Install all requires dependencies for `
poetry install poetry install
dev-drop-db: dev-drop-db:
echo dropdb -U ${pg_user} -h ${pg_host} ${pg_name} dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
# Also remove the test-db if it exists # Also remove the test-db if it exists
dropdb -U ${pg_user} -h ${pg_host} test_${pg_name} || true dropdb -U ${pg_user} -h ${pg_host} test_${pg_name} || true
echo redis-cli -n 0 flushall redis-cli -n 0 flushall
dev-create-db: dev-create-db:
createdb -U ${pg_user} -h ${pg_host} ${pg_name} createdb -U ${pg_user} -h ${pg_host} ${pg_name}

View file

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

View file

@ -1,7 +1,7 @@
"""Meta API""" """Meta API"""
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
from rest_framework.fields import CharField from rest_framework.fields import CharField
from rest_framework.permissions import IsAdminUser from rest_framework.permissions import IsAuthenticated
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.viewsets import ViewSet from rest_framework.viewsets import ViewSet
@ -21,7 +21,7 @@ class AppSerializer(PassiveSerializer):
class AppsViewSet(ViewSet): class AppsViewSet(ViewSet):
"""Read-only view list all installed apps""" """Read-only view list all installed apps"""
permission_classes = [IsAdminUser] permission_classes = [IsAuthenticated]
@extend_schema(responses={200: AppSerializer(many=True)}) @extend_schema(responses={200: AppSerializer(many=True)})
def list(self, request: Request) -> Response: def list(self, request: Request) -> Response:
@ -35,7 +35,7 @@ class AppsViewSet(ViewSet):
class ModelViewSet(ViewSet): class ModelViewSet(ViewSet):
"""Read-only view list all installed models""" """Read-only view list all installed models"""
permission_classes = [IsAdminUser] permission_classes = [IsAuthenticated]
@extend_schema(responses={200: AppSerializer(many=True)}) @extend_schema(responses={200: AppSerializer(many=True)})
def list(self, request: Request) -> Response: def list(self, request: Request) -> Response:

View file

@ -5,7 +5,7 @@ from django.db.models.functions import ExtractHour
from drf_spectacular.utils import extend_schema, extend_schema_field from drf_spectacular.utils import extend_schema, extend_schema_field
from guardian.shortcuts import get_objects_for_user from guardian.shortcuts import get_objects_for_user
from rest_framework.fields import IntegerField, SerializerMethodField from rest_framework.fields import IntegerField, SerializerMethodField
from rest_framework.permissions import IsAdminUser from rest_framework.permissions import IsAuthenticated
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.views import APIView from rest_framework.views import APIView
@ -68,7 +68,7 @@ class LoginMetricsSerializer(PassiveSerializer):
class AdministrationMetricsViewSet(APIView): class AdministrationMetricsViewSet(APIView):
"""Login Metrics per 1h""" """Login Metrics per 1h"""
permission_classes = [IsAdminUser] permission_classes = [IsAuthenticated]
@extend_schema(responses={200: LoginMetricsSerializer(many=False)}) @extend_schema(responses={200: LoginMetricsSerializer(many=False)})
def get(self, request: Request) -> Response: def get(self, request: Request) -> Response:

View file

@ -8,7 +8,6 @@ from django.utils.timezone import now
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
from gunicorn import version_info as gunicorn_version from gunicorn import version_info as gunicorn_version
from rest_framework.fields import SerializerMethodField from rest_framework.fields import SerializerMethodField
from rest_framework.permissions import IsAdminUser
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.views import APIView from rest_framework.views import APIView
@ -17,6 +16,7 @@ from authentik.core.api.utils import PassiveSerializer
from authentik.lib.utils.reflection import get_env from authentik.lib.utils.reflection import get_env
from authentik.outposts.apps import MANAGED_OUTPOST from authentik.outposts.apps import MANAGED_OUTPOST
from authentik.outposts.models import Outpost from authentik.outposts.models import Outpost
from authentik.rbac.permissions import HasPermission
class RuntimeDict(TypedDict): class RuntimeDict(TypedDict):
@ -88,7 +88,7 @@ class SystemSerializer(PassiveSerializer):
class SystemView(APIView): class SystemView(APIView):
"""Get system information.""" """Get system information."""
permission_classes = [IsAdminUser] permission_classes = [HasPermission("authentik_rbac.view_system_info")]
pagination_class = None pagination_class = None
filter_backends = [] filter_backends = []
serializer_class = SystemSerializer serializer_class = SystemSerializer

View file

@ -14,14 +14,15 @@ from rest_framework.fields import (
ListField, ListField,
SerializerMethodField, SerializerMethodField,
) )
from rest_framework.permissions import IsAdminUser
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.viewsets import ViewSet from rest_framework.viewsets import ViewSet
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.api.decorators import permission_required
from authentik.core.api.utils import PassiveSerializer from authentik.core.api.utils import PassiveSerializer
from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus
from authentik.rbac.permissions import HasPermission
LOGGER = get_logger() LOGGER = get_logger()
@ -63,7 +64,7 @@ class TaskSerializer(PassiveSerializer):
class TaskViewSet(ViewSet): class TaskViewSet(ViewSet):
"""Read-only view set that returns all background tasks""" """Read-only view set that returns all background tasks"""
permission_classes = [IsAdminUser] permission_classes = [HasPermission("authentik_rbac.view_system_tasks")]
serializer_class = TaskSerializer serializer_class = TaskSerializer
@extend_schema( @extend_schema(
@ -93,6 +94,7 @@ class TaskViewSet(ViewSet):
tasks = sorted(TaskInfo.all().values(), key=lambda task: task.task_name) tasks = sorted(TaskInfo.all().values(), key=lambda task: task.task_name)
return Response(TaskSerializer(tasks, many=True).data) return Response(TaskSerializer(tasks, many=True).data)
@permission_required(None, ["authentik_rbac.run_system_tasks"])
@extend_schema( @extend_schema(
request=OpenApiTypes.NONE, request=OpenApiTypes.NONE,
responses={ responses={

View file

@ -2,18 +2,18 @@
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 rest_framework.fields import IntegerField from rest_framework.fields import IntegerField
from rest_framework.permissions import IsAdminUser
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.views import APIView from rest_framework.views import APIView
from authentik.rbac.permissions import HasPermission
from authentik.root.celery import CELERY_APP from authentik.root.celery import CELERY_APP
class WorkerView(APIView): class WorkerView(APIView):
"""Get currently connected worker count.""" """Get currently connected worker count."""
permission_classes = [IsAdminUser] permission_classes = [HasPermission("authentik_rbac.view_system_info")]
@extend_schema(responses=inline_serializer("Workers", fields={"count": IntegerField()})) @extend_schema(responses=inline_serializer("Workers", fields={"count": IntegerField()}))
def get(self, request: Request) -> Response: def get(self, request: Request) -> Response:

View file

@ -7,9 +7,9 @@ from rest_framework.authentication import get_authorization_header
from rest_framework.filters import BaseFilterBackend from rest_framework.filters import BaseFilterBackend
from rest_framework.permissions import BasePermission from rest_framework.permissions import BasePermission
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework_guardian.filters import ObjectPermissionsFilter
from authentik.api.authentication import validate_auth from authentik.api.authentication import validate_auth
from authentik.rbac.filters import ObjectFilter
class OwnerFilter(BaseFilterBackend): class OwnerFilter(BaseFilterBackend):
@ -26,14 +26,14 @@ class OwnerFilter(BaseFilterBackend):
class SecretKeyFilter(DjangoFilterBackend): class SecretKeyFilter(DjangoFilterBackend):
"""Allow access to all objects when authenticated with secret key as token. """Allow access to all objects when authenticated with secret key as token.
Replaces both DjangoFilterBackend and ObjectPermissionsFilter""" Replaces both DjangoFilterBackend and ObjectFilter"""
def filter_queryset(self, request: Request, queryset: QuerySet, view) -> QuerySet: def filter_queryset(self, request: Request, queryset: QuerySet, view) -> QuerySet:
auth_header = get_authorization_header(request) auth_header = get_authorization_header(request)
token = validate_auth(auth_header) token = validate_auth(auth_header)
if token and token == settings.SECRET_KEY: if token and token == settings.SECRET_KEY:
return queryset return queryset
queryset = ObjectPermissionsFilter().filter_queryset(request, queryset, view) queryset = ObjectFilter().filter_queryset(request, queryset, view)
return super().filter_queryset(request, queryset, view) return super().filter_queryset(request, queryset, view)

View file

@ -10,7 +10,7 @@ from structlog.stdlib import get_logger
LOGGER = get_logger() LOGGER = get_logger()
def permission_required(perm: Optional[str] = None, other_perms: Optional[list[str]] = None): def permission_required(obj_perm: Optional[str] = None, global_perms: Optional[list[str]] = None):
"""Check permissions for a single custom action""" """Check permissions for a single custom action"""
def wrapper_outter(func: Callable): def wrapper_outter(func: Callable):
@ -18,15 +18,17 @@ def permission_required(perm: Optional[str] = None, other_perms: Optional[list[s
@wraps(func) @wraps(func)
def wrapper(self: ModelViewSet, request: Request, *args, **kwargs) -> Response: def wrapper(self: ModelViewSet, request: Request, *args, **kwargs) -> Response:
if perm: if obj_perm:
obj = self.get_object() obj = self.get_object()
if not request.user.has_perm(perm, obj): if not request.user.has_perm(obj_perm, obj):
LOGGER.debug("denying access for object", user=request.user, perm=perm, obj=obj) LOGGER.debug(
"denying access for object", user=request.user, perm=obj_perm, obj=obj
)
return self.permission_denied(request) return self.permission_denied(request)
if other_perms: if global_perms:
for other_perm in other_perms: for other_perm in global_perms:
if not request.user.has_perm(other_perm): if not request.user.has_perm(other_perm):
LOGGER.debug("denying access for other", user=request.user, perm=perm) LOGGER.debug("denying access for other", user=request.user, perm=other_perm)
return self.permission_denied(request) return self.permission_denied(request)
return func(self, request, *args, **kwargs) return func(self, request, *args, **kwargs)

View file

@ -77,3 +77,10 @@ class Pagination(pagination.PageNumberPagination):
}, },
"required": ["pagination", "results"], "required": ["pagination", "results"],
} }
class SmallerPagination(Pagination):
"""Smaller pagination for objects which might require a lot of queries
to retrieve all data for."""
max_page_size = 10

View file

@ -16,6 +16,7 @@ def viewset_tester_factory(test_viewset: type[ModelViewSet]) -> Callable:
def tester(self: TestModelViewSets): def tester(self: TestModelViewSets):
self.assertIsNotNone(getattr(test_viewset, "search_fields", None)) self.assertIsNotNone(getattr(test_viewset, "search_fields", None))
self.assertIsNotNone(getattr(test_viewset, "ordering", None))
filterset_class = getattr(test_viewset, "filterset_class", None) filterset_class = getattr(test_viewset, "filterset_class", None)
if not filterset_class: if not filterset_class:
self.assertIsNotNone(getattr(test_viewset, "filterset_fields", None)) self.assertIsNotNone(getattr(test_viewset, "filterset_fields", None))

View file

@ -21,7 +21,9 @@ _other_urls = []
for _authentik_app in get_apps(): for _authentik_app in get_apps():
try: try:
api_urls = import_module(f"{_authentik_app.name}.urls") api_urls = import_module(f"{_authentik_app.name}.urls")
except (ModuleNotFoundError, ImportError) as exc: except ModuleNotFoundError:
continue
except ImportError as exc:
LOGGER.warning("Could not import app's URLs", app_name=_authentik_app.name, exc=exc) LOGGER.warning("Could not import app's URLs", app_name=_authentik_app.name, exc=exc)
continue continue
if not hasattr(api_urls, "api_urlpatterns"): if not hasattr(api_urls, "api_urlpatterns"):

View file

@ -4,7 +4,6 @@ from drf_spectacular.utils import extend_schema, inline_serializer
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, DateTimeField, JSONField from rest_framework.fields import CharField, DateTimeField, JSONField
from rest_framework.permissions import IsAdminUser
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 ListSerializer, ModelSerializer from rest_framework.serializers import ListSerializer, ModelSerializer
@ -87,11 +86,11 @@ class BlueprintInstanceSerializer(ModelSerializer):
class BlueprintInstanceViewSet(UsedByMixin, ModelViewSet): class BlueprintInstanceViewSet(UsedByMixin, ModelViewSet):
"""Blueprint instances""" """Blueprint instances"""
permission_classes = [IsAdminUser]
serializer_class = BlueprintInstanceSerializer serializer_class = BlueprintInstanceSerializer
queryset = BlueprintInstance.objects.all() queryset = BlueprintInstance.objects.all()
search_fields = ["name", "path"] search_fields = ["name", "path"]
filterset_fields = ["name", "path"] filterset_fields = ["name", "path"]
ordering = ["name"]
@extend_schema( @extend_schema(
responses={ responses={

View file

@ -40,7 +40,7 @@ class ManagedAppConfig(AppConfig):
meth() meth()
self._logger.debug("Successfully reconciled", name=name) self._logger.debug("Successfully reconciled", name=name)
except (DatabaseError, ProgrammingError, InternalError) as exc: except (DatabaseError, ProgrammingError, InternalError) as exc:
self._logger.debug("Failed to run reconcile", name=name, exc=exc) self._logger.warning("Failed to run reconcile", name=name, exc=exc)
class AuthentikBlueprintsConfig(ManagedAppConfig): class AuthentikBlueprintsConfig(ManagedAppConfig):

View file

@ -6,6 +6,7 @@ from django.test import TestCase
from authentik.blueprints.v1.importer import is_model_allowed from authentik.blueprints.v1.importer import is_model_allowed
from authentik.lib.models import SerializerModel from authentik.lib.models import SerializerModel
from authentik.providers.oauth2.models import RefreshToken
class TestModels(TestCase): class TestModels(TestCase):
@ -21,6 +22,9 @@ def serializer_tester_factory(test_model: Type[SerializerModel]) -> Callable:
model_class = test_model() model_class = test_model()
self.assertTrue(isinstance(model_class, SerializerModel)) self.assertTrue(isinstance(model_class, SerializerModel))
self.assertIsNotNone(model_class.serializer) self.assertIsNotNone(model_class.serializer)
if model_class.serializer.Meta().model == RefreshToken:
return
self.assertEqual(model_class.serializer.Meta().model, test_model)
return tester return tester

View file

@ -584,12 +584,17 @@ class EntryInvalidError(SentryIgnoredException):
entry_model: Optional[str] entry_model: Optional[str]
entry_id: Optional[str] entry_id: Optional[str]
validation_error: Optional[ValidationError] validation_error: Optional[ValidationError]
serializer: Optional[Serializer] = None
def __init__(self, *args: object, validation_error: Optional[ValidationError] = None) -> None: def __init__(
self, *args: object, validation_error: Optional[ValidationError] = None, **kwargs
) -> None:
super().__init__(*args) super().__init__(*args)
self.entry_model = None self.entry_model = None
self.entry_id = None self.entry_id = None
self.validation_error = validation_error self.validation_error = validation_error
for key, value in kwargs.items():
setattr(self, key, value)
@staticmethod @staticmethod
def from_entry( def from_entry(

View file

@ -35,25 +35,28 @@ from authentik.core.models import (
Source, Source,
UserSourceConnection, UserSourceConnection,
) )
from authentik.enterprise.models import LicenseUsage
from authentik.events.utils import cleanse_dict from authentik.events.utils import cleanse_dict
from authentik.flows.models import FlowToken, Stage from authentik.flows.models import FlowToken, Stage
from authentik.lib.models import SerializerModel from authentik.lib.models import SerializerModel
from authentik.lib.sentry import SentryIgnoredException from authentik.lib.sentry import SentryIgnoredException
from authentik.outposts.models import OutpostServiceConnection from authentik.outposts.models import OutpostServiceConnection
from authentik.policies.models import Policy, PolicyBindingModel from authentik.policies.models import Policy, PolicyBindingModel
from authentik.providers.scim.models import SCIMGroup, SCIMUser
# Context set when the serializer is created in a blueprint context # Context set when the serializer is created in a blueprint context
# Update website/developer-docs/blueprints/v1/models.md when used # Update website/developer-docs/blueprints/v1/models.md when used
SERIALIZER_CONTEXT_BLUEPRINT = "blueprint_entry" SERIALIZER_CONTEXT_BLUEPRINT = "blueprint_entry"
def is_model_allowed(model: type[Model]) -> bool: def excluded_models() -> list[type[Model]]:
"""Check if model is allowed""" """Return a list of all excluded models that shouldn't be exposed via API
or other means (internal only, base classes, non-used objects, etc)"""
# pylint: disable=imported-auth-user # pylint: disable=imported-auth-user
from django.contrib.auth.models import Group as DjangoGroup from django.contrib.auth.models import Group as DjangoGroup
from django.contrib.auth.models import User as DjangoUser from django.contrib.auth.models import User as DjangoUser
excluded_models = ( return (
DjangoUser, DjangoUser,
DjangoGroup, DjangoGroup,
# Base classes # Base classes
@ -69,8 +72,15 @@ def is_model_allowed(model: type[Model]) -> bool:
AuthenticatedSession, AuthenticatedSession,
# Classes which are only internally managed # Classes which are only internally managed
FlowToken, FlowToken,
LicenseUsage,
SCIMGroup,
SCIMUser,
) )
return model not in excluded_models and issubclass(model, (SerializerModel, BaseMetaModel))
def is_model_allowed(model: type[Model]) -> bool:
"""Check if model is allowed"""
return model not in excluded_models() and issubclass(model, (SerializerModel, BaseMetaModel))
class DoRollback(SentryIgnoredException): class DoRollback(SentryIgnoredException):
@ -245,7 +255,10 @@ class Importer:
try: try:
full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import)) full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
except ValueError as exc: except ValueError as exc:
raise EntryInvalidError.from_entry(exc, entry) from exc raise EntryInvalidError.from_entry(
exc,
entry,
) from exc
always_merger.merge(full_data, updated_identifiers) always_merger.merge(full_data, updated_identifiers)
serializer_kwargs["data"] = full_data serializer_kwargs["data"] = full_data
@ -262,6 +275,7 @@ class Importer:
f"Serializer errors {serializer.errors}", f"Serializer errors {serializer.errors}",
validation_error=exc, validation_error=exc,
entry=entry, entry=entry,
serializer=serializer,
) from exc ) from exc
return serializer return serializer
@ -290,12 +304,14 @@ class Importer:
) )
return False return False
# Validate each single entry # Validate each single entry
serializer = None
try: try:
serializer = self._validate_single(entry) serializer = self._validate_single(entry)
except EntryInvalidError as exc: except EntryInvalidError as exc:
# For deleting objects we don't need the serializer to be valid # For deleting objects we don't need the serializer to be valid
if entry.get_state(self._import) == BlueprintEntryDesiredState.ABSENT: if entry.get_state(self._import) == BlueprintEntryDesiredState.ABSENT:
continue serializer = exc.serializer
else:
self.logger.warning(f"entry invalid: {exc}", entry=entry, error=exc) self.logger.warning(f"entry invalid: {exc}", entry=entry, error=exc)
if raise_errors: if raise_errors:
raise exc raise exc

View file

@ -75,14 +75,14 @@ class BlueprintEventHandler(FileSystemEventHandler):
return return
if event.is_directory: if event.is_directory:
return return
if isinstance(event, FileCreatedEvent):
LOGGER.debug("new blueprint file created, starting discovery")
blueprints_discovery.delay()
if isinstance(event, FileModifiedEvent):
path = Path(event.src_path)
root = Path(CONFIG.get("blueprints_dir")).absolute() root = Path(CONFIG.get("blueprints_dir")).absolute()
path = Path(event.src_path).absolute()
rel_path = str(path.relative_to(root)) rel_path = str(path.relative_to(root))
for instance in BlueprintInstance.objects.filter(path=rel_path): if isinstance(event, FileCreatedEvent):
LOGGER.debug("new blueprint file created, starting discovery", path=rel_path)
blueprints_discovery.delay(rel_path)
if isinstance(event, FileModifiedEvent):
for instance in BlueprintInstance.objects.filter(path=rel_path, enabled=True):
LOGGER.debug("modified blueprint file, starting apply", instance=instance) LOGGER.debug("modified blueprint file, starting apply", instance=instance)
apply_blueprint.delay(instance.pk.hex) apply_blueprint.delay(instance.pk.hex)
@ -98,39 +98,32 @@ def blueprints_find_dict():
return blueprints return blueprints
def blueprints_find(): def blueprints_find() -> list[BlueprintFile]:
"""Find blueprints and return valid ones""" """Find blueprints and return valid ones"""
blueprints = [] blueprints = []
root = Path(CONFIG.get("blueprints_dir")) root = Path(CONFIG.get("blueprints_dir"))
for path in root.rglob("**/*.yaml"): for path in root.rglob("**/*.yaml"):
rel_path = path.relative_to(root)
# Check if any part in the path starts with a dot and assume a hidden file # Check if any part in the path starts with a dot and assume a hidden file
if any(part for part in path.parts if part.startswith(".")): if any(part for part in path.parts if part.startswith(".")):
continue continue
LOGGER.debug("found blueprint", path=str(path))
with open(path, "r", encoding="utf-8") as blueprint_file: with open(path, "r", encoding="utf-8") as blueprint_file:
try: try:
raw_blueprint = load(blueprint_file.read(), BlueprintLoader) raw_blueprint = load(blueprint_file.read(), BlueprintLoader)
except YAMLError as exc: except YAMLError as exc:
raw_blueprint = None raw_blueprint = None
LOGGER.warning("failed to parse blueprint", exc=exc, path=str(path)) LOGGER.warning("failed to parse blueprint", exc=exc, path=str(rel_path))
if not raw_blueprint: if not raw_blueprint:
continue continue
metadata = raw_blueprint.get("metadata", None) metadata = raw_blueprint.get("metadata", None)
version = raw_blueprint.get("version", 1) version = raw_blueprint.get("version", 1)
if version != 1: if version != 1:
LOGGER.warning("invalid blueprint version", version=version, path=str(path)) LOGGER.warning("invalid blueprint version", version=version, path=str(rel_path))
continue continue
file_hash = sha512(path.read_bytes()).hexdigest() file_hash = sha512(path.read_bytes()).hexdigest()
blueprint = BlueprintFile( blueprint = BlueprintFile(str(rel_path), version, file_hash, int(path.stat().st_mtime))
str(path.relative_to(root)), version, file_hash, int(path.stat().st_mtime)
)
blueprint.meta = from_dict(BlueprintMetadata, metadata) if metadata else None blueprint.meta = from_dict(BlueprintMetadata, metadata) if metadata else None
blueprints.append(blueprint) blueprints.append(blueprint)
LOGGER.debug(
"parsed & loaded blueprint",
hash=file_hash,
path=str(path),
)
return blueprints return blueprints
@ -138,10 +131,12 @@ def blueprints_find():
throws=(DatabaseError, ProgrammingError, InternalError), base=MonitoredTask, bind=True throws=(DatabaseError, ProgrammingError, InternalError), base=MonitoredTask, bind=True
) )
@prefill_task @prefill_task
def blueprints_discovery(self: MonitoredTask): def blueprints_discovery(self: MonitoredTask, path: Optional[str] = None):
"""Find blueprints and check if they need to be created in the database""" """Find blueprints and check if they need to be created in the database"""
count = 0 count = 0
for blueprint in blueprints_find(): for blueprint in blueprints_find():
if path and blueprint.path != path:
continue
check_blueprint_v1_file(blueprint) check_blueprint_v1_file(blueprint)
count += 1 count += 1
self.set_status( self.set_status(
@ -171,7 +166,11 @@ def check_blueprint_v1_file(blueprint: BlueprintFile):
metadata={}, metadata={},
) )
instance.save() instance.save()
LOGGER.info(
"Creating new blueprint instance from file", instance=instance, path=instance.path
)
if instance.last_applied_hash != blueprint.hash: if instance.last_applied_hash != blueprint.hash:
LOGGER.info("Applying blueprint due to changed file", instance=instance, path=instance.path)
apply_blueprint.delay(str(instance.pk)) apply_blueprint.delay(str(instance.pk))

View file

@ -17,7 +17,6 @@ from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from structlog.testing import capture_logs from structlog.testing import capture_logs
@ -38,6 +37,7 @@ from authentik.lib.utils.file import (
from authentik.policies.api.exec import PolicyTestResultSerializer from authentik.policies.api.exec import PolicyTestResultSerializer
from authentik.policies.engine import PolicyEngine from authentik.policies.engine import PolicyEngine
from authentik.policies.types import PolicyResult from authentik.policies.types import PolicyResult
from authentik.rbac.filters import ObjectFilter
LOGGER = get_logger() LOGGER = get_logger()
@ -98,6 +98,7 @@ class ApplicationSerializer(ModelSerializer):
class ApplicationViewSet(UsedByMixin, ModelViewSet): class ApplicationViewSet(UsedByMixin, ModelViewSet):
"""Application Viewset""" """Application Viewset"""
# pylint: disable=no-member
queryset = Application.objects.all().prefetch_related("provider") queryset = Application.objects.all().prefetch_related("provider")
serializer_class = ApplicationSerializer serializer_class = ApplicationSerializer
search_fields = [ search_fields = [
@ -122,7 +123,7 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
def _filter_queryset_for_list(self, queryset: QuerySet) -> QuerySet: def _filter_queryset_for_list(self, queryset: QuerySet) -> QuerySet:
"""Custom filter_queryset method which ignores guardian, but still supports sorting""" """Custom filter_queryset method which ignores guardian, but still supports sorting"""
for backend in list(self.filter_backends): for backend in list(self.filter_backends):
if backend == ObjectPermissionsFilter: if backend == ObjectFilter:
continue continue
queryset = backend().filter_queryset(self.request, queryset, self) queryset = backend().filter_queryset(self.request, queryset, self)
return queryset return queryset

View file

@ -2,7 +2,6 @@
from json import loads from json import loads
from typing import Optional from typing import Optional
from django.db.models.query import QuerySet
from django.http import Http404 from django.http import Http404
from django_filters.filters import CharFilter, ModelMultipleChoiceFilter from django_filters.filters import CharFilter, ModelMultipleChoiceFilter
from django_filters.filterset import FilterSet from django_filters.filterset import FilterSet
@ -14,12 +13,12 @@ from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import ListSerializer, ModelSerializer, ValidationError from rest_framework.serializers import ListSerializer, ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
from authentik.api.decorators import permission_required from authentik.api.decorators import permission_required
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer, is_dict from authentik.core.api.utils import PassiveSerializer, is_dict
from authentik.core.models import Group, User from authentik.core.models import Group, User
from authentik.rbac.api.roles import RoleSerializer
class GroupMemberSerializer(ModelSerializer): class GroupMemberSerializer(ModelSerializer):
@ -49,6 +48,12 @@ class GroupSerializer(ModelSerializer):
users_obj = ListSerializer( users_obj = ListSerializer(
child=GroupMemberSerializer(), read_only=True, source="users", required=False child=GroupMemberSerializer(), read_only=True, source="users", required=False
) )
roles_obj = ListSerializer(
child=RoleSerializer(),
read_only=True,
source="roles",
required=False,
)
parent_name = CharField(source="parent.name", read_only=True, allow_null=True) parent_name = CharField(source="parent.name", read_only=True, allow_null=True)
num_pk = IntegerField(read_only=True) num_pk = IntegerField(read_only=True)
@ -71,8 +76,10 @@ class GroupSerializer(ModelSerializer):
"parent", "parent",
"parent_name", "parent_name",
"users", "users",
"attributes",
"users_obj", "users_obj",
"attributes",
"roles",
"roles_obj",
] ]
extra_kwargs = { extra_kwargs = {
"users": { "users": {
@ -132,25 +139,13 @@ class UserAccountSerializer(PassiveSerializer):
class GroupViewSet(UsedByMixin, ModelViewSet): class GroupViewSet(UsedByMixin, ModelViewSet):
"""Group Viewset""" """Group Viewset"""
# pylint: disable=no-member
queryset = Group.objects.all().select_related("parent").prefetch_related("users") queryset = Group.objects.all().select_related("parent").prefetch_related("users")
serializer_class = GroupSerializer serializer_class = GroupSerializer
search_fields = ["name", "is_superuser"] search_fields = ["name", "is_superuser"]
filterset_class = GroupFilter filterset_class = GroupFilter
ordering = ["name"] ordering = ["name"]
def _filter_queryset_for_list(self, queryset: QuerySet) -> QuerySet:
"""Custom filter_queryset method which ignores guardian, but still supports sorting"""
for backend in list(self.filter_backends):
if backend == ObjectPermissionsFilter:
continue
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
def filter_queryset(self, queryset):
if self.request.user.has_perm("authentik_core.view_group"):
return self._filter_queryset_for_list(queryset)
return super().filter_queryset(queryset)
@permission_required(None, ["authentik_core.add_user"]) @permission_required(None, ["authentik_core.add_user"])
@extend_schema( @extend_schema(
request=UserAccountSerializer, request=UserAccountSerializer,

View file

@ -38,7 +38,7 @@ class SourceSerializer(ModelSerializer, MetaNameSerializer):
managed = ReadOnlyField() managed = ReadOnlyField()
component = SerializerMethodField() component = SerializerMethodField()
icon = ReadOnlyField(source="get_icon") icon = ReadOnlyField(source="icon_url")
def get_component(self, obj: Source) -> str: def get_component(self, obj: Source) -> str:
"""Get object component so that we know how to edit the object""" """Get object component so that we know how to edit the object"""

View file

@ -119,6 +119,7 @@ class TransactionApplicationResponseSerializer(PassiveSerializer):
class TransactionalApplicationView(APIView): class TransactionalApplicationView(APIView):
"""Create provider and application and attach them in a single transaction""" """Create provider and application and attach them in a single transaction"""
# TODO: Migrate to a more specific permission
permission_classes = [IsAdminUser] permission_classes = [IsAdminUser]
@extend_schema( @extend_schema(

View file

@ -73,6 +73,11 @@ class UsedByMixin:
# but so we only apply them once, have a simple flag for the first object # but so we only apply them once, have a simple flag for the first object
first_object = True first_object = True
# TODO: This will only return the used-by references that the user can see
# Either we have to leak model information here to not make the list
# useless if the user doesn't have all permissions, or we need to double
# query and check if there is a difference between modes the user can see
# and can't see and add a warning
for obj in get_objects_for_user( for obj in get_objects_for_user(
request.user, f"{app}.view_{model_name}", manager request.user, f"{app}.view_{model_name}", manager
).all(): ).all():

View file

@ -7,7 +7,6 @@ from django.contrib.auth import update_session_auth_hash
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
from django.db.models.functions import ExtractHour from django.db.models.functions import ExtractHour
from django.db.models.query import QuerySet
from django.db.transaction import atomic from django.db.transaction import atomic
from django.db.utils import IntegrityError from django.db.utils import IntegrityError
from django.urls import reverse_lazy from django.urls import reverse_lazy
@ -52,7 +51,6 @@ from rest_framework.serializers import (
) )
from rest_framework.validators import UniqueValidator from rest_framework.validators import UniqueValidator
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.admin.api.metrics import CoordinateSerializer from authentik.admin.api.metrics import CoordinateSerializer
@ -173,6 +171,11 @@ class UserSerializer(ModelSerializer):
raise ValidationError("Setting a user to internal service account is not allowed.") raise ValidationError("Setting a user to internal service account is not allowed.")
return user_type return user_type
def validate(self, attrs: dict) -> dict:
if self.instance and self.instance.type == UserTypes.INTERNAL_SERVICE_ACCOUNT:
raise ValidationError("Can't modify internal service account users")
return super().validate(attrs)
class Meta: class Meta:
model = User model = User
fields = [ fields = [
@ -190,6 +193,7 @@ class UserSerializer(ModelSerializer):
"uid", "uid",
"path", "path",
"type", "type",
"uuid",
] ]
extra_kwargs = { extra_kwargs = {
"name": {"allow_blank": True}, "name": {"allow_blank": True},
@ -204,6 +208,7 @@ class UserSelfSerializer(ModelSerializer):
groups = SerializerMethodField() groups = SerializerMethodField()
uid = CharField(read_only=True) uid = CharField(read_only=True)
settings = SerializerMethodField() settings = SerializerMethodField()
system_permissions = SerializerMethodField()
@extend_schema_field( @extend_schema_field(
ListSerializer( ListSerializer(
@ -225,6 +230,14 @@ class UserSelfSerializer(ModelSerializer):
"""Get user settings with tenant and group settings applied""" """Get user settings with tenant and group settings applied"""
return user.group_attributes(self._context["request"]).get("settings", {}) return user.group_attributes(self._context["request"]).get("settings", {})
def get_system_permissions(self, user: User) -> list[str]:
"""Get all system permissions assigned to the user"""
return list(
user.user_permissions.filter(
content_type__app_label="authentik_rbac", content_type__model="systempermission"
).values_list("codename", flat=True)
)
class Meta: class Meta:
model = User model = User
fields = [ fields = [
@ -239,6 +252,7 @@ class UserSelfSerializer(ModelSerializer):
"uid", "uid",
"settings", "settings",
"type", "type",
"system_permissions",
] ]
extra_kwargs = { extra_kwargs = {
"is_active": {"read_only": True}, "is_active": {"read_only": True},
@ -653,19 +667,6 @@ class UserViewSet(UsedByMixin, ModelViewSet):
return Response(status=204) return Response(status=204)
def _filter_queryset_for_list(self, queryset: QuerySet) -> QuerySet:
"""Custom filter_queryset method which ignores guardian, but still supports sorting"""
for backend in list(self.filter_backends):
if backend == ObjectPermissionsFilter:
continue
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
def filter_queryset(self, queryset):
if self.request.user.has_perm("authentik_core.view_user"):
return self._filter_queryset_for_list(queryset)
return super().filter_queryset(queryset)
@extend_schema( @extend_schema(
responses={ responses={
200: inline_serializer( 200: inline_serializer(

View file

@ -44,6 +44,7 @@ class PropertyMappingEvaluator(BaseEvaluator):
if request: if request:
req.http_request = request req.http_request = request
self._context["request"] = req self._context["request"] = req
req.context.update(**kwargs)
self._context.update(**kwargs) self._context.update(**kwargs)
self.dry_run = dry_run self.dry_run = dry_run

View file

@ -17,9 +17,15 @@ class Command(BaseCommand):
"""Run worker""" """Run worker"""
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument("-b", "--beat", action="store_true") parser.add_argument(
"-b",
"--beat",
action="store_false",
help="When set, this worker will _not_ run Beat (scheduled) tasks",
)
def handle(self, **options): def handle(self, **options):
LOGGER.debug("Celery options", **options)
close_old_connections() close_old_connections()
if CONFIG.get_bool("remote_debug"): if CONFIG.get_bool("remote_debug"):
import debugpy import debugpy

View file

@ -0,0 +1,45 @@
# Generated by Django 4.2.6 on 2023-10-11 13:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0031_alter_user_type"),
("authentik_rbac", "0001_initial"),
]
operations = [
migrations.AlterModelOptions(
name="group",
options={"verbose_name": "Group", "verbose_name_plural": "Groups"},
),
migrations.AlterModelOptions(
name="token",
options={
"permissions": [("view_token_key", "View token's key")],
"verbose_name": "Token",
"verbose_name_plural": "Tokens",
},
),
migrations.AlterModelOptions(
name="user",
options={
"permissions": [
("reset_user_password", "Reset Password"),
("impersonate", "Can impersonate other users"),
("assign_user_permissions", "Can assign permissions to users"),
("unassign_user_permissions", "Can unassign permissions from users"),
],
"verbose_name": "User",
"verbose_name_plural": "Users",
},
),
migrations.AddField(
model_name="group",
name="roles",
field=models.ManyToManyField(
blank=True, related_name="ak_groups", to="authentik_rbac.role"
),
),
]

View file

@ -1,7 +1,7 @@
"""authentik core models""" """authentik core models"""
from datetime import timedelta from datetime import timedelta
from hashlib import sha256 from hashlib import sha256
from typing import Any, Optional from typing import Any, Optional, Self
from uuid import uuid4 from uuid import uuid4
from deepmerge import always_merger from deepmerge import always_merger
@ -88,6 +88,8 @@ class Group(SerializerModel):
default=False, help_text=_("Users added to this group will be superusers.") default=False, help_text=_("Users added to this group will be superusers.")
) )
roles = models.ManyToManyField("authentik_rbac.Role", related_name="ak_groups", blank=True)
parent = models.ForeignKey( parent = models.ForeignKey(
"Group", "Group",
blank=True, blank=True,
@ -115,6 +117,38 @@ class Group(SerializerModel):
"""Recursively check if `user` is member of us, or any parent.""" """Recursively check if `user` is member of us, or any parent."""
return user.all_groups().filter(group_uuid=self.group_uuid).exists() return user.all_groups().filter(group_uuid=self.group_uuid).exists()
def children_recursive(self: Self | QuerySet["Group"]) -> QuerySet["Group"]:
"""Recursively get all groups that have this as parent or are indirectly related"""
direct_groups = []
if isinstance(self, QuerySet):
direct_groups = list(x for x in self.all().values_list("pk", flat=True).iterator())
else:
direct_groups = [self.pk]
if len(direct_groups) < 1:
return Group.objects.none()
query = """
WITH RECURSIVE parents AS (
SELECT authentik_core_group.*, 0 AS relative_depth
FROM authentik_core_group
WHERE authentik_core_group.group_uuid = ANY(%s)
UNION ALL
SELECT authentik_core_group.*, parents.relative_depth + 1
FROM authentik_core_group, parents
WHERE (
authentik_core_group.group_uuid = parents.parent_id and
parents.relative_depth < 20
)
)
SELECT group_uuid
FROM parents
GROUP BY group_uuid, name
ORDER BY name;
"""
group_pks = [group.pk for group in Group.objects.raw(query, [direct_groups]).iterator()]
return Group.objects.filter(pk__in=group_pks)
def __str__(self): def __str__(self):
return f"Group {self.name}" return f"Group {self.name}"
@ -125,6 +159,8 @@ class Group(SerializerModel):
"parent", "parent",
), ),
) )
verbose_name = _("Group")
verbose_name_plural = _("Groups")
class UserManager(DjangoUserManager): class UserManager(DjangoUserManager):
@ -160,33 +196,7 @@ class User(SerializerModel, GuardianUserMixin, AbstractUser):
"""Recursively get all groups this user is a member of. """Recursively get all groups this user is a member of.
At least one query is done to get the direct groups of the user, with groups At least one query is done to get the direct groups of the user, with groups
there are at most 3 queries done""" there are at most 3 queries done"""
direct_groups = list( return Group.children_recursive(self.ak_groups.all())
x for x in self.ak_groups.all().values_list("pk", flat=True).iterator()
)
if len(direct_groups) < 1:
return Group.objects.none()
query = """
WITH RECURSIVE parents AS (
SELECT authentik_core_group.*, 0 AS relative_depth
FROM authentik_core_group
WHERE authentik_core_group.group_uuid = ANY(%s)
UNION ALL
SELECT authentik_core_group.*, parents.relative_depth + 1
FROM authentik_core_group, parents
WHERE (
authentik_core_group.group_uuid = parents.parent_id and
parents.relative_depth < 20
)
)
SELECT group_uuid
FROM parents
GROUP BY group_uuid, name
ORDER BY name;
"""
group_pks = [group.pk for group in Group.objects.raw(query, [direct_groups]).iterator()]
return Group.objects.filter(pk__in=group_pks)
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,
@ -261,12 +271,14 @@ class User(SerializerModel, GuardianUserMixin, AbstractUser):
return get_avatar(self) return get_avatar(self)
class Meta: class Meta:
permissions = (
("reset_user_password", "Reset Password"),
("impersonate", "Can impersonate other users"),
)
verbose_name = _("User") verbose_name = _("User")
verbose_name_plural = _("Users") verbose_name_plural = _("Users")
permissions = [
("reset_user_password", _("Reset Password")),
("impersonate", _("Can impersonate other users")),
("assign_user_permissions", _("Can assign permissions to users")),
("unassign_user_permissions", _("Can unassign permissions from users")),
]
class Provider(SerializerModel): class Provider(SerializerModel):
@ -675,7 +687,7 @@ class Token(SerializerModel, ManagedModel, ExpiringModel):
models.Index(fields=["identifier"]), models.Index(fields=["identifier"]),
models.Index(fields=["key"]), models.Index(fields=["key"]),
] ]
permissions = (("view_token_key", "View token's key"),) permissions = [("view_token_key", _("View token's key"))]
class PropertyMapping(SerializerModel, ManagedModel): class PropertyMapping(SerializerModel, ManagedModel):

View file

@ -7,6 +7,7 @@ from django.db.models import Model
from django.db.models.signals import post_save, pre_delete, pre_save from django.db.models.signals import post_save, pre_delete, pre_save
from django.dispatch import receiver from django.dispatch import receiver
from django.http.request import HttpRequest from django.http.request import HttpRequest
from structlog.stdlib import get_logger
from authentik.core.models import Application, AuthenticatedSession, BackchannelProvider, User from authentik.core.models import Application, AuthenticatedSession, BackchannelProvider, User
@ -15,6 +16,8 @@ password_changed = Signal()
# Arguments: credentials: dict[str, any], request: HttpRequest, stage: Stage # Arguments: credentials: dict[str, any], request: HttpRequest, stage: Stage
login_failed = Signal() login_failed = Signal()
LOGGER = get_logger()
@receiver(post_save, sender=Application) @receiver(post_save, sender=Application)
def post_save_application(sender: type[Model], instance, created: bool, **_): def post_save_application(sender: type[Model], instance, created: bool, **_):

View file

@ -97,6 +97,7 @@ class SourceFlowManager:
if self.request.user.is_authenticated: if self.request.user.is_authenticated:
new_connection.user = self.request.user new_connection.user = self.request.user
new_connection = self.update_connection(new_connection, **kwargs) new_connection = self.update_connection(new_connection, **kwargs)
# pylint: disable=no-member
new_connection.save() new_connection.save()
return Action.LINK, new_connection return Action.LINK, new_connection

View file

@ -13,7 +13,6 @@
{% block head_before %} {% block head_before %}
{% endblock %} {% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/theme-dark.css' %}" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject> <link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
<script src="{% static 'dist/poly.js' %}?version={{ version }}" type="module"></script> <script src="{% static 'dist/poly.js' %}?version={{ version }}" type="module"></script>
<script src="{% static 'dist/standalone/loading/index.js' %}?version={{ version }}" type="module"></script> <script src="{% static 'dist/standalone/loading/index.js' %}?version={{ version }}" type="module"></script>

View file

@ -16,8 +16,8 @@ You've logged out of {{ application }}.
{% block card %} {% block card %}
<form method="POST" class="pf-c-form"> <form method="POST" class="pf-c-form">
<p> <p>
{% blocktrans with application=application.name %} {% blocktrans with application=application.name branding_title=tenant.branding_title %}
You've logged out of {{ application }}. You can go back to the overview to launch another application, or log out of your authentik account. You've logged out of {{ application }}. You can go back to the overview to launch another application, or log out of your {{ branding_title }} account.
{% endblocktrans %} {% endblocktrans %}
</p> </p>

View file

@ -6,6 +6,7 @@
{% block head_before %} {% block head_before %}
<link rel="prefetch" href="/static/dist/assets/images/flow_background.jpg" /> <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' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/theme-dark.css' %}" media="(prefers-color-scheme: dark)">
{% include "base/header_js.html" %} {% include "base/header_js.html" %}
{% endblock %} {% endblock %}

View file

@ -21,10 +21,9 @@ def create_test_flow(
) )
def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User: def create_test_user(name: Optional[str] = None, **kwargs) -> User:
"""Generate a test-admin user""" """Generate a test user"""
uid = generate_id(20) if not name else name uid = generate_id(20) if not name else name
group = Group.objects.create(name=uid, is_superuser=True)
kwargs.setdefault("email", f"{uid}@goauthentik.io") kwargs.setdefault("email", f"{uid}@goauthentik.io")
kwargs.setdefault("username", uid) kwargs.setdefault("username", uid)
user: User = User.objects.create( user: User = User.objects.create(
@ -33,6 +32,13 @@ def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User:
) )
user.set_password(uid) user.set_password(uid)
user.save() user.save()
return user
def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User:
"""Generate a test-admin user"""
user = create_test_user(name, **kwargs)
group = Group.objects.create(name=user.name or name, is_superuser=True)
group.users.add(user) group.users.add(user)
return user return user

View file

@ -1,13 +1,10 @@
"""authentik crypto app config""" """authentik crypto app config"""
from datetime import datetime from datetime import datetime
from typing import TYPE_CHECKING, Optional from typing import Optional
from authentik.blueprints.apps import ManagedAppConfig from authentik.blueprints.apps import ManagedAppConfig
from authentik.lib.generators import generate_id from authentik.lib.generators import generate_id
if TYPE_CHECKING:
from authentik.crypto.models import CertificateKeyPair
MANAGED_KEY = "goauthentik.io/crypto/jwt-managed" MANAGED_KEY = "goauthentik.io/crypto/jwt-managed"
@ -23,33 +20,37 @@ class AuthentikCryptoConfig(ManagedAppConfig):
"""Load crypto tasks""" """Load crypto tasks"""
self.import_module("authentik.crypto.tasks") self.import_module("authentik.crypto.tasks")
def _create_update_cert(self, cert: Optional["CertificateKeyPair"] = None): def _create_update_cert(self):
from authentik.crypto.builder import CertificateBuilder from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
builder = CertificateBuilder("authentik Internal JWT Certificate") common_name = "authentik Internal JWT Certificate"
builder = CertificateBuilder(common_name)
builder.build( builder.build(
subject_alt_names=["goauthentik.io"], subject_alt_names=["goauthentik.io"],
validity_days=360, validity_days=360,
) )
if not cert: CertificateKeyPair.objects.update_or_create(
cert = CertificateKeyPair() managed=MANAGED_KEY,
builder.cert = cert defaults={
builder.cert.managed = MANAGED_KEY "name": common_name,
builder.save() "certificate_data": builder.certificate,
"key_data": builder.private_key,
},
)
def reconcile_managed_jwt_cert(self): def reconcile_managed_jwt_cert(self):
"""Ensure managed JWT certificate""" """Ensure managed JWT certificate"""
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
certs = CertificateKeyPair.objects.filter(managed=MANAGED_KEY) cert: Optional[CertificateKeyPair] = CertificateKeyPair.objects.filter(
if not certs.exists(): managed=MANAGED_KEY
self._create_update_cert() ).first()
return
cert: CertificateKeyPair = certs.first()
now = datetime.now() now = datetime.now()
if now < cert.certificate.not_valid_before or now > cert.certificate.not_valid_after: if not cert or (
self._create_update_cert(cert) now < cert.certificate.not_valid_before or now > cert.certificate.not_valid_after
):
self._create_update_cert()
def reconcile_self_signed(self): def reconcile_self_signed(self):
"""Create self-signed keypair""" """Create self-signed keypair"""
@ -61,4 +62,10 @@ class AuthentikCryptoConfig(ManagedAppConfig):
return return
builder = CertificateBuilder(name) builder = CertificateBuilder(name)
builder.build(subject_alt_names=[f"{generate_id()}.self-signed.goauthentik.io"]) builder.build(subject_alt_names=[f"{generate_id()}.self-signed.goauthentik.io"])
builder.save() CertificateKeyPair.objects.get_or_create(
name=name,
defaults={
"certificate_data": builder.certificate,
"key_data": builder.private_key,
},
)

View file

@ -6,7 +6,7 @@ from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema, inline_serializer from drf_spectacular.utils import extend_schema, inline_serializer
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import BooleanField, CharField, DateTimeField, IntegerField from rest_framework.fields import BooleanField, CharField, DateTimeField, IntegerField
from rest_framework.permissions import IsAdminUser, IsAuthenticated from rest_framework.permissions import IsAuthenticated
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 from rest_framework.serializers import ModelSerializer
@ -84,7 +84,7 @@ class LicenseViewSet(UsedByMixin, ModelViewSet):
200: inline_serializer("InstallIDSerializer", {"install_id": CharField(required=True)}), 200: inline_serializer("InstallIDSerializer", {"install_id": CharField(required=True)}),
}, },
) )
@action(detail=False, methods=["GET"], permission_classes=[IsAdminUser]) @action(detail=False, methods=["GET"])
def get_install_id(self, request: Request) -> Response: def get_install_id(self, request: Request) -> Response:
"""Get install_id""" """Get install_id"""
return Response( return Response(

View file

@ -33,4 +33,8 @@ class Migration(migrations.Migration):
"verbose_name_plural": "License Usage Records", "verbose_name_plural": "License Usage Records",
}, },
), ),
migrations.AlterModelOptions(
name="license",
options={"verbose_name": "License", "verbose_name_plural": "Licenses"},
),
] ]

View file

@ -19,8 +19,10 @@ from django.utils.translation import gettext as _
from guardian.shortcuts import get_anonymous_user from guardian.shortcuts import get_anonymous_user
from jwt import PyJWTError, decode, get_unverified_header from jwt import PyJWTError, decode, get_unverified_header
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from rest_framework.serializers import BaseSerializer
from authentik.core.models import ExpiringModel, User, UserTypes from authentik.core.models import ExpiringModel, User, UserTypes
from authentik.lib.models import SerializerModel
from authentik.root.install_id import get_install_id from authentik.root.install_id import get_install_id
@ -134,6 +136,9 @@ class LicenseKey:
def record_usage(self): def record_usage(self):
"""Capture the current validity status and metrics and save them""" """Capture the current validity status and metrics and save them"""
threshold = now() - timedelta(hours=8)
if LicenseUsage.objects.filter(record_date__gte=threshold).exists():
return
LicenseUsage.objects.create( LicenseUsage.objects.create(
user_count=self.get_default_user_count(), user_count=self.get_default_user_count(),
external_user_count=self.get_external_user_count(), external_user_count=self.get_external_user_count(),
@ -151,7 +156,7 @@ class LicenseKey:
return usage.record_date return usage.record_date
class License(models.Model): class License(SerializerModel):
"""An authentik enterprise license""" """An authentik enterprise license"""
license_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4) license_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
@ -162,6 +167,12 @@ class License(models.Model):
internal_users = models.BigIntegerField() internal_users = models.BigIntegerField()
external_users = models.BigIntegerField() external_users = models.BigIntegerField()
@property
def serializer(self) -> type[BaseSerializer]:
from authentik.enterprise.api import LicenseSerializer
return LicenseSerializer
@property @property
def status(self) -> LicenseKey: def status(self) -> LicenseKey:
"""Get parsed license status""" """Get parsed license status"""
@ -169,6 +180,8 @@ class License(models.Model):
class Meta: class Meta:
indexes = (HashIndex(fields=("key",)),) indexes = (HashIndex(fields=("key",)),)
verbose_name = _("License")
verbose_name_plural = _("Licenses")
def usage_expiry(): def usage_expiry():

View file

@ -6,7 +6,7 @@ from authentik.lib.utils.time import fqdn_rand
CELERY_BEAT_SCHEDULE = { CELERY_BEAT_SCHEDULE = {
"enterprise_calculate_license": { "enterprise_calculate_license": {
"task": "authentik.enterprise.tasks.calculate_license", "task": "authentik.enterprise.tasks.calculate_license",
"schedule": crontab(minute=fqdn_rand("calculate_license"), hour="*/8"), "schedule": crontab(minute=fqdn_rand("calculate_license"), hour="*/2"),
"options": {"queue": "authentik_scheduled"}, "options": {"queue": "authentik_scheduled"},
} }
} }

View file

@ -6,5 +6,4 @@ from authentik.root.celery import CELERY_APP
@CELERY_APP.task() @CELERY_APP.task()
def calculate_license(): def calculate_license():
"""Calculate licensing status""" """Calculate licensing status"""
total = LicenseKey.get_total() LicenseKey.get_total().record_usage()
total.record_usage()

View file

@ -27,6 +27,7 @@ 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
from authentik.outposts.models import OutpostServiceConnection from authentik.outposts.models import OutpostServiceConnection
from authentik.policies.models import Policy, PolicyBindingModel from authentik.policies.models import Policy, PolicyBindingModel
from authentik.policies.reputation.models import Reputation
from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken
from authentik.providers.scim.models import SCIMGroup, SCIMUser from authentik.providers.scim.models import SCIMGroup, SCIMUser
from authentik.stages.authenticator_static.models import StaticToken from authentik.stages.authenticator_static.models import StaticToken
@ -52,11 +53,13 @@ IGNORED_MODELS = (
RefreshToken, RefreshToken,
SCIMUser, SCIMUser,
SCIMGroup, SCIMGroup,
Reputation,
) )
def should_log_model(model: Model) -> bool: def should_log_model(model: Model) -> bool:
"""Return true if operation on `model` should be logged""" """Return true if operation on `model` should be logged"""
# Check for silk by string so this comparison doesn't fail when silk isn't installed
if model.__module__.startswith("silk"): if model.__module__.startswith("silk"):
return False return False
return model.__class__ not in IGNORED_MODELS return model.__class__ not in IGNORED_MODELS
@ -93,21 +96,30 @@ class AuditMiddleware:
of models""" of models"""
get_response: Callable[[HttpRequest], HttpResponse] get_response: Callable[[HttpRequest], HttpResponse]
anonymous_user: User = None
def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]): def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):
self.get_response = get_response self.get_response = get_response
def _ensure_fallback_user(self):
"""Defer fetching anonymous user until we have to"""
if self.anonymous_user:
return
from guardian.shortcuts import get_anonymous_user
self.anonymous_user = get_anonymous_user()
def connect(self, request: HttpRequest): def connect(self, request: HttpRequest):
"""Connect signal for automatic logging""" """Connect signal for automatic logging"""
if not hasattr(request, "user"): self._ensure_fallback_user()
return user = getattr(request, "user", self.anonymous_user)
if not getattr(request.user, "is_authenticated", False): if not user.is_authenticated:
return user = self.anonymous_user
if not hasattr(request, "request_id"): if not hasattr(request, "request_id"):
return return
post_save_handler = partial(self.post_save_handler, user=request.user, request=request) post_save_handler = partial(self.post_save_handler, user=user, request=request)
pre_delete_handler = partial(self.pre_delete_handler, user=request.user, request=request) pre_delete_handler = partial(self.pre_delete_handler, user=user, request=request)
m2m_changed_handler = partial(self.m2m_changed_handler, user=request.user, request=request) m2m_changed_handler = partial(self.m2m_changed_handler, user=user, request=request)
post_save.connect( post_save.connect(
post_save_handler, post_save_handler,
dispatch_uid=request.request_id, dispatch_uid=request.request_id,

View file

@ -217,6 +217,7 @@ class Event(SerializerModel, ExpiringModel):
"path": request.path, "path": request.path,
"method": request.method, "method": request.method,
"args": cleanse_dict(QueryDict(request.META.get("QUERY_STRING", ""))), "args": cleanse_dict(QueryDict(request.META.get("QUERY_STRING", ""))),
"user_agent": request.META.get("HTTP_USER_AGENT", ""),
} }
# Special case for events created during flow execution # Special case for events created during flow execution
# since they keep the http query within a wrapped query # since they keep the http query within a wrapped query
@ -436,32 +437,39 @@ class NotificationTransport(SerializerModel):
def send_email(self, notification: "Notification") -> list[str]: def send_email(self, notification: "Notification") -> list[str]:
"""Send notification via global email configuration""" """Send notification via global email configuration"""
subject = "authentik Notification: " subject_prefix = "authentik Notification: "
key_value = { context = {
"key_value": {
"user_email": notification.user.email, "user_email": notification.user.email,
"user_username": notification.user.username, "user_username": notification.user.username,
},
"body": notification.body,
"title": "",
} }
if notification.event and notification.event.user: if notification.event and notification.event.user:
key_value["event_user_email"] = notification.event.user.get("email", None) context["key_value"]["event_user_email"] = notification.event.user.get("email", None)
key_value["event_user_username"] = notification.event.user.get("username", None) context["key_value"]["event_user_username"] = notification.event.user.get(
"username", None
)
if notification.event: if notification.event:
subject += notification.event.action context["title"] += notification.event.action
for key, value in notification.event.context.items(): for key, value in notification.event.context.items():
if not isinstance(value, str): if not isinstance(value, str):
continue continue
key_value[key] = value context["key_value"][key] = value
else: else:
subject += notification.body[:75] context["title"] += notification.body[:75]
# TODO: improve permission check
if notification.user.is_superuser:
context["source"] = {
"from": self.name,
}
mail = TemplateEmailMessage( mail = TemplateEmailMessage(
subject=subject, subject=subject_prefix + context["title"],
to=[notification.user.email], to=[notification.user.email],
language=notification.user.locale(), language=notification.user.locale(),
template_name="email/generic.html", template_name="email/event_notification.html",
template_context={ template_context=context,
"title": subject,
"body": notification.body,
"key_value": key_value,
},
) )
# Email is sent directly here, as the call to send() should have been from a task. # Email is sent directly here, as the call to send() should have been from a task.
try: try:

View file

@ -206,8 +206,8 @@ def prefill_task(func):
task_call_module=func.__module__, task_call_module=func.__module__,
task_call_func=func.__name__, task_call_func=func.__name__,
# We don't have real values for these attributes but they cannot be null # We don't have real values for these attributes but they cannot be null
start_timestamp=default_timer(), start_timestamp=0,
finish_timestamp=default_timer(), finish_timestamp=0,
finish_time=datetime.now(), finish_time=datetime.now(),
).save(86400) ).save(86400)
LOGGER.debug("prefilled task", task_name=func.__name__) LOGGER.debug("prefilled task", task_name=func.__name__)

View file

@ -13,6 +13,7 @@ from authentik.events.tasks import event_notification_handler, gdpr_cleanup
from authentik.flows.models import Stage 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.lib.config import CONFIG
from authentik.stages.invitation.models import Invitation from authentik.stages.invitation.models import Invitation
from authentik.stages.invitation.signals import invitation_used from authentik.stages.invitation.signals import invitation_used
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
@ -92,4 +93,5 @@ def event_post_save_notification(sender, instance: Event, **_):
@receiver(pre_delete, sender=User) @receiver(pre_delete, sender=User)
def event_user_pre_delete_cleanup(sender, instance: User, **_): def event_user_pre_delete_cleanup(sender, instance: User, **_):
"""If gdpr_compliance is enabled, remove all the user's events""" """If gdpr_compliance is enabled, remove all the user's events"""
if CONFIG.get_bool("gdpr_compliance", True):
gdpr_cleanup.delay(instance.pk) gdpr_cleanup.delay(instance.pk)

View file

@ -53,7 +53,15 @@ class TestEvents(TestCase):
"""Test plain from_http""" """Test plain from_http"""
event = Event.new("unittest").from_http(self.factory.get("/")) event = Event.new("unittest").from_http(self.factory.get("/"))
self.assertEqual( self.assertEqual(
event.context, {"http_request": {"args": {}, "method": "GET", "path": "/"}} event.context,
{
"http_request": {
"args": {},
"method": "GET",
"path": "/",
"user_agent": "",
}
},
) )
def test_from_http_clean_querystring(self): def test_from_http_clean_querystring(self):
@ -67,6 +75,7 @@ class TestEvents(TestCase):
"args": {"token": SafeExceptionReporterFilter.cleansed_substitute}, "args": {"token": SafeExceptionReporterFilter.cleansed_substitute},
"method": "GET", "method": "GET",
"path": "/", "path": "/",
"user_agent": "",
} }
}, },
) )
@ -83,6 +92,7 @@ class TestEvents(TestCase):
"args": {"token": SafeExceptionReporterFilter.cleansed_substitute}, "args": {"token": SafeExceptionReporterFilter.cleansed_substitute},
"method": "GET", "method": "GET",
"path": "/", "path": "/",
"user_agent": "",
} }
}, },
) )

View file

@ -2,17 +2,20 @@
import re import re
from copy import copy from copy import copy
from dataclasses import asdict, is_dataclass from dataclasses import asdict, is_dataclass
from datetime import date, datetime, time, timedelta
from enum import Enum from enum import Enum
from pathlib import Path from pathlib import Path
from types import GeneratorType from types import GeneratorType, NoneType
from typing import Any, Optional from typing import Any, Optional
from uuid import UUID from uuid import UUID
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser
from django.core.handlers.wsgi import WSGIRequest from django.core.handlers.wsgi import WSGIRequest
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models 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.utils import timezone
from django.views.debug import SafeExceptionReporterFilter from django.views.debug import SafeExceptionReporterFilter
from geoip2.models import City from geoip2.models import City
from guardian.utils import get_anonymous_user from guardian.utils import get_anonymous_user
@ -84,7 +87,7 @@ def get_user(user: User, original_user: Optional[User] = None) -> dict[str, Any]
return user_data return user_data
# pylint: disable=too-many-return-statements # pylint: disable=too-many-return-statements,too-many-branches
def sanitize_item(value: Any) -> Any: def sanitize_item(value: Any) -> Any:
"""Sanitize a single item, ensure it is JSON parsable""" """Sanitize a single item, ensure it is JSON parsable"""
if is_dataclass(value): if is_dataclass(value):
@ -134,7 +137,37 @@ def sanitize_item(value: Any) -> Any:
"type": value.__name__, "type": value.__name__,
"module": value.__module__, "module": value.__module__,
} }
# See
# https://github.com/encode/django-rest-framework/blob/master/rest_framework/utils/encoders.py
# For Date Time string spec, see ECMA 262
# https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
if isinstance(value, datetime):
representation = value.isoformat()
if representation.endswith("+00:00"):
representation = representation[:-6] + "Z"
return representation
if isinstance(value, date):
return value.isoformat()
if isinstance(value, time):
if timezone and timezone.is_aware(value):
raise ValueError("JSON can't represent timezone-aware times.")
return value.isoformat()
if isinstance(value, timedelta):
return str(value.total_seconds())
if callable(value):
return {
"type": "callable",
"name": value.__name__,
"module": value.__module__,
}
# List taken from the stdlib's JSON encoder (_make_iterencode, encoder.py:415)
if isinstance(value, (bool, int, float, NoneType, list, tuple, dict)):
return value return value
try:
return DjangoJSONEncoder().default(value)
except TypeError:
return str(value)
return str(value)
def sanitize_dict(source: dict[Any, Any]) -> dict[Any, Any]: def sanitize_dict(source: dict[Any, Any]) -> dict[Any, Any]:

View file

@ -45,3 +45,4 @@ class FlowStageBindingViewSet(UsedByMixin, ModelViewSet):
serializer_class = FlowStageBindingSerializer serializer_class = FlowStageBindingSerializer
filterset_fields = "__all__" filterset_fields = "__all__"
search_fields = ["stage__name"] search_fields = ["stage__name"]
ordering = ["order"]

View file

@ -8,6 +8,11 @@ GAUGE_FLOWS_CACHED = Gauge(
"authentik_flows_cached", "authentik_flows_cached",
"Cached flows", "Cached flows",
) )
HIST_FLOW_EXECUTION_STAGE_TIME = Histogram(
"authentik_flows_execution_stage_time",
"Duration each stage took to execute.",
["stage_type", "method"],
)
HIST_FLOWS_PLAN_TIME = Histogram( HIST_FLOWS_PLAN_TIME = Histogram(
"authentik_flows_plan_time", "authentik_flows_plan_time",
"Duration to build a plan for a flow", "Duration to build a plan for a flow",

View file

@ -132,13 +132,6 @@ class PermissionDict(TypedDict):
name: str name: str
class PermissionSerializer(PassiveSerializer):
"""Permission used for consent"""
name = CharField(allow_blank=True)
id = CharField()
class ChallengeResponse(PassiveSerializer): class ChallengeResponse(PassiveSerializer):
"""Base class for all challenge responses""" """Base class for all challenge responses"""

View file

@ -0,0 +1,25 @@
# Generated by Django 4.2.6 on 2023-10-10 17:18
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0025_alter_flowstagebinding_evaluate_on_plan_and_more"),
]
operations = [
migrations.AlterModelOptions(
name="flow",
options={
"permissions": [
("export_flow", "Can export a Flow"),
("inspect_flow", "Can inspect a Flow's execution"),
("view_flow_cache", "View Flow's cache metrics"),
("clear_flow_cache", "Clear Flow's cache metrics"),
],
"verbose_name": "Flow",
"verbose_name_plural": "Flows",
},
),
]

View file

@ -0,0 +1,34 @@
# Generated by Django 4.2.6 on 2023-10-28 14:24
from django.apps.registry import Apps
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def set_oobe_flow_authentication(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
from guardian.shortcuts import get_anonymous_user
Flow = apps.get_model("authentik_flows", "Flow")
User = apps.get_model("authentik_core", "User")
db_alias = schema_editor.connection.alias
users = User.objects.using(db_alias).exclude(username="akadmin")
try:
users = users.exclude(pk=get_anonymous_user().pk)
# pylint: disable=broad-except
except Exception: # nosec
pass
if users.exists():
Flow.objects.filter(slug="initial-setup").update(authentication="require_superuser")
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0026_alter_flow_options"),
]
operations = [
migrations.RunPython(set_oobe_flow_authentication),
]

View file

@ -194,9 +194,10 @@ class Flow(SerializerModel, PolicyBindingModel):
verbose_name_plural = _("Flows") verbose_name_plural = _("Flows")
permissions = [ permissions = [
("export_flow", "Can export a Flow"), ("export_flow", _("Can export a Flow")),
("view_flow_cache", "View Flow's cache metrics"), ("inspect_flow", _("Can inspect a Flow's execution")),
("clear_flow_cache", "Clear Flow's cache metrics"), ("view_flow_cache", _("View Flow's cache metrics")),
("clear_flow_cache", _("Clear Flow's cache metrics")),
] ]

View file

@ -167,7 +167,11 @@ class ChallengeStageView(StageView):
stage_type=self.__class__.__name__, method="get_challenge" stage_type=self.__class__.__name__, method="get_challenge"
).time(), ).time(),
): ):
try:
challenge = self.get_challenge(*args, **kwargs) challenge = self.get_challenge(*args, **kwargs)
except StageInvalidException as exc:
self.logger.debug("Got StageInvalidException", exc=exc)
return self.executor.stage_invalid()
with Hub.current.start_span( with Hub.current.start_span(
op="authentik.flow.stage._get_challenge", op="authentik.flow.stage._get_challenge",
description=self.__class__.__name__, description=self.__class__.__name__,

View file

@ -24,6 +24,7 @@ from structlog.stdlib import BoundLogger, get_logger
from authentik.core.models import Application from authentik.core.models import Application
from authentik.events.models import Event, EventAction, cleanse_dict from authentik.events.models import Event, EventAction, cleanse_dict
from authentik.flows.apps import HIST_FLOW_EXECUTION_STAGE_TIME
from authentik.flows.challenge import ( from authentik.flows.challenge import (
Challenge, Challenge,
ChallengeResponse, ChallengeResponse,
@ -266,17 +267,21 @@ class FlowExecutorView(APIView):
) )
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Get the next pending challenge from the currently active flow.""" """Get the next pending challenge from the currently active flow."""
class_path = class_to_path(self.current_stage_view.__class__)
self._logger.debug( self._logger.debug(
"f(exec): Passing GET", "f(exec): Passing GET",
view_class=class_to_path(self.current_stage_view.__class__), view_class=class_path,
stage=self.current_stage, stage=self.current_stage,
) )
try: try:
with Hub.current.start_span( with Hub.current.start_span(
op="authentik.flow.executor.stage", op="authentik.flow.executor.stage",
description=class_to_path(self.current_stage_view.__class__), description=class_path,
) as span: ) as span, HIST_FLOW_EXECUTION_STAGE_TIME.labels(
span.set_data("Method", "GET") method=request.method.upper(),
stage_type=class_path,
).time():
span.set_data("Method", request.method.upper())
span.set_data("authentik Stage", self.current_stage_view) span.set_data("authentik Stage", self.current_stage_view)
span.set_data("authentik Flow", self.flow.slug) span.set_data("authentik Flow", self.flow.slug)
stage_response = self.current_stage_view.dispatch(request) stage_response = self.current_stage_view.dispatch(request)
@ -310,17 +315,21 @@ class FlowExecutorView(APIView):
) )
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Solve the previously retrieved challenge and advanced to the next stage.""" """Solve the previously retrieved challenge and advanced to the next stage."""
class_path = class_to_path(self.current_stage_view.__class__)
self._logger.debug( self._logger.debug(
"f(exec): Passing POST", "f(exec): Passing POST",
view_class=class_to_path(self.current_stage_view.__class__), view_class=class_path,
stage=self.current_stage, stage=self.current_stage,
) )
try: try:
with Hub.current.start_span( with Hub.current.start_span(
op="authentik.flow.executor.stage", op="authentik.flow.executor.stage",
description=class_to_path(self.current_stage_view.__class__), description=class_path,
) as span: ) as span, HIST_FLOW_EXECUTION_STAGE_TIME.labels(
span.set_data("Method", "POST") method=request.method.upper(),
stage_type=class_path,
).time():
span.set_data("Method", request.method.upper())
span.set_data("authentik Stage", self.current_stage_view) span.set_data("authentik Stage", self.current_stage_view)
span.set_data("authentik Flow", self.flow.slug) span.set_data("authentik Flow", self.flow.slug)
stage_response = self.current_stage_view.dispatch(request) stage_response = self.current_stage_view.dispatch(request)

View file

@ -3,6 +3,7 @@ from hashlib import sha256
from typing import Any from typing import Any
from django.conf import settings from django.conf import settings
from django.http import Http404
from django.http.request import HttpRequest from django.http.request import HttpRequest
from django.http.response import HttpResponse from django.http.response import HttpResponse
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
@ -11,7 +12,6 @@ from django.views.decorators.clickjacking import xframe_options_sameorigin
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiResponse, extend_schema from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework.fields import BooleanField, ListField, SerializerMethodField from rest_framework.fields import BooleanField, ListField, SerializerMethodField
from rest_framework.permissions import IsAdminUser
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.views import APIView from rest_framework.views import APIView
@ -68,21 +68,19 @@ class FlowInspectionSerializer(PassiveSerializer):
class FlowInspectorView(APIView): class FlowInspectorView(APIView):
"""Flow inspector API""" """Flow inspector API"""
permission_classes = [IsAdminUser]
flow: Flow flow: Flow
_logger: BoundLogger _logger: BoundLogger
permission_classes = []
def check_permissions(self, request):
"""Always allow access when in debug mode"""
if settings.DEBUG:
return None
return super().check_permissions(request)
def setup(self, request: HttpRequest, flow_slug: str): def setup(self, request: HttpRequest, flow_slug: str):
super().setup(request, flow_slug=flow_slug) super().setup(request, flow_slug=flow_slug)
self.flow = get_object_or_404(Flow.objects.select_related(), slug=flow_slug)
self._logger = get_logger().bind(flow_slug=flow_slug) self._logger = get_logger().bind(flow_slug=flow_slug)
self.flow = get_object_or_404(Flow.objects.select_related(), slug=flow_slug)
if settings.DEBUG:
return
if request.user.has_perm("authentik_flow.inspect_flow", self.flow):
return
raise Http404
@extend_schema( @extend_schema(
responses={ responses={

View file

@ -24,7 +24,7 @@ ENVIRONMENT = os.getenv(f"{ENV_PREFIX}_ENV", "local")
def get_path_from_dict(root: dict, path: str, sep=".", default=None) -> Any: def get_path_from_dict(root: dict, path: str, sep=".", default=None) -> Any:
"""Recursively walk through `root`, checking each part of `path` split by `sep`. """Recursively walk through `root`, checking each part of `path` separated by `sep`.
If at any point a dict does not exist, return default""" If at any point a dict does not exist, return default"""
for comp in path.split(sep): for comp in path.split(sep):
if root and comp in root: if root and comp in root:
@ -34,7 +34,19 @@ def get_path_from_dict(root: dict, path: str, sep=".", default=None) -> Any:
return root return root
@dataclass def set_path_in_dict(root: dict, path: str, value: Any, sep="."):
"""Recursively walk through `root`, checking each part of `path` separated by `sep`
and setting the last value to `value`"""
# Walk each component of the path
path_parts = path.split(sep)
for comp in path_parts[:-1]:
if comp not in root:
root[comp] = {}
root = root.get(comp, {})
root[path_parts[-1]] = value
@dataclass(slots=True)
class Attr: class Attr:
"""Single configuration attribute""" """Single configuration attribute"""
@ -55,6 +67,10 @@ class Attr:
# to the config file containing this change or the file containing this value # to the config file containing this change or the file containing this value
source: Optional[str] = field(default=None) source: Optional[str] = field(default=None)
def __post_init__(self):
if isinstance(self.value, Attr):
raise RuntimeError(f"config Attr with nested Attr for source {self.source}")
class AttrEncoder(JSONEncoder): class AttrEncoder(JSONEncoder):
"""JSON encoder that can deal with `Attr` classes""" """JSON encoder that can deal with `Attr` classes"""
@ -227,15 +243,7 @@ class ConfigLoader:
def set(self, path: str, value: Any, sep="."): def set(self, path: str, value: Any, sep="."):
"""Set value using same syntax as get()""" """Set value using same syntax as get()"""
# Walk sub_dicts before parsing path set_path_in_dict(self.raw, path, Attr(value), sep=sep)
root = self.raw
# Walk each component of the path
path_parts = path.split(sep)
for comp in path_parts[:-1]:
if comp not in root:
root[comp] = {}
root = root.get(comp, {})
root[path_parts[-1]] = Attr(value)
CONFIG = ConfigLoader() CONFIG = ConfigLoader()

View file

@ -106,7 +106,6 @@ default_token_length: 60
impersonation: true impersonation: true
blueprints_dir: /blueprints blueprints_dir: /blueprints
variables_discovery_dir: /data/variables
web: web:
# No default here as it's set dynamically # No default here as it's set dynamically

View file

@ -141,7 +141,7 @@ class BaseEvaluator:
"""Create event with supplied data and try to extract as much relevant data """Create event with supplied data and try to extract as much relevant data
from the context""" from the context"""
context = self._context.copy() context = self._context.copy()
# If the result was a complex variable, we don't want to re-use it # If the result was a complex variable, we don't want to reuse it
context.pop("result", None) context.pop("result", None)
context.pop("handler", None) context.pop("handler", None)
event_kwargs = context event_kwargs = context

View file

@ -0,0 +1,32 @@
"""Serializer validators"""
from typing import Optional
from django.utils.translation import gettext_lazy as _
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import Serializer
from rest_framework.utils.representation import smart_repr
class RequiredTogetherValidator:
"""Serializer-level validator that ensures all fields in `fields` are only
used together"""
fields: list[str]
requires_context = True
message = _("The fields {field_names} must be used together.")
def __init__(self, fields: list[str], message: Optional[str] = None) -> None:
self.fields = fields
self.message = message or self.message
def __call__(self, attrs: dict, serializer: Serializer):
"""Check that if any of the fields in `self.fields` are set, all of them must be set"""
if any(field in attrs for field in self.fields) and not all(
field in attrs for field in self.fields
):
field_names = ", ".join(self.fields)
message = self.message.format(field_names=field_names)
raise ValidationError(message, code="required")
def __repr__(self):
return "<%s(fields=%s)>" % (self.__class__.__name__, smart_repr(self.fields))

View file

@ -18,7 +18,7 @@ from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer, is_dict from authentik.core.api.utils import PassiveSerializer, is_dict
from authentik.core.models import Provider from authentik.core.models import Provider
from authentik.outposts.api.service_connections import ServiceConnectionSerializer from authentik.outposts.api.service_connections import ServiceConnectionSerializer
from authentik.outposts.apps import MANAGED_OUTPOST from authentik.outposts.apps import MANAGED_OUTPOST, MANAGED_OUTPOST_NAME
from authentik.outposts.models import ( from authentik.outposts.models import (
Outpost, Outpost,
OutpostConfig, OutpostConfig,
@ -47,6 +47,16 @@ class OutpostSerializer(ModelSerializer):
source="service_connection", read_only=True source="service_connection", read_only=True
) )
def validate_name(self, name: str) -> str:
"""Validate name (especially for embedded outpost)"""
if not self.instance:
return name
if self.instance.managed == MANAGED_OUTPOST and name != MANAGED_OUTPOST_NAME:
raise ValidationError("Embedded outpost's name cannot be changed")
if self.instance.name == MANAGED_OUTPOST_NAME:
self.instance.managed = MANAGED_OUTPOST
return name
def validate_providers(self, providers: list[Provider]) -> list[Provider]: def validate_providers(self, providers: list[Provider]) -> list[Provider]:
"""Check that all providers match the type of the outpost""" """Check that all providers match the type of the outpost"""
type_map = { type_map = {

View file

@ -15,6 +15,7 @@ GAUGE_OUTPOSTS_LAST_UPDATE = Gauge(
["outpost", "uid", "version"], ["outpost", "uid", "version"],
) )
MANAGED_OUTPOST = "goauthentik.io/outposts/embedded" MANAGED_OUTPOST = "goauthentik.io/outposts/embedded"
MANAGED_OUTPOST_NAME = "authentik Embedded Outpost"
class AuthentikOutpostConfig(ManagedAppConfig): class AuthentikOutpostConfig(ManagedAppConfig):
@ -35,14 +36,17 @@ class AuthentikOutpostConfig(ManagedAppConfig):
DockerServiceConnection, DockerServiceConnection,
KubernetesServiceConnection, KubernetesServiceConnection,
Outpost, Outpost,
OutpostConfig,
OutpostType, OutpostType,
) )
if outpost := Outpost.objects.filter(name=MANAGED_OUTPOST_NAME, managed="").first():
outpost.managed = MANAGED_OUTPOST
outpost.save()
return
outpost, updated = Outpost.objects.update_or_create( outpost, updated = Outpost.objects.update_or_create(
defaults={ defaults={
"name": "authentik Embedded Outpost",
"type": OutpostType.PROXY, "type": OutpostType.PROXY,
"name": MANAGED_OUTPOST_NAME,
}, },
managed=MANAGED_OUTPOST, managed=MANAGED_OUTPOST,
) )
@ -51,10 +55,4 @@ class AuthentikOutpostConfig(ManagedAppConfig):
outpost.service_connection = KubernetesServiceConnection.objects.first() outpost.service_connection = KubernetesServiceConnection.objects.first()
elif DockerServiceConnection.objects.exists(): elif DockerServiceConnection.objects.exists():
outpost.service_connection = DockerServiceConnection.objects.first() outpost.service_connection = DockerServiceConnection.objects.first()
outpost.config = OutpostConfig(
kubernetes_disabled_components=[
"deployment",
"secret",
]
)
outpost.save() outpost.save()

View file

@ -4,6 +4,7 @@ from datetime import datetime
from enum import IntEnum from enum import IntEnum
from typing import Any, Optional from typing import Any, Optional
from asgiref.sync import async_to_sync
from channels.exceptions import DenyConnection from channels.exceptions import DenyConnection
from dacite.core import from_dict from dacite.core import from_dict
from dacite.data import Data from dacite.data import Data
@ -14,6 +15,8 @@ from authentik.core.channels import AuthJsonConsumer
from authentik.outposts.apps import GAUGE_OUTPOSTS_CONNECTED, GAUGE_OUTPOSTS_LAST_UPDATE from authentik.outposts.apps import GAUGE_OUTPOSTS_CONNECTED, GAUGE_OUTPOSTS_LAST_UPDATE
from authentik.outposts.models import OUTPOST_HELLO_INTERVAL, Outpost, OutpostState from authentik.outposts.models import OUTPOST_HELLO_INTERVAL, Outpost, OutpostState
OUTPOST_GROUP = "group_outpost_%(outpost_pk)s"
class WebsocketMessageInstruction(IntEnum): class WebsocketMessageInstruction(IntEnum):
"""Commands which can be triggered over Websocket""" """Commands which can be triggered over Websocket"""
@ -27,6 +30,9 @@ class WebsocketMessageInstruction(IntEnum):
# Message sent by us to trigger an Update # Message sent by us to trigger an Update
TRIGGER_UPDATE = 2 TRIGGER_UPDATE = 2
# Provider specific message
PROVIDER_SPECIFIC = 3
@dataclass(slots=True) @dataclass(slots=True)
class WebsocketMessage: class WebsocketMessage:
@ -44,8 +50,6 @@ class OutpostConsumer(AuthJsonConsumer):
last_uid: Optional[str] = None last_uid: Optional[str] = None
first_msg = False
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.logger = get_logger() self.logger = get_logger()
@ -68,22 +72,26 @@ class OutpostConsumer(AuthJsonConsumer):
raise DenyConnection() raise DenyConnection()
self.outpost = outpost self.outpost = outpost
self.last_uid = self.channel_name self.last_uid = self.channel_name
async_to_sync(self.channel_layer.group_add)(
OUTPOST_GROUP % {"outpost_pk": str(self.outpost.pk)}, self.channel_name
)
GAUGE_OUTPOSTS_CONNECTED.labels(
outpost=self.outpost.name,
uid=self.last_uid,
expected=self.outpost.config.kubernetes_replicas,
).inc()
def disconnect(self, code): def disconnect(self, code):
if self.outpost:
async_to_sync(self.channel_layer.group_discard)(
OUTPOST_GROUP % {"outpost_pk": str(self.outpost.pk)}, self.channel_name
)
if self.outpost and self.last_uid: if self.outpost and self.last_uid:
state = OutpostState.for_instance_uid(self.outpost, self.last_uid)
if self.channel_name in state.channel_ids:
state.channel_ids.remove(self.channel_name)
state.save()
GAUGE_OUTPOSTS_CONNECTED.labels( GAUGE_OUTPOSTS_CONNECTED.labels(
outpost=self.outpost.name, outpost=self.outpost.name,
uid=self.last_uid, uid=self.last_uid,
expected=self.outpost.config.kubernetes_replicas, expected=self.outpost.config.kubernetes_replicas,
).dec() ).dec()
self.logger.debug(
"removed outpost instance from cache",
instance_uuid=self.last_uid,
)
def receive_json(self, content: Data): def receive_json(self, content: Data):
msg = from_dict(WebsocketMessage, content) msg = from_dict(WebsocketMessage, content)
@ -94,26 +102,13 @@ class OutpostConsumer(AuthJsonConsumer):
raise DenyConnection() raise DenyConnection()
state = OutpostState.for_instance_uid(self.outpost, uid) state = OutpostState.for_instance_uid(self.outpost, uid)
if self.channel_name not in state.channel_ids:
state.channel_ids.append(self.channel_name)
state.last_seen = datetime.now() state.last_seen = datetime.now()
state.hostname = msg.args.get("hostname", "") state.hostname = msg.args.pop("hostname", "")
if not self.first_msg:
GAUGE_OUTPOSTS_CONNECTED.labels(
outpost=self.outpost.name,
uid=self.last_uid,
expected=self.outpost.config.kubernetes_replicas,
).inc()
self.logger.debug(
"added outpost instance to cache",
instance_uuid=self.last_uid,
)
self.first_msg = True
if msg.instruction == WebsocketMessageInstruction.HELLO: if msg.instruction == WebsocketMessageInstruction.HELLO:
state.version = msg.args.get("version", None) state.version = msg.args.pop("version", None)
state.build_hash = msg.args.get("buildHash", "") state.build_hash = msg.args.pop("buildHash", "")
state.args = msg.args
elif msg.instruction == WebsocketMessageInstruction.ACK: elif msg.instruction == WebsocketMessageInstruction.ACK:
return return
GAUGE_OUTPOSTS_LAST_UPDATE.labels( GAUGE_OUTPOSTS_LAST_UPDATE.labels(
@ -131,3 +126,14 @@ class OutpostConsumer(AuthJsonConsumer):
self.send_json( self.send_json(
asdict(WebsocketMessage(instruction=WebsocketMessageInstruction.TRIGGER_UPDATE)) asdict(WebsocketMessage(instruction=WebsocketMessageInstruction.TRIGGER_UPDATE))
) )
def event_provider_specific(self, event):
"""Event handler which can be called by provider-specific
implementations to send specific messages to the outpost"""
self.send_json(
asdict(
WebsocketMessage(
instruction=WebsocketMessageInstruction.PROVIDER_SPECIFIC, args=event
)
)
)

View file

@ -43,6 +43,10 @@ class DeploymentReconciler(KubernetesObjectReconciler[V1Deployment]):
self.api = AppsV1Api(controller.client) self.api = AppsV1Api(controller.client)
self.outpost = self.controller.outpost self.outpost = self.controller.outpost
@property
def noop(self) -> bool:
return self.is_embedded
@staticmethod @staticmethod
def reconciler_name() -> str: def reconciler_name() -> str:
return "deployment" return "deployment"

View file

@ -24,6 +24,10 @@ class SecretReconciler(KubernetesObjectReconciler[V1Secret]):
super().__init__(controller) super().__init__(controller)
self.api = CoreV1Api(controller.client) self.api = CoreV1Api(controller.client)
@property
def noop(self) -> bool:
return self.is_embedded
@staticmethod @staticmethod
def reconciler_name() -> str: def reconciler_name() -> str:
return "secret" return "secret"

View file

@ -77,7 +77,10 @@ class PrometheusServiceMonitorReconciler(KubernetesObjectReconciler[PrometheusSe
@property @property
def noop(self) -> bool: def noop(self) -> bool:
return (not self._crd_exists()) or (self.is_embedded) if not self._crd_exists():
self.logger.debug("CRD doesn't exist")
return True
return self.is_embedded
def _crd_exists(self) -> bool: def _crd_exists(self) -> bool:
"""Check if the Prometheus ServiceMonitor exists""" """Check if the Prometheus ServiceMonitor exists"""

View file

@ -28,4 +28,8 @@ class Migration(migrations.Migration):
verbose_name="Managed by authentik", verbose_name="Managed by authentik",
), ),
), ),
migrations.AlterModelOptions(
name="outpost",
options={"verbose_name": "Outpost", "verbose_name_plural": "Outposts"},
),
] ]

View file

@ -344,11 +344,21 @@ class Outpost(SerializerModel, ManagedModel):
user_created = False user_created = False
if not user: if not user:
user: User = User.objects.create(username=self.user_identifier) user: User = User.objects.create(username=self.user_identifier)
user.set_unusable_password()
user_created = True user_created = True
user.type = UserTypes.INTERNAL_SERVICE_ACCOUNT attrs = {
user.name = f"Outpost {self.name} Service-Account" "type": UserTypes.INTERNAL_SERVICE_ACCOUNT,
user.path = USER_PATH_OUTPOSTS "name": f"Outpost {self.name} Service-Account",
"path": USER_PATH_OUTPOSTS,
}
dirty = False
for key, value in attrs.items():
if getattr(user, key) != value:
dirty = True
setattr(user, key, value)
if user.has_usable_password():
user.set_unusable_password()
dirty = True
if dirty:
user.save() user.save()
if user_created: if user_created:
self.build_user_permissions(user) self.build_user_permissions(user)
@ -380,7 +390,7 @@ class Outpost(SerializerModel, ManagedModel):
managed=managed, managed=managed,
) )
except IntegrityError: except IntegrityError:
# Integrity error happens mostly when managed is re-used # Integrity error happens mostly when managed is reused
Token.objects.filter(managed=managed).delete() Token.objects.filter(managed=managed).delete()
Token.objects.filter(identifier=self.token_identifier).delete() Token.objects.filter(identifier=self.token_identifier).delete()
return self.token return self.token
@ -405,18 +415,22 @@ class Outpost(SerializerModel, ManagedModel):
def __str__(self) -> str: def __str__(self) -> str:
return f"Outpost {self.name}" return f"Outpost {self.name}"
class Meta:
verbose_name = _("Outpost")
verbose_name_plural = _("Outposts")
@dataclass @dataclass
class OutpostState: class OutpostState:
"""Outpost instance state, last_seen and version""" """Outpost instance state, last_seen and version"""
uid: str uid: str
channel_ids: list[str] = field(default_factory=list)
last_seen: Optional[datetime] = field(default=None) last_seen: Optional[datetime] = field(default=None)
version: Optional[str] = field(default=None) version: Optional[str] = field(default=None)
version_should: Version = field(default=OUR_VERSION) version_should: Version = field(default=OUR_VERSION)
build_hash: str = field(default="") build_hash: str = field(default="")
hostname: str = field(default="") hostname: str = field(default="")
args: dict = field(default_factory=dict)
_outpost: Optional[Outpost] = field(default=None) _outpost: Optional[Outpost] = field(default=None)

View file

@ -5,7 +5,6 @@ from socket import gethostname
from typing import Any, Optional from typing import Any, Optional
from urllib.parse import urlparse from urllib.parse import urlparse
import yaml
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer from channels.layers import get_channel_layer
from django.core.cache import cache from django.core.cache import cache
@ -16,6 +15,7 @@ from docker.constants import DEFAULT_UNIX_SOCKET
from kubernetes.config.incluster_config import SERVICE_TOKEN_FILENAME from kubernetes.config.incluster_config import SERVICE_TOKEN_FILENAME
from kubernetes.config.kube_config import KUBE_CONFIG_DEFAULT_LOCATION from kubernetes.config.kube_config import KUBE_CONFIG_DEFAULT_LOCATION
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from yaml import safe_load
from authentik.events.monitored_tasks import ( from authentik.events.monitored_tasks import (
MonitoredTask, MonitoredTask,
@ -25,6 +25,7 @@ from authentik.events.monitored_tasks import (
) )
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.lib.utils.reflection import path_to_class from authentik.lib.utils.reflection import path_to_class
from authentik.outposts.consumer import OUTPOST_GROUP
from authentik.outposts.controllers.base import BaseController, ControllerException from authentik.outposts.controllers.base import BaseController, ControllerException
from authentik.outposts.controllers.docker import DockerClient from authentik.outposts.controllers.docker import DockerClient
from authentik.outposts.controllers.kubernetes import KubernetesClient from authentik.outposts.controllers.kubernetes import KubernetesClient
@ -34,7 +35,6 @@ from authentik.outposts.models import (
Outpost, Outpost,
OutpostModel, OutpostModel,
OutpostServiceConnection, OutpostServiceConnection,
OutpostState,
OutpostType, OutpostType,
ServiceConnectionInvalid, ServiceConnectionInvalid,
) )
@ -243,10 +243,9 @@ def _outpost_single_update(outpost: Outpost, layer=None):
outpost.build_user_permissions(outpost.user) outpost.build_user_permissions(outpost.user)
if not layer: # pragma: no cover if not layer: # pragma: no cover
layer = get_channel_layer() layer = get_channel_layer()
for state in OutpostState.for_outpost(outpost): group = OUTPOST_GROUP % {"outpost_pk": str(outpost.pk)}
for channel in state.channel_ids: LOGGER.debug("sending update", channel=group, outpost=outpost)
LOGGER.debug("sending update", channel=channel, instance=state.uid, outpost=outpost) async_to_sync(layer.group_send)(group, {"type": "event.update"})
async_to_sync(layer.send)(channel, {"type": "event.update"})
@CELERY_APP.task( @CELERY_APP.task(
@ -279,7 +278,7 @@ def outpost_connection_discovery(self: MonitoredTask):
with kubeconfig_path.open("r", encoding="utf8") as _kubeconfig: with kubeconfig_path.open("r", encoding="utf8") as _kubeconfig:
KubernetesServiceConnection.objects.create( KubernetesServiceConnection.objects.create(
name=kubeconfig_local_name, name=kubeconfig_local_name,
kubeconfig=yaml.safe_load(_kubeconfig), kubeconfig=safe_load(_kubeconfig),
) )
unix_socket_path = urlparse(DEFAULT_UNIX_SOCKET).path unix_socket_path = urlparse(DEFAULT_UNIX_SOCKET).path
socket = Path(unix_socket_path) socket = Path(unix_socket_path)

View file

@ -2,11 +2,13 @@
from django.urls import reverse from django.urls import reverse
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
from authentik.blueprints.tests import reconcile_app
from authentik.core.models import PropertyMapping from authentik.core.models import PropertyMapping
from authentik.core.tests.utils import create_test_admin_user, create_test_flow from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.lib.generators import generate_id from authentik.lib.generators import generate_id
from authentik.outposts.api.outposts import OutpostSerializer from authentik.outposts.api.outposts import OutpostSerializer
from authentik.outposts.models import OutpostType, default_outpost_config from authentik.outposts.apps import MANAGED_OUTPOST
from authentik.outposts.models import Outpost, OutpostType, default_outpost_config
from authentik.providers.ldap.models import LDAPProvider from authentik.providers.ldap.models import LDAPProvider
from authentik.providers.proxy.models import ProxyProvider from authentik.providers.proxy.models import ProxyProvider
@ -22,7 +24,36 @@ class TestOutpostServiceConnectionsAPI(APITestCase):
self.user = create_test_admin_user() self.user = create_test_admin_user()
self.client.force_login(self.user) self.client.force_login(self.user)
def test_outpost_validaton(self): @reconcile_app("authentik_outposts")
def test_managed_name_change(self):
"""Test name change for embedded outpost"""
embedded_outpost = Outpost.objects.filter(managed=MANAGED_OUTPOST).first()
self.assertIsNotNone(embedded_outpost)
response = self.client.patch(
reverse("authentik_api:outpost-detail", kwargs={"pk": embedded_outpost.pk}),
{"name": "foo"},
)
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content, {"name": ["Embedded outpost's name cannot be changed"]}
)
@reconcile_app("authentik_outposts")
def test_managed_without_managed(self):
"""Test name change for embedded outpost"""
embedded_outpost = Outpost.objects.filter(managed=MANAGED_OUTPOST).first()
self.assertIsNotNone(embedded_outpost)
embedded_outpost.managed = ""
embedded_outpost.save()
response = self.client.patch(
reverse("authentik_api:outpost-detail", kwargs={"pk": embedded_outpost.pk}),
{"name": "foo"},
)
self.assertEqual(response.status_code, 200)
embedded_outpost.refresh_from_db()
self.assertEqual(embedded_outpost.managed, MANAGED_OUTPOST)
def test_outpost_validation(self):
"""Test Outpost validation""" """Test Outpost validation"""
valid = OutpostSerializer( valid = OutpostSerializer(
data={ data={

View file

@ -7,7 +7,7 @@ from django.test import TransactionTestCase
from authentik import __version__ from authentik import __version__
from authentik.core.tests.utils import create_test_flow from authentik.core.tests.utils import create_test_flow
from authentik.outposts.channels import WebsocketMessage, WebsocketMessageInstruction from authentik.outposts.consumer import WebsocketMessage, WebsocketMessageInstruction
from authentik.outposts.models import Outpost, OutpostType from authentik.outposts.models import Outpost, OutpostType
from authentik.providers.proxy.models import ProxyProvider from authentik.providers.proxy.models import ProxyProvider
from authentik.root import websocket from authentik.root import websocket

View file

@ -7,7 +7,7 @@ from authentik.outposts.api.service_connections import (
KubernetesServiceConnectionViewSet, KubernetesServiceConnectionViewSet,
ServiceConnectionViewSet, ServiceConnectionViewSet,
) )
from authentik.outposts.channels import OutpostConsumer from authentik.outposts.consumer import OutpostConsumer
from authentik.root.middleware import ChannelsLoggingMiddleware from authentik.root.middleware import ChannelsLoggingMiddleware
websocket_urlpatterns = [ websocket_urlpatterns = [

View file

@ -7,7 +7,11 @@ GAUGE_POLICIES_CACHED = Gauge(
"authentik_policies_cached", "authentik_policies_cached",
"Cached Policies", "Cached Policies",
) )
HIST_POLICIES_ENGINE_TOTAL_TIME = Histogram(
"authentik_policies_engine_time_total_seconds",
"(Total) Duration the policy engine took to evaluate a result.",
["obj_type", "obj_pk"],
)
HIST_POLICIES_EXECUTION_TIME = Histogram( HIST_POLICIES_EXECUTION_TIME = Histogram(
"authentik_policies_execution_time", "authentik_policies_execution_time",
"Execution times for single policies", "Execution times for single policies",
@ -17,6 +21,7 @@ HIST_POLICIES_EXECUTION_TIME = Histogram(
"binding_target_name", "binding_target_name",
"object_pk", "object_pk",
"object_type", "object_type",
"mode",
], ],
) )

View file

@ -1,6 +1,7 @@
"""authentik policy engine""" """authentik policy engine"""
from multiprocessing import Pipe, current_process from multiprocessing import Pipe, current_process
from multiprocessing.connection import Connection from multiprocessing.connection import Connection
from timeit import default_timer
from typing import Iterator, Optional from typing import Iterator, Optional
from django.core.cache import cache from django.core.cache import cache
@ -10,6 +11,8 @@ 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.lib.utils.reflection import class_to_path
from authentik.policies.apps import HIST_POLICIES_ENGINE_TOTAL_TIME, HIST_POLICIES_EXECUTION_TIME
from authentik.policies.exceptions import PolicyEngineException from authentik.policies.exceptions import PolicyEngineException
from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel, PolicyEngineMode from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel, PolicyEngineMode
from authentik.policies.process import PolicyProcess, cache_key from authentik.policies.process import PolicyProcess, cache_key
@ -77,6 +80,33 @@ class PolicyEngine:
if binding.policy is not None and binding.policy.__class__ == Policy: if binding.policy is not None and binding.policy.__class__ == Policy:
raise PolicyEngineException(f"Policy '{binding.policy}' is root type") raise PolicyEngineException(f"Policy '{binding.policy}' is root type")
def _check_cache(self, binding: PolicyBinding):
if not self.use_cache:
return False
before = default_timer()
key = cache_key(binding, self.request)
cached_policy = cache.get(key, None)
duration = max(default_timer() - before, 0)
if not cached_policy:
return False
self.logger.debug(
"P_ENG: Taking result from cache",
binding=binding,
cache_key=key,
request=self.request,
)
HIST_POLICIES_EXECUTION_TIME.labels(
binding_order=binding.order,
binding_target_type=binding.target_type,
binding_target_name=binding.target_name,
object_pk=str(self.request.obj.pk),
object_type=class_to_path(self.request.obj.__class__),
mode="cache_retrieve",
).observe(duration)
# It's a bit silly to time this, but
self.__cached_policies.append(cached_policy)
return True
def build(self) -> "PolicyEngine": def build(self) -> "PolicyEngine":
"""Build wrapper which monitors performance""" """Build wrapper which monitors performance"""
with ( with (
@ -84,6 +114,10 @@ class PolicyEngine:
op="authentik.policy.engine.build", op="authentik.policy.engine.build",
description=self.__pbm, description=self.__pbm,
) as span, ) as span,
HIST_POLICIES_ENGINE_TOTAL_TIME.labels(
obj_type=class_to_path(self.__pbm.__class__),
obj_pk=str(self.__pbm.pk),
).time(),
): ):
span: Span span: Span
span.set_data("pbm", self.__pbm) span.set_data("pbm", self.__pbm)
@ -92,16 +126,7 @@ class PolicyEngine:
self.__expected_result_count += 1 self.__expected_result_count += 1
self._check_policy_type(binding) self._check_policy_type(binding)
key = cache_key(binding, self.request) if self._check_cache(binding):
cached_policy = cache.get(key, None)
if cached_policy and self.use_cache:
self.logger.debug(
"P_ENG: Taking result from cache",
binding=binding,
cache_key=key,
request=self.request,
)
self.__cached_policies.append(cached_policy)
continue continue
self.logger.debug("P_ENG: Evaluating policy", binding=binding, request=self.request) self.logger.debug("P_ENG: Evaluating policy", binding=binding, request=self.request)
our_end, task_end = Pipe(False) our_end, task_end = Pipe(False)

View file

@ -1,32 +1,10 @@
"""Expression Policy API""" """Expression Policy API"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.policies.api.policies import PolicySerializer from authentik.policies.api.policies import PolicySerializer
from authentik.policies.expression.evaluator import PolicyEvaluator from authentik.policies.expression.evaluator import PolicyEvaluator
from authentik.policies.expression.models import ExpressionPolicy, ExpressionVariable from authentik.policies.expression.models import ExpressionPolicy
class ExpressionVariableSerializer(ModelSerializer):
"""Expression Variable Serializer"""
class Meta:
model = ExpressionVariable
fields = "__all__"
extra_kwargs = {
"managed": {"read_only": True},
}
class ExpressionVariableViewSet(UsedByMixin, ModelViewSet):
"""Expression Variable Viewset"""
queryset = ExpressionVariable.objects.all()
serializer_class = ExpressionVariableSerializer
filterset_fields = "__all__"
ordering = ["name"]
search_fields = ["name"]
class ExpressionPolicySerializer(PolicySerializer): class ExpressionPolicySerializer(PolicySerializer):
@ -40,7 +18,7 @@ class ExpressionPolicySerializer(PolicySerializer):
class Meta: class Meta:
model = ExpressionPolicy model = ExpressionPolicy
fields = PolicySerializer.Meta.fields + ["expression", "variables"] fields = PolicySerializer.Meta.fields + ["expression"]
class ExpressionPolicyViewSet(UsedByMixin, ModelViewSet): class ExpressionPolicyViewSet(UsedByMixin, ModelViewSet):

View file

@ -13,7 +13,7 @@ from authentik.policies.types import PolicyRequest, PolicyResult
LOGGER = get_logger() LOGGER = get_logger()
if TYPE_CHECKING: if TYPE_CHECKING:
from authentik.policies.expression.models import ExpressionPolicy, ExpressionVariable from authentik.policies.expression.models import ExpressionPolicy
class PolicyEvaluator(BaseEvaluator): class PolicyEvaluator(BaseEvaluator):
@ -30,7 +30,6 @@ class PolicyEvaluator(BaseEvaluator):
# update website/docs/expressions/_functions.md # update website/docs/expressions/_functions.md
self._context["ak_message"] = self.expr_func_message self._context["ak_message"] = self.expr_func_message
self._context["ak_user_has_authenticator"] = self.expr_func_user_has_authenticator self._context["ak_user_has_authenticator"] = self.expr_func_user_has_authenticator
self._context["ak_variables"] = {}
def expr_func_message(self, message: str): def expr_func_message(self, message: str):
"""Wrapper to append to messages list, which is returned with PolicyResult""" """Wrapper to append to messages list, which is returned with PolicyResult"""
@ -53,12 +52,6 @@ class PolicyEvaluator(BaseEvaluator):
self._context["ak_client_ip"] = ip_address(get_client_ip(request)) self._context["ak_client_ip"] = ip_address(get_client_ip(request))
self._context["http_request"] = request self._context["http_request"] = request
def set_variables(self, variables: list["ExpressionVariable"]):
"""Update context base on expression policy variables"""
for variable in variables:
variable.reload()
self._context["ak_variables"][variable.name] = variable.value
def handle_error(self, exc: Exception, expression_source: str): def handle_error(self, exc: Exception, expression_source: str):
"""Exception Handler""" """Exception Handler"""
raise PolicyException(exc) raise PolicyException(exc)

View file

@ -1,48 +0,0 @@
# Generated by Django 4.2.5 on 2023-09-29 00:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_policies_expression", "0004_expressionpolicy_authentik_p_policy__fb6feb_idx"),
]
operations = [
migrations.CreateModel(
name="ExpressionVariable",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("created", models.DateTimeField(auto_now_add=True)),
("last_updated", models.DateTimeField(auto_now=True)),
(
"managed",
models.TextField(
default=None,
help_text="Objects that are managed by authentik. These objects are created and updated automatically. This flag only indicates that an object can be overwritten by migrations. You can still modify the objects via the API, but expect changes to be overwritten in a later update.",
null=True,
unique=True,
verbose_name="Managed by authentik",
),
),
("name", models.TextField(unique=True)),
("value", models.TextField()),
],
options={
"verbose_name": "Expression Variable",
"verbose_name_plural": "Expression Variables",
},
),
migrations.AddField(
model_name="expressionpolicy",
name="variables",
field=models.ManyToManyField(
blank=True, to="authentik_policies_expression.expressionvariable"
),
),
]

View file

@ -1,66 +1,18 @@
"""authentik expression Policy Models""" """authentik expression Policy Models"""
from pathlib import Path
from django.db import models from django.db import models
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from rest_framework.serializers import BaseSerializer from rest_framework.serializers import BaseSerializer
from structlog.stdlib import get_logger
from authentik.blueprints.models import ManagedModel
from authentik.lib.config import CONFIG
from authentik.lib.models import CreatedUpdatedModel, SerializerModel
from authentik.policies.expression.evaluator import PolicyEvaluator from authentik.policies.expression.evaluator import PolicyEvaluator
from authentik.policies.models import Policy from authentik.policies.models import Policy
from authentik.policies.types import PolicyRequest, PolicyResult from authentik.policies.types import PolicyRequest, PolicyResult
LOGGER = get_logger()
MANAGED_DISCOVERED = "goauthentik.io/variables/discovered/%s"
class ExpressionVariable(SerializerModel, ManagedModel, CreatedUpdatedModel):
"""Variable that can be given to expression policies"""
name = models.TextField(unique=True)
value = models.TextField()
@property
def serializer(self) -> type[BaseSerializer]:
from authentik.policies.expression.api import ExpressionVariableSerializer
return ExpressionVariableSerializer
def reload(self):
"""Reload a variable from disk if it's managed"""
if self.managed != MANAGED_DISCOVERED % self.name:
return
path = Path(CONFIG.get("variables_discovery_dir")) / Path(self.name)
try:
with open(path, "r", encoding="utf-8") as _file:
body = _file.read()
if body != self.value:
self.value = body
self.save()
except (OSError, ValueError) as exc:
LOGGER.warning(
"Failed to reload variable, continuing anyway",
exc=exc,
file=path,
variable=self.name,
)
class Meta:
verbose_name = _("Expression Variable")
verbose_name_plural = _("Expression Variables")
class ExpressionPolicy(Policy): class ExpressionPolicy(Policy):
"""Execute arbitrary Python code to implement custom checks and validation.""" """Execute arbitrary Python code to implement custom checks and validation."""
expression = models.TextField() expression = models.TextField()
variables = models.ManyToManyField(ExpressionVariable, blank=True)
@property @property
def serializer(self) -> type[BaseSerializer]: def serializer(self) -> type[BaseSerializer]:
from authentik.policies.expression.api import ExpressionPolicySerializer from authentik.policies.expression.api import ExpressionPolicySerializer
@ -76,7 +28,6 @@ class ExpressionPolicy(Policy):
evaluator = PolicyEvaluator(self.name) evaluator = PolicyEvaluator(self.name)
evaluator.policy = self evaluator.policy = self
evaluator.set_policy_request(request) evaluator.set_policy_request(request)
evaluator.set_variables(self.variables)
return evaluator.evaluate(self.expression) return evaluator.evaluate(self.expression)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):

View file

@ -1,86 +0,0 @@
"""Expression tasks"""
from glob import glob
from pathlib import Path
from django.utils.translation import gettext_lazy as _
from structlog.stdlib import get_logger
from watchdog.events import (
FileCreatedEvent,
FileModifiedEvent,
FileSystemEvent,
FileSystemEventHandler,
)
from watchdog.observers import Observer
from authentik.events.monitored_tasks import (
MonitoredTask,
TaskResult,
TaskResultStatus,
prefill_task,
)
from authentik.lib.config import CONFIG
from authentik.policies.expression.models import MANAGED_DISCOVERED, ExpressionVariable
from authentik.root.celery import CELERY_APP
LOGGER = get_logger()
_file_watcher_started = False
@CELERY_APP.task(bind=True, base=MonitoredTask)
@prefill_task
def variable_discovery(self: MonitoredTask):
"""Discover, import and update variables from the filesystem"""
variables = {}
discovered = 0
base_path = Path(CONFIG.get("variables_discovery_dir")).absolute()
for file in glob(str(base_path) + "/**", recursive=True):
path = Path(file)
if not path.exists():
continue
if path.is_dir():
continue
try:
with open(path, "r", encoding="utf-8") as _file:
body = _file.read()
variables[str(path.relative_to(base_path))] = body
discovered += 1
except (OSError, ValueError) as exc:
LOGGER.warning("Failed to open file", exc=exc, file=path)
for name, value in variables.items():
variable = ExpressionVariable.objects.filter(managed=MANAGED_DISCOVERED % name).first()
if not variable:
variable = ExpressionVariable(name=name, managed=MANAGED_DISCOVERED % name)
if variable.value != value:
variable.value = value
variable.save()
self.set_status(
TaskResult(
TaskResultStatus.SUCCESSFUL,
messages=[_("Successfully imported %(count)d files." % {"count": discovered})],
)
)
class VariableEventHandler(FileSystemEventHandler):
"""Event handler for variable events"""
def on_any_event(self, event: FileSystemEvent):
if not isinstance(event, (FileCreatedEvent, FileModifiedEvent)):
return
if event.is_directory:
return
LOGGER.debug("variable file changed, starting discovery", file=event.src_path)
variable_discovery.delay()
def start_variables_watcher():
"""Start variables watcher, if it's not running already."""
# This function might be called twice since it's called on celery startup
# pylint: disable=global-statement
global _file_watcher_started
if _file_watcher_started:
return
observer = Observer()
observer.schedule(VariableEventHandler(), CONFIG.get("variables_discovery_dir"), recursive=True)
observer.start()
_file_watcher_started = True

View file

@ -1,7 +1,4 @@
"""API URLs""" """API URLs"""
from authentik.policies.expression.api import ExpressionPolicyViewSet, ExpressionVariableViewSet from authentik.policies.expression.api import ExpressionPolicyViewSet
api_urlpatterns = [ api_urlpatterns = [("policies/expression", ExpressionPolicyViewSet)]
("policies/expression/variables", ExpressionVariableViewSet),
("policies/expression", ExpressionPolicyViewSet),
]

View file

@ -190,8 +190,8 @@ class Policy(SerializerModel, CreatedUpdatedModel):
verbose_name_plural = _("Policies") verbose_name_plural = _("Policies")
permissions = [ permissions = [
("view_policy_cache", "View Policy's cache metrics"), ("view_policy_cache", _("View Policy's cache metrics")),
("clear_policy_cache", "Clear Policy's cache metrics"), ("clear_policy_cache", _("Clear Policy's cache metrics")),
] ]
class PolicyMeta: class PolicyMeta:

View file

@ -11,6 +11,7 @@ from structlog.stdlib import get_logger
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
from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.reflection import class_to_path
from authentik.policies.apps import HIST_POLICIES_EXECUTION_TIME from authentik.policies.apps import HIST_POLICIES_EXECUTION_TIME
from authentik.policies.exceptions import PolicyException from authentik.policies.exceptions import PolicyException
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
@ -128,9 +129,8 @@ class PolicyProcess(PROCESS_CLASS):
binding_target_type=self.binding.target_type, binding_target_type=self.binding.target_type,
binding_target_name=self.binding.target_name, binding_target_name=self.binding.target_name,
object_pk=str(self.request.obj.pk), object_pk=str(self.request.obj.pk),
object_type=( object_type=class_to_path(self.request.obj.__class__),
f"{self.request.obj._meta.app_label}.{self.request.obj._meta.model_name}" mode="execute_process",
),
).time(), ).time(),
): ):
span: Span span: Span

View file

@ -17,7 +17,7 @@ LOGGER = get_logger()
@receiver(monitoring_set) @receiver(monitoring_set)
def monitoring_set_policies(sender, **kwargs): def monitoring_set_policies(sender, **kwargs):
"""set policy gauges""" """set policy gauges"""
GAUGE_POLICIES_CACHED.set(len(cache.keys(f"{CACHE_PREFIX}_*") or [])) GAUGE_POLICIES_CACHED.set(len(cache.keys(f"{CACHE_PREFIX}*") or []))
@receiver(post_save, sender=Policy) @receiver(post_save, sender=Policy)

View file

@ -0,0 +1,27 @@
# Generated by Django 5.0 on 2023-12-22 23:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_oauth2", "0016_alter_refreshtoken_token"),
]
operations = [
migrations.AddField(
model_name="accesstoken",
name="session_id",
field=models.CharField(blank=True, default=""),
),
migrations.AddField(
model_name="authorizationcode",
name="session_id",
field=models.CharField(blank=True, default=""),
),
migrations.AddField(
model_name="refreshtoken",
name="session_id",
field=models.CharField(blank=True, default=""),
),
]

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